Browse Source

feat: 未完成任务移交

zhouhanwei 8 months ago
commit
9d57ac00a8
100 changed files with 6711 additions and 0 deletions
  1. 9 0
      .gitignore
  2. 21 0
      README.md
  3. 64 0
      admin/admin-swagger/pom.xml
  4. 13 0
      admin/admin-swagger/src/main/java/com/thinkunion/smart/park/admin/swagger/SwaggerApplication.java
  5. 50 0
      admin/admin-swagger/src/main/resources/application-dev.yml
  6. 7 0
      admin/admin-swagger/src/main/resources/application.yml
  7. 19 0
      admin/pom.xml
  8. 115 0
      api-gateway/pom.xml
  9. 19 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/CoreGateWayApplication.java
  10. 66 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/config/ErrorHandlerConfiguration.java
  11. 58 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/config/RouterFunctionConfiguration.java
  12. 74 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/DynamicRouteService.java
  13. 75 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/DynamicRouteServiceListener.java
  14. 17 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayFilter.java
  15. 17 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayPredicate.java
  16. 27 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayRoute.java
  17. 162 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/AuthFilter.java
  18. 86 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/GlobalRequestLogFilter.java
  19. 80 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/GlobalResponseLogFilter.java
  20. 129 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/MiniProgramAuthFilter.java
  21. 48 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/RequestFilter.java
  22. 67 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/handler/ErrorExceptionHandler.java
  23. 19 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/props/AuthProperties.java
  24. 80 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/AuthProvider.java
  25. 25 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/RequestProvider.java
  26. 38 0
      api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/ResponseProvider.java
  27. 10 0
      api-gateway/src/main/resources/application-dev.yml
  28. 34 0
      api-gateway/src/main/resources/bootstrap.yml
  29. 28 0
      common/constant-common/pom.xml
  30. 236 0
      common/constant-common/src/main/java/com/thinkunion/park/service/common/cache/CacheNames.java
  31. 46 0
      common/constant-common/src/main/java/com/thinkunion/park/service/common/constant/CommonConstant.java
  32. 32 0
      common/constant-common/src/main/java/com/thinkunion/park/service/common/constant/TenantConstant.java
  33. 73 0
      common/launcher/pom.xml
  34. 133 0
      common/launcher/src/main/java/org/nest/springwrap/launcher/LauncherConstant.java
  35. 46 0
      common/launcher/src/main/java/org/nest/springwrap/launcher/LauncherServiceImpl.java
  36. 35 0
      common/miniprogram-common/pom.xml
  37. 165 0
      common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/auth/MiniprogramAuthUtil.java
  38. 20 0
      common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/constants/LoginConstants.java
  39. 32 0
      common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxLoginVo.java
  40. 53 0
      common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxSaasCompanyVo.java
  41. 73 0
      common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxSaasUserVo.java
  42. 98 0
      common/park-common/pom.xml
  43. 118 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/baseentity/MenuTypeEnum.java
  44. 16 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/constant/GroupAction.java
  45. 46 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/constant/PKCONSTANT.java
  46. 280 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/constant/ParkingConstant.java
  47. 26 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/BasicEntity.java
  48. 130 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/EnterPassTicket.java
  49. 216 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/ExitPassTicket.java
  50. 27 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/ParkEntity.java
  51. 148 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/PassTicket.java
  52. 30 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/Row4LedAbility.java
  53. 15 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/entity/VideoAbility.java
  54. 40 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ActiveStateEnum.java
  55. 44 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/AppEnum.java
  56. 38 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/AppPrivacyEnum.java
  57. 39 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ApplySourceEnum.java
  58. 43 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CarTypeEnum.java
  59. 40 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CerStatusEnum.java
  60. 45 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ChargePlaceEnum.java
  61. 44 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ChargeRuleEnum.java
  62. 26 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CouponEnum.java
  63. 28 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CouponStatusEnum.java
  64. 39 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/DeptApplySourceEnum.java
  65. 40 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/DiscountTypeEnum.java
  66. 40 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/EnergyTypeEnum.java
  67. 46 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/GateLedContentEnum.java
  68. 22 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/GateVoiceContentEnum.java
  69. 50 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/NumberEnum.java
  70. 38 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkBillLogExceptionTypeEnum.java
  71. 52 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkIdEnum.java
  72. 42 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkingBillExceptionTypeEnum.java
  73. 71 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkingCarEventEnum.java
  74. 69 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PassRuleEnum.java
  75. 25 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PayTypeEnum.java
  76. 48 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PlaceUsedTypeEnum.java
  77. 60 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ProportionEnum.java
  78. 67 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ReviewStateEnum.java
  79. 73 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/TicketCauseContent.java
  80. 39 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/VehicleGroupEnum.java
  81. 39 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/VehicleTypeEnum.java
  82. 21 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/WeiXinMessageEnum.java
  83. 47 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/enums/wechat/OfficialTempEnum.java
  84. 132 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/api/DeviceBasicData.java
  85. 117 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/discovery/DiscoveryResponsePayload.java
  86. 122 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/CommonRequestPayload.java
  87. 47 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/CommonResponsePayload.java
  88. 136 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/KeyValuePair.java
  89. 351 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/ValueWrapper.java
  90. 32 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Arg.java
  91. 114 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DataType.java
  92. 114 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DataTypeBak.java
  93. 340 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DeviceModel.java
  94. 74 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Event.java
  95. 6 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/GetService.java
  96. 6 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/NormalService.java
  97. 24 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Profile.java
  98. 70 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Property.java
  99. 138 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Service.java
  100. 22 0
      common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/loader/DeviceModelSerializer.java

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+### Example user template template
+### Example user template
+
+# IntelliJ project files
+.idea
+*.iml
+out
+gen
+*target/

+ 21 - 0
README.md

@@ -0,0 +1,21 @@
+├── common // 公共依赖
+
+│   ├── launcher
+
+│   ├── park-common
+
+├── consumer // 消费者(公众号)
+
+│   ├── consumer-feign-api // 消费端提供的接口
+
+│   ├── consumer-service // 消费者核心代码
+
+├── core // 智慧园区中心服务
+
+│   ├── core-feign-api // 智慧园区提供的接口
+
+│   ├── core-service // 智慧园区核心代码
+
+├── core-gateway // 智慧园区网关
+
+└── swagger // 接口文档

+ 64 - 0
admin/admin-swagger/pom.xml

@@ -0,0 +1,64 @@
+<?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">
+    <parent>
+        <artifactId>admin</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>admin-swagger</artifactId>
+    <dependencies>
+
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>launcher</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>core-cloud</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-aggregation-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-metrics</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.4.1</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 13 - 0
admin/admin-swagger/src/main/java/com/thinkunion/smart/park/admin/swagger/SwaggerApplication.java

@@ -0,0 +1,13 @@
+package com.thinkunion.smart.park.admin.swagger;
+
+import org.nest.springwrap.core.launch.NestApplication;
+import org.nest.springwrap.core.launch.app.AppNameConstant;
+import org.springframework.cloud.client.SpringCloudApplication;
+
+@SpringCloudApplication
+public class SwaggerApplication {
+
+    public static void main(String[] args) {
+        NestApplication.run(AppNameConstant.ADMIN_SWAGGER, SwaggerApplication.class, args);
+    }
+}

+ 50 - 0
admin/admin-swagger/src/main/resources/application-dev.yml

@@ -0,0 +1,50 @@
+knife4j:
+  cloud:
+    routes:
+      #  - name: 园区中心服务
+      #   uri: 192.168.8.222:7777
+      #   location: /core-service/v2/api-docs
+
+      - name: saasPark
+        uri: 127.0.0.1:6721
+        location: /v2/api-docs
+
+      - name: appPark
+        uri: 127.0.0.1:6701
+        location: /v2/api-docs
+
+      - name: park
+        uri: 127.0.0.1:6730
+        location: /v2/api-docs
+
+      - name: saas-visitor
+        uri: 127.0.0.1:6717
+        location: /v2/api-docs
+
+      - name: saas-auth
+        uri: 127.0.0.1:6700
+        location: /v2/api-docs
+
+      - name: saas-integration-service
+        uri: 127.0.0.1:6711
+        location: /v2/api-docs
+
+      - name: saas-integration-isc
+        uri: 127.0.0.1:6718
+        location: /v2/api-docs
+      - name: saas-Consumer
+        uri: 127.0.0.1:6716
+        location: /v2/api-docs
+
+      - name: saas-system
+        uri: 127.0.0.1:6731
+        location: /v2/api-docs
+
+      - name: saas-user
+        uri: 127.0.0.1:6702
+        location: /v2/api-docs
+
+      - name: saas-torch
+        uri: 127.0.0.1:6725
+        location: /v2/api-docs
+

+ 7 - 0
admin/admin-swagger/src/main/resources/application.yml

@@ -0,0 +1,7 @@
+server:
+  port: 9021
+knife4j:
+  enableAggregation: true
+  cloud:
+    enable: true
+  enable: true

+ 19 - 0
admin/pom.xml

@@ -0,0 +1,19 @@
+<?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">
+    <parent>
+        <artifactId>smart-park-integration</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
+    <artifactId>admin</artifactId>
+
+    <modules>
+        <module>admin-swagger</module>
+    </modules>
+
+
+</project>

+ 115 - 0
api-gateway/pom.xml

@@ -0,0 +1,115 @@
+<?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">
+    <parent>
+        <artifactId>smart-park-integration</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>api-gateway</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!--Base-->
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>launcher</artifactId>
+            <version>1.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-web</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-undertow</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-metrics</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-jwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <!--Spring-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.codecentric</groupId>
+            <artifactId>spring-boot-admin-starter-client</artifactId>
+        </dependency>
+        <!--Hystrix-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- Nacos -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-redis</artifactId>
+            <exclusions>
+<!--                <exclusion>-->
+<!--                    <groupId>org.nest.springwrap</groupId>-->
+<!--                    <artifactId>starter-jwt</artifactId>-->
+<!--                </exclusion>-->
+                <exclusion>
+                    <groupId>org.nest.springwrap</groupId>
+                    <artifactId>core-tool</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>constant-common</artifactId>
+        </dependency>
+        <!--        <dependency>-->
+        <!--            <groupId>org.nest.springwrap</groupId>-->
+        <!--            <artifactId>starter-zipkin</artifactId>-->
+        <!--        </dependency>-->
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 19 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/CoreGateWayApplication.java

@@ -0,0 +1,19 @@
+package com.thinkunion.smart.park.core.gateway;
+
+import org.nest.springwrap.core.launch.app.AppNameConstant;
+import org.nest.springwrap.core.launch.NestApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.cloud.netflix.hystrix.EnableHystrix;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+
+@EnableHystrix
+@EnableScheduling
+@SpringCloudApplication
+public class CoreGateWayApplication {
+
+    public static void main(String[] args) {
+        NestApplication.run(AppNameConstant.CORE_GATEWAY, CoreGateWayApplication.class, args);
+    }
+
+}

+ 66 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/config/ErrorHandlerConfiguration.java

@@ -0,0 +1,66 @@
+package com.thinkunion.smart.park.core.gateway.config;
+
+
+import com.thinkunion.smart.park.core.gateway.handler.ErrorExceptionHandler;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.web.reactive.result.view.ViewResolver;
+
+import java.util.Collections;
+import java.util.List;
+
+
+@Configuration
+@AutoConfigureBefore(ErrorWebFluxAutoConfiguration.class)
+@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
+public class ErrorHandlerConfiguration {
+
+    private final ServerProperties serverProperties;
+
+    private final ApplicationContext applicationContext;
+
+    private final ResourceProperties resourceProperties;
+
+    private final List<ViewResolver> viewResolvers;
+
+    private final ServerCodecConfigurer serverCodecConfigurer;
+
+    public ErrorHandlerConfiguration(ServerProperties serverProperties,
+                                     ResourceProperties resourceProperties,
+                                     ObjectProvider<List<ViewResolver>> viewResolversProvider,
+                                     ServerCodecConfigurer serverCodecConfigurer,
+                                     ApplicationContext applicationContext) {
+        this.serverProperties = serverProperties;
+        this.applicationContext = applicationContext;
+        this.resourceProperties = resourceProperties;
+        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
+        this.serverCodecConfigurer = serverCodecConfigurer;
+    }
+
+    @Bean
+    @Order(Ordered.HIGHEST_PRECEDENCE)
+    public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
+        ErrorExceptionHandler exceptionHandler = new ErrorExceptionHandler(
+                errorAttributes,
+                this.resourceProperties,
+                this.serverProperties.getError(),
+                this.applicationContext);
+        exceptionHandler.setViewResolvers(this.viewResolvers);
+        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
+        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
+        return exceptionHandler;
+    }
+
+}

+ 58 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/config/RouterFunctionConfiguration.java

@@ -0,0 +1,58 @@
+package com.thinkunion.smart.park.core.gateway.config;
+
+import com.thinkunion.smart.park.core.gateway.props.AuthProperties;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.cors.reactive.CorsUtils;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+
+
+@Slf4j
+@Configuration
+@AllArgsConstructor
+@EnableConfigurationProperties({AuthProperties.class})
+public class RouterFunctionConfiguration {
+
+
+    private static final String ALLOWED_HEADERS = "X-Requested-With, Tenant-Id, Nest-Auth, Content-Type, " +
+            "Authorization, credential, X-XSRF-TOKEN, token, username, client";
+    private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
+    private static final String ALLOWED_ORIGIN = "*";
+    private static final String ALLOWED_EXPOSE = "*";
+    private static final String MAX_AGE = "18000L";
+
+
+    @Bean
+    public WebFilter corsFilter() {
+        return (ServerWebExchange ctx, WebFilterChain chain) -> {
+            ServerHttpRequest request = ctx.getRequest();
+            if (CorsUtils.isCorsRequest(request)) {
+                ServerHttpResponse response = ctx.getResponse();
+                HttpHeaders headers = response.getHeaders();
+                headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
+                headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
+                headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
+                headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
+                headers.add("Access-Control-Max-Age", MAX_AGE);
+                headers.add("Access-Control-Allow-Credentials", "true");
+                if (request.getMethod() == HttpMethod.OPTIONS) {
+                    response.setStatusCode(HttpStatus.OK);
+                    return Mono.empty();
+                }
+            }
+            return chain.filter(ctx);
+        };
+    }
+
+}

+ 74 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/DynamicRouteService.java

@@ -0,0 +1,74 @@
+package com.thinkunion.smart.park.core.gateway.dynamic;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
+import org.springframework.cloud.gateway.route.RouteDefinition;
+import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+@Slf4j
+@Service
+public class DynamicRouteService implements ApplicationEventPublisherAware {
+
+    private final RouteDefinitionWriter routeDefinitionWriter;
+
+    private ApplicationEventPublisher publisher;
+
+    public DynamicRouteService(RouteDefinitionWriter routeDefinitionWriter) {
+        this.routeDefinitionWriter = routeDefinitionWriter;
+    }
+
+    @Override
+    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+        this.publisher = applicationEventPublisher;
+    }
+
+
+    public String save(RouteDefinition definition) {
+        try {
+            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
+            this.publisher.publishEvent(new RefreshRoutesEvent(this));
+            return "save success";
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            return "save failure";
+        }
+    }
+
+
+    public String update(RouteDefinition definition) {
+        try {
+            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
+            this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
+            this.publisher.publishEvent(new RefreshRoutesEvent(this));
+            return "update success";
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            return "update failure";
+        }
+    }
+
+
+    public String updateList(List<RouteDefinition> routeDefinitions) {
+        routeDefinitions.forEach(this::update);
+        return "update done";
+    }
+
+
+    public String delete(String id) {
+        try {
+            this.routeDefinitionWriter.delete(Mono.just(id));
+            return "delete success";
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            return "delete failure";
+        }
+    }
+
+
+}

+ 75 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/DynamicRouteServiceListener.java

@@ -0,0 +1,75 @@
+package com.thinkunion.smart.park.core.gateway.dynamic;
+
+import com.alibaba.cloud.nacos.NacosConfigProperties;
+import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import lombok.extern.slf4j.Slf4j;
+import org.nest.springwrap.core.launch.constant.NacosConstant;
+import org.nest.springwrap.core.launch.props.NestProperties;
+import org.springframework.cloud.gateway.route.RouteDefinition;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+
+@Order
+@Slf4j
+@Component
+public class DynamicRouteServiceListener {
+
+    private final DynamicRouteService dynamicRouteService;
+    private final NacosDiscoveryProperties nacosDiscoveryProperties;
+    private final NacosConfigProperties nacosConfigProperties;
+    private final NestProperties nestProperties;
+
+    public DynamicRouteServiceListener(DynamicRouteService dynamicRouteService,
+                                       NacosDiscoveryProperties nacosDiscoveryProperties,
+                                       NacosConfigProperties nacosConfigProperties, NestProperties nestProperties) {
+        this.dynamicRouteService = dynamicRouteService;
+        this.nacosDiscoveryProperties = nacosDiscoveryProperties;
+        this.nacosConfigProperties = nacosConfigProperties;
+        this.nestProperties = nestProperties;
+        dynamicRouteServiceListener();
+    }
+
+
+    private void dynamicRouteServiceListener() {
+        try {
+            String dataId = NacosConstant
+                    .dataId(nestProperties.getName(), nestProperties.getEnv(), NacosConstant.NACOS_CONFIG_JSON_FORMAT);
+            String group = nacosConfigProperties.getGroup();
+            Properties properties = new Properties();
+            properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());
+            properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDiscoveryProperties.getNamespace());
+            ConfigService configService = NacosFactory.createConfigService(properties);
+            configService.addListener(dataId, group, new Listener() {
+                @Override
+                public void receiveConfigInfo(String configInfo) {
+                    List<RouteDefinition> routeDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
+                    dynamicRouteService.updateList(routeDefinitions);
+                }
+
+                @Override
+                public Executor getExecutor() {
+                    return null;
+                }
+            });
+            String configInfo = configService.getConfig(dataId, group, 5000);
+            if (configInfo != null) {
+                List<RouteDefinition> routeDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
+                dynamicRouteService.updateList(routeDefinitions);
+            }
+        } catch (NacosException ignored) {
+
+        }
+    }
+
+}

+ 17 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayFilter.java

@@ -0,0 +1,17 @@
+package com.thinkunion.smart.park.core.gateway.dynamic;
+
+import lombok.Data;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+@Data
+public class GatewayFilter {
+
+
+    private String name;
+
+
+    private Map<String, String> args = new LinkedHashMap<>();
+}

+ 17 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayPredicate.java

@@ -0,0 +1,17 @@
+package com.thinkunion.smart.park.core.gateway.dynamic;
+
+import lombok.Data;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+@Data
+public class GatewayPredicate {
+
+
+    private String name;
+
+
+    private Map<String, String> args = new LinkedHashMap<>();
+}

+ 27 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/dynamic/GatewayRoute.java

@@ -0,0 +1,27 @@
+package com.thinkunion.smart.park.core.gateway.dynamic;
+
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Data
+public class GatewayRoute {
+
+
+    private String id;
+
+
+    private List<GatewayPredicate> predicates = new ArrayList<>();
+
+
+    private List<GatewayFilter> filters = new ArrayList<>();
+
+
+    private String uri;
+
+
+    private int order = 0;
+}

+ 162 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/AuthFilter.java

@@ -0,0 +1,162 @@
+package com.thinkunion.smart.park.core.gateway.filter;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.thinkunion.park.service.common.cache.CacheNames;
+import com.thinkunion.smart.park.core.gateway.props.AuthProperties;
+import com.thinkunion.smart.park.core.gateway.provider.AuthProvider;
+import com.thinkunion.smart.park.core.gateway.provider.RequestProvider;
+import com.thinkunion.smart.park.core.gateway.provider.ResponseProvider;
+import io.jsonwebtoken.Claims;
+import jodd.util.StringPool;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.nest.springwrap.core.jwt.JwtUtil;
+import org.nest.springwrap.core.jwt.props.JwtProperties;
+import org.nest.springwrap.core.launch.constant.TokenConstant;
+import org.nest.springwrap.core.redis.cache.NestRedis;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.Resource;
+import java.nio.charset.StandardCharsets;
+
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class AuthFilter implements GlobalFilter, Ordered {
+    private final AuthProperties authProperties;
+    private final ObjectMapper objectMapper;
+    private final JwtProperties jwtProperties;
+    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+    @Resource
+    private NestRedis nestRedis;
+
+    /**
+     * 应用id
+     */
+    public static final String APPLY_ID = "Apply-Id";
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        //校验 Token 合法性
+        ServerHttpResponse resp = exchange.getResponse();
+
+        //校验 Token 放行
+        String originalRequestUrl = RequestProvider.getOriginalRequestUrl(exchange);
+        String path = exchange.getRequest().getURI().getPath();
+        if (isSkip(path) || isSkip(originalRequestUrl)) {
+            return chain.filter(exchange);
+        }
+        //校验应用是否存在
+        String headerApplyId = exchange.getRequest().getHeaders().getFirst(APPLY_ID);
+        String paramApplyId = exchange.getRequest().getQueryParams().getFirst(APPLY_ID);
+        if(StringUtils.isNotBlank(headerApplyId) || StringUtils.isNotBlank(paramApplyId)){
+            String applyId = StringUtils.isBlank(headerApplyId) ? paramApplyId : headerApplyId;
+            if(!nestRedis.exists(String.format(CacheNames.APPLY_ID, applyId))){
+                //不存在则不能访问
+                log.info("当前应用服务已停用,请联系管理员!");
+                return unAuth(resp, "当前应用服务已停用,请联系管理员!",HttpStatus.FORBIDDEN);
+            }
+        }else{
+            log.info("没有找到应用id信息!");
+            return unAuth(resp, "没有找到应用信息,请联系管理员",HttpStatus.FORBIDDEN);
+        }
+        if(originalRequestUrl.contains(StringPool.QUESTION_MARK)){
+            String[] split = originalRequestUrl.split(StringPool.BACK_SLASH+StringPool.QUESTION_MARK);
+            originalRequestUrl=split[0];
+        }
+
+        String headerToken = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_KEY);
+        String paramToken = exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_KEY);
+        if (StringUtils.isBlank(headerToken) && StringUtils.isBlank(paramToken)) {
+            return unAuth(resp, "缺失令牌,鉴权失败",HttpStatus.UNAUTHORIZED);
+        }
+        String auth = StringUtils.isBlank(headerToken) ? paramToken : headerToken;
+        String token = JwtUtil.getToken(auth);
+        Claims claims = JwtUtil.parseJWT(token);
+        if (token == null || claims == null) {
+            return unAuth(resp, "请求未授权",HttpStatus.UNAUTHORIZED);
+        }
+        //判断 Token 状态
+        if (jwtProperties.getState()) {
+            String tenantId = String.valueOf(claims.get(TokenConstant.TENANT_ID));
+            String userId = String.valueOf(claims.get(TokenConstant.USER_ID));
+            String accessToken = JwtUtil.getAccessToken(tenantId, userId, token);
+            log.info("accessToken:{}",accessToken);
+            log.info("token:{}",token);
+            if (!token.equalsIgnoreCase(accessToken)) {
+                return unAuth(resp, "令牌已失效",HttpStatus.UNAUTHORIZED);
+            }
+            log.info("************");
+            //rebuild1.0版本 dept有值得话orgUserId必须要有值,否则说明是旧的token让用户重新登录
+            String deptId = String.valueOf(claims.get(TokenConstant.DEPT_ID));
+            if(StringUtils.isNotBlank(deptId)){
+                if(Long.valueOf(deptId)>0){
+                    String str=String.valueOf(claims.get(TokenConstant.ORG_USER_ID));
+                    if (str == null) {
+                        return unAuth(resp, "令牌已失效",HttpStatus.UNAUTHORIZED);
+                    }
+                    try {
+                       Long orgUserId= Long.valueOf(str);
+                       if(orgUserId<=0){
+                           return unAuth(resp, "令牌已失效",HttpStatus.UNAUTHORIZED);
+                       }
+                    } catch (final NumberFormatException nfe) {
+                        return unAuth(resp, "令牌已失效",HttpStatus.UNAUTHORIZED);
+                    }
+                }
+            }
+
+            //获取用户登录后缓存的接口权限集合,
+//            String menuRootStr = JwtUtil.getMenuRoot(tenantId, token);
+//            MenuRoot menuRoot = JSONObject.parseObject(menuRootStr, MenuRoot.class);
+//            String pathUrl = menuRoot.hasPermission(originalRequestUrl);
+//            if(pathUrl==null){
+//                return unAuth(resp, "请求模块未开通授权",HttpStatus.METHOD_NOT_ALLOWED);
+//            }
+//            if(menuRoot.isExpiration(pathUrl)){
+//                return unAuth(resp, "服务已到期",HttpStatus.PAYMENT_REQUIRED);
+//            }
+        }
+
+
+        return chain.filter(exchange);
+    }
+
+    private boolean isSkip(String path) {
+        return AuthProvider.getDefaultSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path))
+                || authProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
+    }
+
+    private Mono<Void> unAuth(ServerHttpResponse resp, String msg,HttpStatus status) {
+        resp.setStatusCode(status);
+        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
+        String result = "";
+        try {
+            result = objectMapper.writeValueAsString(ResponseProvider.response(status.value(),msg));
+        } catch (JsonProcessingException e) {
+            log.error(e.getMessage(), e);
+        }
+        DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
+        return resp.writeWith(Flux.just(buffer));
+    }
+
+
+    @Override
+    public int getOrder() {
+        return -100;
+    }
+
+}

+ 86 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/GlobalRequestLogFilter.java

@@ -0,0 +1,86 @@
+package com.thinkunion.smart.park.core.gateway.filter;
+
+import com.thinkunion.smart.park.core.gateway.provider.AuthProvider;
+import com.thinkunion.smart.park.core.gateway.provider.RequestProvider;
+import io.jsonwebtoken.Claims;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.nest.springwrap.core.jwt.JwtUtil;
+import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Slf4j
+@Configuration
+@RequiredArgsConstructor
+@ConditionalOnProperty(value = "nest.log.request.enabled", havingValue = "true", matchIfMissing = true)
+public class GlobalRequestLogFilter implements GlobalFilter, Ordered {
+    private final WebEndpointProperties endpointProperties;
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        ServerHttpRequest request = exchange.getRequest();
+        // 打印请求路径
+        String path = request.getPath().pathWithinApplication().value();
+
+        // 忽略 endpoint 请求
+        String endpointBasePath = endpointProperties.getBasePath();
+        if (StringUtils.isNotBlank(endpointBasePath) && path.startsWith(endpointBasePath)) {
+            return chain.filter(exchange);
+        }
+
+        String requestUrl = RequestProvider.getOriginalRequestUrl(exchange);
+
+        // 构建成一条长 日志,避免并发下日志错乱
+        StringBuilder beforeReqLog = new StringBuilder(300);
+        // 日志参数
+        List<Object> beforeReqArgs = new ArrayList<>();
+        beforeReqLog.append("\n\n================ Gateway Request Start  ================\n");
+        // 打印路由
+        beforeReqLog.append("===> {}: {}\n");
+        // 参数
+        String requestMethod = request.getMethodValue();
+        beforeReqArgs.add(requestMethod);
+        beforeReqArgs.add(requestUrl);
+
+        // 打印请求头
+        HttpHeaders headers = request.getHeaders();
+        headers.forEach((headerName, headerValue) -> {
+            beforeReqLog.append("===Headers===  {}: {}\n");
+            beforeReqArgs.add(headerName);
+            if (AuthProvider.AUTH_KEY.toLowerCase().equals(headerName)) {
+                String value = headerValue.get(0);
+                String token = JwtUtil.getToken(value);
+                Claims claims = JwtUtil.parseJWT(token);
+                beforeReqArgs.add((claims == null) ? "" : claims.toString());
+                beforeReqLog.append("===Headers===  {}: {}\n");
+                beforeReqArgs.add(headerName.concat("-original"));
+                beforeReqArgs.add(StringUtils.join(headerValue.toArray()));
+            } else {
+                beforeReqArgs.add(StringUtils.join(headerValue.toArray()));
+            }
+        });
+
+        beforeReqLog.append("================  Gateway Request End  =================\n");
+        // 打印执行时间
+        log.info(beforeReqLog.toString(), beforeReqArgs.toArray());
+        return chain.filter(exchange);
+    }
+
+    @Override
+    public int getOrder() {
+        return Ordered.LOWEST_PRECEDENCE;
+    }
+}

+ 80 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/GlobalResponseLogFilter.java

@@ -0,0 +1,80 @@
+package com.thinkunion.smart.park.core.gateway.filter;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Slf4j
+@Configuration
+@RequiredArgsConstructor
+@ConditionalOnProperty(value = "nest.log.request.enabled", havingValue = "true", matchIfMissing = true)
+public class GlobalResponseLogFilter implements GlobalFilter, Ordered {
+    private final WebEndpointProperties endpointProperties;
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        ServerHttpRequest request = exchange.getRequest();
+        // 打印请求路径
+        String path = request.getPath().pathWithinApplication().value();
+        // 忽略 endpoint 请求
+        String endpointBasePath = endpointProperties.getBasePath();
+        if (StringUtils.isNotBlank(endpointBasePath) && path.startsWith(endpointBasePath)) {
+            return chain.filter(exchange);
+        }
+        return chain.filter(exchange).then(
+                Mono.fromRunnable(() -> {
+                    MultiValueMap<String, String> queryParams = request.getQueryParams();
+                    String requestUrl = UriComponentsBuilder.fromPath(path).queryParams(queryParams).build()
+                            .toUriString();
+
+                    // 构建成一条长 日志,避免并发下日志错乱
+                    StringBuilder responseLog = new StringBuilder(300);
+                    // 日志参数
+                    List<Object> responseArgs = new ArrayList<>();
+                    responseLog.append("\n\n================ Gateway Response Start  ================\n");
+                    ServerHttpResponse response = exchange.getResponse();
+                    // 打印路由 200 get: /api/xxx/xxx
+                    responseLog.append("<=== {} {}: {}\n");
+                    // 参数
+                    String requestMethod = request.getMethodValue();
+                    responseArgs.add(response.getStatusCode().value());
+                    responseArgs.add(requestMethod);
+                    responseArgs.add(requestUrl);
+
+                    // 打印请求头
+                    HttpHeaders headers = response.getHeaders();
+                    headers.forEach((headerName, headerValue) -> {
+                        responseLog.append("===Headers===  {}: {}\n");
+                        responseArgs.add(headerName);
+                        responseArgs.add(StringUtils.join(headerValue.toArray()));
+                    });
+
+                    responseLog.append("================  Gateway Response End  =================\n");
+                    // 打印执行时间
+                    log.info(responseLog.toString(), responseArgs.toArray());
+                })
+        );
+    }
+
+    @Override
+    public int getOrder() {
+        return Ordered.HIGHEST_PRECEDENCE;
+    }
+}

+ 129 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/MiniProgramAuthFilter.java

@@ -0,0 +1,129 @@
+package com.thinkunion.smart.park.core.gateway.filter;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.thinkunion.smart.park.core.gateway.provider.RequestProvider;
+import com.thinkunion.smart.park.core.gateway.provider.ResponseProvider;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class MiniProgramAuthFilter implements GlobalFilter, Ordered {
+	@Autowired
+	private RedisTemplate<String,String> redisTemplate;
+	private final ObjectMapper objectMapper;
+	private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+	private static final List<String> DEFAULT_SKIP_URL = new ArrayList<>();
+	static {
+		//****原本的接口暂时不走登录校验
+		//consumer相关接口
+		DEFAULT_SKIP_URL.add("/saas-consumer/invoice/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/parking/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/people/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/RegisterPlate/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/mail/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/test/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/uploadImg/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/vehicle/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/visitor/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/tempMessage/**");
+		DEFAULT_SKIP_URL.add("/saas-consumer/order/pay/**");
+
+		//支付相关接口
+		DEFAULT_SKIP_URL.add("/saas-payment/pay/**");
+		DEFAULT_SKIP_URL.add("/saas-payment/test/**");
+
+		//访客相关接口
+		DEFAULT_SKIP_URL.add("/saas-visitor/hikIsc/**");
+		DEFAULT_SKIP_URL.add("/saas-visitor/visitor/**");
+
+		//**新接口
+		DEFAULT_SKIP_URL.add("/saas-consumer/wechat/auth/**");//登录相关接口不走校验
+		DEFAULT_SKIP_URL.add("/saas-consumer/v2/api-docs/**");//swagger接口不走校验
+	}
+	private static final List<String> DEFAULT_VERIFICATION_URL = new ArrayList<>();
+	static {
+		DEFAULT_VERIFICATION_URL.add("/mini-program/**");//小程序接口走token校验
+	}
+
+	private boolean isVerification(String path) {
+		return DEFAULT_VERIFICATION_URL.stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
+	}
+	private boolean isSkip(String path) {
+		return DEFAULT_SKIP_URL.stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
+	}
+
+
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+//		//校验 Token 放行
+//		String originalRequestUrl = RequestProvider.getOriginalRequestUrl(exchange);
+//		String path = exchange.getRequest().getURI().getPath();
+//
+//		if(isVerification(path)||isVerification(originalRequestUrl)){
+//			if(isSkip(path)||isSkip(originalRequestUrl)){
+//				return chain.filter(exchange);
+//			}else{
+//				log.info("originalRequestUrl:{},path:{}",originalRequestUrl,path);
+//			}
+//		}else {
+//			return chain.filter(exchange);
+//		}
+//
+//		//校验 Token 合法性
+//		ServerHttpResponse resp = exchange.getResponse();
+//		String headerToken = exchange.getRequest().getHeaders().getFirst("Authorization");
+//		if (StringUtils.isBlank(headerToken)) {
+//			return unAuth(resp, "缺失令牌,鉴权失败");
+//		}
+//
+//		String json=redisTemplate.opsForValue().get("wechat:login:"+headerToken);
+//		if(StringUtils.isBlank(json)){
+//			return unAuth(resp, "缺失令牌,鉴权失败");
+//		}
+
+
+		return chain.filter(exchange);
+	}
+
+	private Mono<Void> unAuth(ServerHttpResponse resp, String msg) {
+		resp.setStatusCode(HttpStatus.UNAUTHORIZED);
+		resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
+		String result = "";
+		try {
+			result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
+		} catch (JsonProcessingException e) {
+			log.error(e.getMessage(), e);
+		}
+		DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
+		return resp.writeWith(Flux.just(buffer));
+	}
+
+
+	@Override
+	public int getOrder() {
+		return -100;
+	}
+
+}

+ 48 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/filter/RequestFilter.java

@@ -0,0 +1,48 @@
+package com.thinkunion.smart.park.core.gateway.filter;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
+
+
+@Component
+public class RequestFilter implements GlobalFilter, Ordered {
+
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        // 1. 清洗请求头中from 参数
+        ServerHttpRequest request = exchange.getRequest().mutate()
+                .headers(httpHeaders -> httpHeaders.remove("X"))
+                .build();
+
+        // 2. 重写StripPrefix
+        addOriginalRequestUrl(exchange, request.getURI());
+        String rawPath = request.getURI().getRawPath();
+        String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/"))
+                .skip(1L).collect(Collectors.joining("/"));
+        ServerHttpRequest newRequest = request.mutate()
+                .path(newPath)
+                .build();
+        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
+
+        return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build());
+    }
+
+    @Override
+    public int getOrder() {
+        return -1000;
+    }
+
+}

+ 67 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/handler/ErrorExceptionHandler.java

@@ -0,0 +1,67 @@
+package com.thinkunion.smart.park.core.gateway.handler;
+
+import com.thinkunion.smart.park.core.gateway.provider.ResponseProvider;
+import org.springframework.boot.autoconfigure.web.ErrorProperties;
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.reactive.function.server.*;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.util.Map;
+
+
+public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler {
+
+    public ErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
+                                 ErrorProperties errorProperties, ApplicationContext applicationContext) {
+        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
+    }
+
+
+    @Override
+    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
+        int code = 500;
+        Throwable error = super.getError(request);
+        if (error instanceof NotFoundException) {
+            code = 404;
+        }
+        if (error instanceof ResponseStatusException) {
+            code = ((ResponseStatusException) error).getStatus().value();
+        }
+        return ResponseProvider.response(code, this.buildMessage(request, error));
+    }
+
+
+    @Override
+    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
+        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
+    }
+
+
+    @Override
+    protected int getHttpStatus(Map<String, Object> errorAttributes) {
+        return (int) errorAttributes.get("code");
+    }
+
+
+    private String buildMessage(ServerRequest request, Throwable ex) {
+        String uri = request.uri().toString();
+        if (uri.endsWith("doc.html")) {
+            return "[Swagger聚合网关] 已迁移至 [nest-swagger] 服务,请开启 [nest-swagger] 服务并访问 [http://127.0.0.1:18000/doc.html]";
+        }
+        StringBuilder message = new StringBuilder("Failed to handle request [");
+        message.append(request.methodName());
+        message.append(" ");
+        message.append(request.uri());
+        message.append("]");
+        if (ex != null) {
+            message.append(": ");
+            message.append(ex.getMessage());
+        }
+        return message.toString();
+    }
+
+}

+ 19 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/props/AuthProperties.java

@@ -0,0 +1,19 @@
+package com.thinkunion.smart.park.core.gateway.props;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Data
+@RefreshScope
+@ConfigurationProperties("nest.secure")
+public class AuthProperties {
+
+
+    private final List<String> skipUrl = new ArrayList<>();
+
+}

+ 80 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/AuthProvider.java

@@ -0,0 +1,80 @@
+
+package com.thinkunion.smart.park.core.gateway.provider;
+
+import org.nest.springwrap.core.launch.constant.TokenConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class AuthProvider {
+
+    public static final String AUTH_KEY = TokenConstant.HEADER;
+    private static final List<String> DEFAULT_SKIP_URL = new ArrayList<>();
+
+    static {
+        DEFAULT_SKIP_URL.add("/pms-program/**");//公众号接口不走token校验
+        DEFAULT_SKIP_URL.add("/mini-program/**");//小程序接口不走token校验
+        DEFAULT_SKIP_URL.add("/isc/event/**");//isc事件不走检验
+        DEFAULT_SKIP_URL.add("/example");
+        DEFAULT_SKIP_URL.add("/oauth/token/**");
+        DEFAULT_SKIP_URL.add("/oauth/captcha/**");
+        DEFAULT_SKIP_URL.add("/oauth/clear-cache/**");
+        DEFAULT_SKIP_URL.add("/oauth/user-info");
+        DEFAULT_SKIP_URL.add("/oauth/render");
+        DEFAULT_SKIP_URL.add("/oauth/callback");
+        DEFAULT_SKIP_URL.add("/oauth/revoke");
+        DEFAULT_SKIP_URL.add("/oauth/refresh");
+        DEFAULT_SKIP_URL.add("/token/**");
+        DEFAULT_SKIP_URL.add("/actuator/**");
+        DEFAULT_SKIP_URL.add("/v2/api-docs/**");
+        DEFAULT_SKIP_URL.add("/auth/**");
+        DEFAULT_SKIP_URL.add("/log/**");
+        DEFAULT_SKIP_URL.add("/menu/routes");
+        DEFAULT_SKIP_URL.add("/menu/auth-routes");
+        DEFAULT_SKIP_URL.add("/menu/top-menu");
+        DEFAULT_SKIP_URL.add("/tenant/info");
+        DEFAULT_SKIP_URL.add("/process/resource-view");
+        DEFAULT_SKIP_URL.add("/process/diagram-view");
+        DEFAULT_SKIP_URL.add("/manager/check-upload");
+        DEFAULT_SKIP_URL.add("/error/**");
+        DEFAULT_SKIP_URL.add("/assets/**");
+        DEFAULT_SKIP_URL.add("/charge/order/record"); // 云快充导入充电账单接口
+        DEFAULT_SKIP_URL.add("/sms/send/code");//登录使用的发送验证码接口
+        DEFAULT_SKIP_URL.add("/userInfo/platform/list");//登录使用的平台列表接口
+        DEFAULT_SKIP_URL.add("/dept/list");//登录使用的平台列表接口
+        DEFAULT_SKIP_URL.add("/rebuild/dept/list");//登录使用的平台列表接口
+        DEFAULT_SKIP_URL.add("/sms/verify/code");//登录使用的平台列表接口
+        DEFAULT_SKIP_URL.add("/ue4/**");//ue4相关不走校验
+        DEFAULT_SKIP_URL.add("/sms/verify/code");//登录使用的平台列表接口
+        DEFAULT_SKIP_URL.add("/ue4/**");//ue4相关不走校验
+        DEFAULT_SKIP_URL.add("/parking/infoQuery/getAppearCarListJt");//开放明源接口
+        DEFAULT_SKIP_URL.add("/parkInfo/getJtlist");//开放明源接口
+        DEFAULT_SKIP_URL.add("/mingYuan/getTemporaryPayment");//开放明源接口
+        DEFAULT_SKIP_URL.add("/mingYuan/getTemporaryRefund");//开放明源接口
+        DEFAULT_SKIP_URL.add("/parking/vehicle/monthly/card/getCardListJt");//开放明源接口
+        DEFAULT_SKIP_URL.add("/parking/vehicle/monthly/card/getCardBillListJt");//开放明源接口
+        DEFAULT_SKIP_URL.add("/tenant/getDetail");//获取租户明细接口
+        DEFAULT_SKIP_URL.add("/parkInfo/getAllVisitor");//获取所有园区接口
+        DEFAULT_SKIP_URL.add("/station/app/list");//获取小程序电站列表接口
+        DEFAULT_SKIP_URL.add("/userOauth/captcha");//获取图形验证码
+        DEFAULT_SKIP_URL.add("/userCheck/login");//一次校验登录
+        DEFAULT_SKIP_URL.add("/getUserByPhoneOrEmail");
+        DEFAULT_SKIP_URL.add("/send/code");
+        DEFAULT_SKIP_URL.add("/send/emailCode");
+        DEFAULT_SKIP_URL.add("/verify/code");
+        DEFAULT_SKIP_URL.add("/updatePassword");
+        DEFAULT_SKIP_URL.add("/parkInfo/listAll");//获取不分租户的所有园区接口(小程序用)
+        //优惠券白名单
+        DEFAULT_SKIP_URL.add("/coupon/record/scan/**");
+        DEFAULT_SKIP_URL.add("/coupon/record/receive");
+        //二维码扫码
+        DEFAULT_SKIP_URL.add("/parkNotice/list");
+        DEFAULT_SKIP_URL.add("/parkNotice/getDetail");
+        DEFAULT_SKIP_URL.add("/parkNotice/addViewCount");
+    }
+
+    public static List<String> getDefaultSkipUrl() {
+        return DEFAULT_SKIP_URL;
+    }
+}

+ 25 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/RequestProvider.java

@@ -0,0 +1,25 @@
+package com.thinkunion.smart.park.core.gateway.provider;
+
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.net.URI;
+import java.util.LinkedHashSet;
+
+
+public class RequestProvider {
+
+
+    public static String getOriginalRequestUrl(ServerWebExchange exchange) {
+        ServerHttpRequest request = exchange.getRequest();
+        LinkedHashSet<URI> uris = exchange
+                .getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
+        URI requestUri = uris.stream().findFirst().orElse(request.getURI());
+        MultiValueMap<String, String> queryParams = request.getQueryParams();
+        return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();
+    }
+
+}

+ 38 - 0
api-gateway/src/main/java/com/thinkunion/smart/park/core/gateway/provider/ResponseProvider.java

@@ -0,0 +1,38 @@
+package com.thinkunion.smart.park.core.gateway.provider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class ResponseProvider {
+
+
+    public static Map<String, Object> success(String message) {
+        return response(200, message);
+    }
+
+
+    public static Map<String, Object> fail(String message) {
+        return response(400, message);
+    }
+
+
+    public static Map<String, Object> unAuth(String message) {
+        return response(401, message);
+    }
+
+
+    public static Map<String, Object> error(String message) {
+        return response(500, message);
+    }
+
+
+    public static Map<String, Object> response(int status, String message) {
+        Map<String, Object> map = new HashMap<>(16);
+        map.put("code", status);
+        map.put("msg", message);
+        map.put("data", null);
+        return map;
+    }
+
+}

+ 10 - 0
api-gateway/src/main/resources/application-dev.yml

@@ -0,0 +1,10 @@
+nest:
+  #多团队协作服务配置
+  ribbon:
+    rule:
+      #开启配置
+      enabled: true
+      #负载均衡优先调用的ip段
+      prior-ip-pattern:
+        - 127.0.0.1
+        - 192.168.8.*

+ 34 - 0
api-gateway/src/main/resources/bootstrap.yml

@@ -0,0 +1,34 @@
+server:
+  port: 6777
+
+spring:
+  cloud:
+    discovery:
+      reactive:
+        enabled: false
+    gateway:
+      discovery:
+        locator:
+          enabled: true
+      routes:
+        - id: service_consumer
+          uri: lb://saas-consumer
+          predicates:
+            - Path= /mini-program/saas-consumer/**
+          filters:
+            - StripPrefix=1
+        - id: service_visitor
+          uri: lb://saas-visitor
+          predicates:
+            - Path= /mini-program/saas-visitor/**
+          filters:
+            - StripPrefix=1
+        - id: service_payment
+          uri: lb://saas-payment
+          predicates:
+            - Path= /mini-program/saas-payment/**
+          filters:
+            - StripPrefix=1
+    loadbalancer:
+      retry:
+        enabled: true

+ 28 - 0
common/constant-common/pom.xml

@@ -0,0 +1,28 @@
+<?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">
+    <parent>
+        <artifactId>common</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>constant-common</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>launcher</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.4.1</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 236 - 0
common/constant-common/src/main/java/com/thinkunion/park/service/common/cache/CacheNames.java

@@ -0,0 +1,236 @@
+package com.thinkunion.park.service.common.cache;
+
+
+public interface CacheNames {
+
+    String ANONYMOUS_PLATE_NO_CHECK = "car:anonymous:check:";
+
+    /**
+     * 用于缓存的key为  CAPTCHA_KEY+车牌号+道闸
+     * 作用于临闸缴费 下发开闸控制
+     */
+    String CAPTCHA_KEY = "nest:auth::nest:captcha:";
+
+    String TENANT_CAPTCHA_KEY = "nest:auth::nest:captcha:%s:%s";
+
+    String CAPTCHA_KEY_TIMES = "nest:auth:%s:nest:captcha:times:%s";
+
+    /**
+     * 作用于缓存 放行规则返回的数据
+     * CAR_RULE_KEY+车牌号
+     */
+    String CAR_RULE_KEY = "car:auth::nest:plateNo:";
+
+    /**
+     * 作用域缓存 无牌车放行规则返回的数据
+     * CAR_NO_PLATE_RULE_KEY + 事件Id
+     */
+    String ANONYMOUS_PLATE_RULE_KEY = "car:auth::nest:no:plateNo:event:";
+    /**
+     * 作用于车辆入场保存一条过车记录
+     * CAR_LOG_IN_KEY+parkingId+roadwayId
+     */
+    String CAR_LOG_IN_KEY = "car:auth::nest:log:in:";
+
+    /**
+     * 作用于车辆出场保存一条过车记录
+     * CAR_LOG_OUT_KEY+parkingId+roadwayId
+     */
+    String CAR_LOG_OUT_KEY = "car:auth::nest:log:out:";
+
+    String ROADWAY_NO_PLATE_NO_ID = "car:auth::nest:no:plate:";
+
+    /**
+     * 用于缓存停车场的月卡数据
+     * MONTHLY_BILL_KEY+parkingId
+     */
+    String MONTHLY_BILL_KEY = "car:auth::nest:monthlyBill:";
+
+    /**
+     * 用于缓存当前停车场下的所有的道闸信息
+     * <p>
+     * PARKING_ROADWAY_OUT_KEY + parkingId
+     */
+    String PARKING_ROADWAY_OUT_KEY = "parking:auth::nest:roadway:";
+
+    /**
+     * 用于缓存当前停车场下的所有的道闸信息
+     * <p>
+     * PARKING_EVENT_ID + (eventCmd + eventIndex)
+     */
+    String PARKING_EVENT_ID = "parking:auth::nest:event:";
+
+    /**
+     * 用于缓存当前停车场下设备+车牌号的事件
+     * <p>
+     * PARKING_PLATENO_DEVICENAME + (plateNo + deviceName)
+     */
+    String PARKING_DEVICENAME_PLATENO = "parking:deviceName::plateNo";
+
+    /**
+     * 用于缓存厦门银行XCPay支付信息
+     */
+    String PARK_PAY_XCPAY = "park:pay:xcpay:";
+
+    /**
+     * 用于缓存停车场数据信息
+     */
+    String PARK_PARKING_EXTEND = "park:parking:extend:";
+    /**
+     * 用于缓存访客车信息
+     */
+    String VISITOR_CAR_INFO = "park:parking:visitor:";
+
+    /**
+     * 用于缓存停车场免费车辆
+     */
+    String PARK_PARKING_QRCODE_FREE = "park:parking:qrcode:free:";
+
+    /**
+     * 是否开启人脸
+     */
+    String OPEN_FACE = "park:visitor:open:face";
+
+
+    /**
+     * 缓存设备信息的redis_key前缀
+     **/
+    String DEVICE_PRO_PREFIX = "park:device:";
+
+
+    /**
+     * 缓存计算值整体前缀
+     */
+    String DEVICE_STATISTIC_CASH_KEY = "park:device:statistic:";
+
+    /**
+     * 缓存计算值的能耗统计前缀
+     */
+    String DEVICE_COUNT_CASH_KEY = "park:device:statistic:count:";
+    /**
+     * 趋势数据缓存
+     */
+    String DEVICE_TREND_CASH_KEY = "park:device:statistic:trend:";
+    /**
+     * 排名数据缓存
+     */
+    String DEVICE_RANK_CASH_KEY = "park:device:statistic:rank:";
+    /**
+     * 最新数据缓存key
+     */
+    String DEVICE_LATEST_CASH_KEY = "park:device:statistic:latest:";
+
+    /**
+     * 单个设备的统计数据前缀 single
+     */
+    String DEVICE_DEFINITE_CASH_KEY = "park:device:statistic:count:single:";
+
+
+    /**
+     * 人员登陆之后输入账号和密码的次数
+     */
+    String USER_ACCESS_AUTH = "user:access:auth:";
+
+    /**
+     * 园区土壤湿度界限值
+     */
+    String PARK_SOIL_HUMIDITY = "park:soil:humidity:";
+
+    /**
+     * 设备画像类型key
+     */
+    String EQ_BREAKDOWN_TYPE = "park:equipment:breakdown:type";
+
+    /**
+     * 设备故障规则key
+     */
+    String EQ_BREAKDOWN_RULE_KEY = "park:equipment:breakdown:rule";
+
+    /**
+     * 设备画像规则key
+     */
+    String EQ_PICTURE_RULE = "park:equipment:picture:rule";
+
+    /**
+     * 设备画像分析数据存储前缀
+     */
+    String EQ_PICTURE_CODE = "park:equipment:picture:analyse";
+
+    /**
+     * 旧ISC人员信息同步key
+     */
+    String SYNC_OLD_ISC_PEOPLE = "sync:old:isc:people:";
+
+    /**
+     * 停车场车辆事件
+     * parking:car:event:停车场ID:车牌号
+     */
+    String PARKING_CAR_EVENT = "parking:car:event:";
+
+    /**
+     * 停车场车辆无感支付加锁
+     * parking:car:noFeel:停车场ID:车牌号
+     */
+    String PARKING_CAR_NOFEEL = "parking:car:noFeel:";
+
+    /**
+     * 停车场——定时任务事件
+     * parking:task:定时任务名
+     */
+    String PARKING_TASK = "parking:task:";
+
+    /**
+     * 月卡状态是否进行更新标识
+     */
+    String PARKING_CARD_STATE_TASK = "parking:card:stateTask";
+
+    /**
+     * 停车场车辆开闸记录
+     *
+     */
+    String PARKING_PLATENO_GATEOPEN = "parking:plateNo:gateOpen";
+    String CHARGING_TERMINAL_START_LIMIT ="charging_start_limit_terminalid_%s";
+    String CHARGING_RESULT_NOTIFY ="charging_result_notify_%s";
+    String CHARGING_TERMINAL_BASIC_KEY = "charging:tml:basic:terminalid_%s";
+
+    String CHARGING_TERMINAL_DETAIL_MAP = "charging:tml:station_%s:detail:map";
+
+    String CHARGING_TERMINAL_DETAIL_MAP_KEY = "charging:tml:detail:map:productKey_%s:gunNo_%s";
+
+    String CHARGING_TERMINAL_CHARGING_MAP = "charging:tml:station_%s:charging:map";
+
+    String CHARGING_TERMINAL_USER_CHARGING_LIST_KEY = "charging:tml:userid_%s:charging:list";
+
+    String CHARGING_TERMINAL_CHARGING_MAP_KEY = "charging:tml:charging2:map:terminalid_%s";
+
+    String WECHAT_ACCESS_TOKEN_NAME="wechat_acess_token_appid_%s";
+    String RSJ_CAMERA_TOKEN = "rsj:camera:token";
+    String CHARGE_STATION_OCCUPY_TIME = "charge:occupy:freetime:station_%s:";
+    String CHARGE_STATION_OCCUPY_SB = "charge:occupy:freetime:station_sb%s:";
+
+    String CHANGE_CREATE_SEND_CODE_KEY="change:create:%s";
+
+    /**
+     * 应用id
+     */
+    String APPLY_ID = "apply:id:%s";
+
+    String LOCK="lock:";
+
+    String LOCK_SYNC_DEPT=LOCK+"syncDept:";
+
+    /**
+     * 房源抄表加锁
+     */
+    String LOCK_HOUSE_METER_READING=LOCK+"houseMeterReading:";
+
+    /**
+     * 房源抄表加锁
+     */
+    String LOCK_PUBLIC_METER_READING=LOCK+"publicMeterReading:";
+
+    /**
+     * 活动排序调整加锁
+     */
+    String LOCK_PAY_REDUCTION_SORT=LOCK+"payReductionSort:";
+}

+ 46 - 0
common/constant-common/src/main/java/com/thinkunion/park/service/common/constant/CommonConstant.java

@@ -0,0 +1,46 @@
+package com.thinkunion.park.service.common.constant;
+
+
+public interface CommonConstant {
+
+
+    String SWORD_NAME = "sword";
+
+
+    String SABER_NAME = "saber";
+
+    String PARK_NAME = "park";
+
+
+    Long TOP_PARENT_ID = 0L;
+
+
+    String TOP_PARENT_NAME = "顶级";
+
+
+    Integer NOT_SEALED_ID = 0;
+
+
+    String DEFAULT_PASSWORD = "YC123456";
+
+    String ADMIN_DEPT="1123598813738675201";
+    String DEFAULT_PARAM_PASSWORD = "account.initPassword";
+
+
+    String SORT_FIELD = "sort";
+
+
+    Integer DATA_SCOPE_CATEGORY = 1;
+
+
+    Integer API_SCOPE_CATEGORY = 2;
+
+
+	/***
+	 * 摄像头产品
+	 */
+
+	String PRODUCT_CAMERA_POINT = "384rQ13KlTUvrx3q";
+
+	String DEFAULT_PASSWORD_V1 = "zhyq888888";
+}

+ 32 - 0
common/constant-common/src/main/java/com/thinkunion/park/service/common/constant/TenantConstant.java

@@ -0,0 +1,32 @@
+package com.thinkunion.park.service.common.constant;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+public interface TenantConstant {
+
+
+	String PASSWORD_KEY = "tenant.default.password";
+
+	
+	String ACCOUNT_NUMBER_KEY = "tenant.default.accountNumber";
+
+	
+	String ACCOUNT_MENU_CODE_KEY = "tenant.default.menuCode";
+
+	
+	String DEFAULT_PASSWORD = "123456";
+
+	
+	String DES_KEY = "0000000000000000";
+
+	
+	Integer DEFAULT_ACCOUNT_NUMBER = -1;
+
+	
+	List<String> MENU_CODES = Arrays.asList(
+		"desk", "flow", "work", "monitor", "resource", "role", "user", "dept", "dictbiz", "topmenu"
+	);
+
+}

+ 73 - 0
common/launcher/pom.xml

@@ -0,0 +1,73 @@
+<?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>
+
+    <parent>
+        <artifactId>common</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>launcher</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>core-launch</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-ribbon</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>core-auto</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <finalName>${project.name}</finalName>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven.plugin.version}</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>UTF-8</encoding>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <distributionManagement>
+        <repository>
+            <id>releases</id>
+            <url>http://192.168.0.120:18081/repository/maven-releases/</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots</id>
+            <url>http://192.168.0.120:18081/repository/maven-snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+</project>

+ 133 - 0
common/launcher/src/main/java/org/nest/springwrap/launcher/LauncherConstant.java

@@ -0,0 +1,133 @@
+package org.nest.springwrap.launcher;
+
+import org.nest.springwrap.core.launch.constant.AppConstant;
+
+
+public interface LauncherConstant {
+
+
+    String NACOS_DEV_ADDR = "127.0.0.1:8848";
+    //String NACOS_DEV_ADDR = "192.168.0.175:8848";
+
+    String NACOS_PROD_ADDR = "192.168.0.230:8112";
+
+    String NACOS_PRE_ADDR = "192.168.0.120:18848";
+
+    String NACOS_TEST_ADDR = "192.168.0.25:8848";
+
+
+    String SENTINEL_DEV_ADDR = "127.0.0.1:8858";
+
+
+    String SENTINEL_PROD_ADDR = "127.0.0.1:8858";
+
+
+    String SENTINEL_TEST_ADDR = "127.0.0.1:8858";
+
+
+    String SEATA_DEV_ADDR = "127.0.0.1:8091";
+
+
+    String SEATA_PROD_ADDR = "127.0.0.1:8091";
+
+
+    String SEATA_TEST_ADDR = "127.0.0.1:8091";
+
+
+    String ZIPKIN_DEV_ADDR = "http://127.0.0.1:9411";
+
+
+    String ZIPKIN_PROD_ADDR = "http://127.0.0.1:9411";
+
+
+    String ZIPKIN_TEST_ADDR = "http://127.0.0.1:9411";
+
+
+    String ELK_DEV_ADDR = "127.0.0.1:9000";
+
+
+    String ELK_PROD_ADDR = "127.0.0.1:9000";
+
+
+    String ELK_TEST_ADDR = "127.0.0.1:9000";
+
+
+    String FILE_MODE = "file";
+
+
+    String NACOS_MODE = "nacos";
+
+
+    String DEFAULT_MODE = "default";
+
+
+    String GROUP_NAME = "-group";
+
+
+    static String seataServiceGroup(String appName) {
+        return appName.concat(GROUP_NAME);
+    }
+
+
+    static String nacosAddr(String profile) {
+        switch (profile) {
+            case (AppConstant.PROD_CODE):
+                return NACOS_PROD_ADDR;
+            case (AppConstant.TEST_CODE):
+                return NACOS_TEST_ADDR;
+            case (AppConstant.PRE_CODE):
+                return NACOS_PRE_ADDR;
+            default:
+                return NACOS_DEV_ADDR;
+        }
+    }
+
+
+    static String sentinelAddr(String profile) {
+        switch (profile) {
+            case (AppConstant.PROD_CODE):
+                return SENTINEL_PROD_ADDR;
+            case (AppConstant.TEST_CODE):
+                return SENTINEL_TEST_ADDR;
+            default:
+                return SENTINEL_DEV_ADDR;
+        }
+    }
+
+
+    static String seataAddr(String profile) {
+        switch (profile) {
+            case (AppConstant.PROD_CODE):
+                return SEATA_PROD_ADDR;
+            case (AppConstant.TEST_CODE):
+                return SEATA_TEST_ADDR;
+            default:
+                return SEATA_DEV_ADDR;
+        }
+    }
+
+
+    static String zipkinAddr(String profile) {
+        switch (profile) {
+            case (AppConstant.PROD_CODE):
+                return ZIPKIN_PROD_ADDR;
+            case (AppConstant.TEST_CODE):
+                return ZIPKIN_TEST_ADDR;
+            default:
+                return ZIPKIN_DEV_ADDR;
+        }
+    }
+
+
+    static String elkAddr(String profile) {
+        switch (profile) {
+            case (AppConstant.PROD_CODE):
+                return ELK_PROD_ADDR;
+            case (AppConstant.TEST_CODE):
+                return ELK_TEST_ADDR;
+            default:
+                return ELK_DEV_ADDR;
+        }
+    }
+
+}

+ 46 - 0
common/launcher/src/main/java/org/nest/springwrap/launcher/LauncherServiceImpl.java

@@ -0,0 +1,46 @@
+package org.nest.springwrap.launcher;
+
+import org.nest.springwrap.core.auto.service.AutoService;
+import org.nest.springwrap.core.launch.service.LauncherService;
+import org.nest.springwrap.core.launch.utils.PropsUtil;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+import java.util.Properties;
+
+
+@AutoService(LauncherService.class)
+public class LauncherServiceImpl implements LauncherService {
+
+    @Override
+    public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
+        Properties props = System.getProperties();
+        // 通用注册
+        PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.server-addr", LauncherConstant.nacosAddr(profile));
+        PropsUtil.setProperty(props, "spring.cloud.nacos.config.server-addr", LauncherConstant.nacosAddr(profile));
+        PropsUtil.setProperty(props, "spring.cloud.sentinel.transport.dashboard",
+                LauncherConstant.sentinelAddr(profile));
+        PropsUtil.setProperty(props, "spring.zipkin.base-url", LauncherConstant.zipkinAddr(profile));
+        PropsUtil.setProperty(props, "spring.datasource.dynamic.enabled", "false");
+
+        // 开启elk日志
+        // PropsUtil.setProperty(props, "nest.log.elk.destination", LauncherConstant.elkAddr(profile));
+
+        // seata注册地址
+         PropsUtil.setProperty(props, "seata.service.grouplist.default", LauncherConstant.seataAddr(profile));
+        // seata注册group格式
+      //   PropsUtil.setProperty(props, "seata.tx-service-group", LauncherConstant.seataServiceGroup(appName));
+         PropsUtil.setProperty(props, "seata.tx-service-group", "dci-tx-group");
+
+        // seata配置服务group
+         PropsUtil.setProperty(props, "seata.service.vgroup-mapping.dci-tx-group", LauncherConstant.DEFAULT_MODE);
+        // seata注册模式配置
+         PropsUtil.setProperty(props, "seata.registry.type", LauncherConstant.NACOS_MODE);
+         PropsUtil.setProperty(props, "seata.registry.nacos.server-addr", LauncherConstant.nacosAddr(profile));
+         PropsUtil.setProperty(props, "seata.registry.nacos.group","SEATA_GROUP");
+         PropsUtil.setProperty(props, "seata.config.type", LauncherConstant.NACOS_MODE);
+         PropsUtil.setProperty(props, "seata.config.nacos.server-addr", LauncherConstant.nacosAddr(profile));
+         PropsUtil.setProperty(props, "seata.config.nacos.group", "SEATA_GROUP");
+         PropsUtil.setProperty(props, "seata.config.nacos.data-id", "seataServer.properties");
+    }
+
+}

+ 35 - 0
common/miniprogram-common/pom.xml

@@ -0,0 +1,35 @@
+<?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">
+    <parent>
+        <artifactId>common</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>miniprogram-common</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-swagger</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 165 - 0
common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/auth/MiniprogramAuthUtil.java

@@ -0,0 +1,165 @@
+package com.yuchen.saas.miniprogram.common.auth;
+
+import com.alibaba.fastjson.JSON;
+import com.yuchen.saas.miniprogram.common.constants.LoginConstants;
+import com.yuchen.saas.miniprogram.common.vo.WxLoginVo;
+import com.yuchen.saas.miniprogram.common.vo.WxSaasCompanyVo;
+import com.yuchen.saas.miniprogram.common.vo.WxSaasUserVo;
+import org.nest.springwrap.core.redis.cache.NestRedis;
+import org.nest.springwrap.core.tool.utils.StringUtil;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class MiniprogramAuthUtil {
+//    @Resource
+//    private NestRedis nestRedis_;
+//    private static NestRedis nestRedis;
+
+    @Resource
+    private RedisTemplate<String,String> redisTemplate_;
+    private static RedisTemplate<String,String> redisTemplate;
+
+    @PostConstruct
+    public void init(){
+//        nestRedis=nestRedis_;
+
+        redisTemplate=redisTemplate_;
+    }
+
+    public static String getToken(){
+        return getRequest().getHeader("Authorization");
+    }
+
+    public static String getToken(HttpServletRequest request){
+        return request.getHeader("Authorization");
+    }
+    public static WxLoginVo getLogin(){
+        return getLogin(getRequest());
+    }
+    public static WxSaasUserVo getSaasUser(){
+        WxLoginVo wxLoginVo = getLogin(getRequest());
+        if(wxLoginVo!=null){
+            return wxLoginVo.getSaasUser();
+        }else {
+            return null;
+        }
+    }
+    public static WxSaasCompanyVo getSaasCompany(){
+        WxLoginVo wxLoginVo = getLogin(getRequest());
+        if(wxLoginVo!=null){
+            return wxLoginVo.getSaasCompany();
+        }else {
+            return null;
+        }
+    }
+    public static WxLoginVo getLogin(HttpServletRequest request){
+        try {
+            String headerToken = getToken(request);
+            return getLogin(headerToken);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static WxSaasUserVo getSaasUser(HttpServletRequest request){
+        WxLoginVo wxLoginVo =null;
+        try {
+            String headerToken = getToken(request);
+            wxLoginVo = getLogin(headerToken);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        if(wxLoginVo!=null){
+            return wxLoginVo.getSaasUser();
+        }
+        return null;
+    }
+    public static WxSaasCompanyVo getSaasCompany(HttpServletRequest request){
+        WxLoginVo wxLoginVo =null;
+        try {
+            String headerToken = getToken(request);
+            wxLoginVo = getLogin(headerToken);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        if(wxLoginVo!=null){
+            return wxLoginVo.getSaasCompany();
+        }
+        return null;
+    }
+    public static WxLoginVo getLogin(String headerToken){
+        try {
+            String json=redisTemplate.opsForValue().get(LoginConstants.WECHAT_USER_LOGIN_REDIS+headerToken);
+            if(StringUtil.isNotBlank(json)){
+                WxLoginVo loginVo=JSON.parseObject(json, WxLoginVo.class);
+                return loginVo;
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static WxSaasUserVo getSaasUser(String headerToken){
+        WxLoginVo loginVo=null;
+        try {
+            String json=redisTemplate.opsForValue().get(LoginConstants.WECHAT_USER_LOGIN_REDIS+headerToken);
+            if(StringUtil.isNotBlank(json)){
+                loginVo=JSON.parseObject(json, WxLoginVo.class);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        if(loginVo!=null){
+            return loginVo.getSaasUser();
+        }
+        return null;
+    }
+    public static WxSaasCompanyVo getSaasCompany(String headerToken){
+        WxLoginVo loginVo=null;
+        try {
+            String json=redisTemplate.opsForValue().get(LoginConstants.WECHAT_USER_LOGIN_REDIS+headerToken);
+            if(StringUtil.isNotBlank(json)){
+                loginVo=JSON.parseObject(json, WxLoginVo.class);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        if(loginVo!=null){
+            return loginVo.getSaasCompany();
+        }
+        return null;
+    }
+    public static void setLogin(WxLoginVo loginVo){
+        //token缓存
+//        nestRedis.setEx(LoginConstants.WECHAT_USER_LOGIN_REDIS+loginVo.getToken(), JSON.toJSONString(loginVo),60*60*24L);
+        redisTemplate.opsForValue().set(LoginConstants.WECHAT_USER_LOGIN_REDIS+loginVo.getToken(), JSON.toJSONString(loginVo),60*60*24L, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 清理登录缓存
+     */
+    public static void clearLogin(){
+        //token缓存
+        clearLogin(getToken());
+    }
+    public static void clearLogin(String token){
+        //token缓存
+//        nestRedis.del(LoginConstants.WECHAT_USER_LOGIN_REDIS+token);
+        redisTemplate.delete(LoginConstants.WECHAT_USER_LOGIN_REDIS+token);
+    }
+
+    public static HttpServletRequest getRequest(){
+        HttpServletRequest request=
+                ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
+        return request;
+    }
+
+}

+ 20 - 0
common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/constants/LoginConstants.java

@@ -0,0 +1,20 @@
+package com.yuchen.saas.miniprogram.common.constants;
+
+public class LoginConstants {
+
+    /**
+     * 微信用户手机授权缓存
+     */
+    public static String WECHAT_PHONE_AUTH_REDIS="wechat:phone_auth:";
+
+    /**
+     * 微信用户登录缓存
+     */
+    public static String WECHAT_USER_LOGIN_REDIS="wechat:login:";
+
+    /**
+     *短信验证码-图形验证码 测试用code
+     */
+    public static String TEST_CODE="wytwyt";
+
+}

+ 32 - 0
common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxLoginVo.java

@@ -0,0 +1,32 @@
+package com.yuchen.saas.miniprogram.common.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "微信登录结果", description = "微信登录结果")
+public class WxLoginVo {
+    //个人用户
+    public static Integer TYPE_USER_ACCOUNT=1;
+    //企业用户
+    public static Integer TYPE_COMPANY_ACCOUNT=2;
+    //个人+企业
+    public static Integer TYPE_SUP_ACCOUNT=3;
+
+    @ApiModelProperty(value = "账户类型1:个人用户,2:企业用户,3:个人+企业")
+    private Integer type;
+    @ApiModelProperty(value = "个人用户信息")
+    private WxSaasUserVo saasUser;
+    @ApiModelProperty(value = "企业用户信息")
+    private WxSaasCompanyVo saasCompany;
+    @ApiModelProperty(value = "登录token")
+    private String token;
+    @ApiModelProperty(value = "openId")
+    private String openId;
+    @ApiModelProperty(value = "phone")
+    private String phone;
+    @ApiModelProperty(value = "appid")
+    private String appid;
+
+}

+ 53 - 0
common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxSaasCompanyVo.java

@@ -0,0 +1,53 @@
+package com.yuchen.saas.miniprogram.common.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+@ApiModel(value = "企业用户对象", description = "企业用户对象")
+public class WxSaasCompanyVo {
+    @JsonSerialize(
+            using = ToStringSerializer.class
+    )
+    @ApiModelProperty("主键id")
+    private Long id;
+    @ApiModelProperty(value = "企业名称")
+    private String companyName;
+    @ApiModelProperty(value = "所属行业")
+    private String companyTrade;
+    @ApiModelProperty(value = "企业规模")
+    private String companyScope;
+    @ApiModelProperty(value = "企业联系人手机")
+    private String phone;
+    @ApiModelProperty(value = "企业联系人")
+    private String linkMan;
+    @ApiModelProperty(value = "联系电话")
+    private String linkPhone;
+    @ApiModelProperty(value = "省")
+    private String province;
+    @ApiModelProperty(value = "省名称")
+    private String provinceName;
+    @ApiModelProperty(value = "市")
+    private String city;
+    @ApiModelProperty(value = "市名称")
+    private String cityName;
+    @ApiModelProperty(value = "区/县")
+    private String county;
+    @ApiModelProperty(value = "区/县名称")
+    private String countyName;
+    @ApiModelProperty(value = "镇/街道")
+    private String town;
+    @ApiModelProperty(value = "镇/街道名称")
+    private String townName;
+    @ApiModelProperty(value = "公司地址")
+    private String address;
+
+}

+ 73 - 0
common/miniprogram-common/src/main/java/com/yuchen/saas/miniprogram/common/vo/WxSaasUserVo.java

@@ -0,0 +1,73 @@
+package com.yuchen.saas.miniprogram.common.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+@ApiModel(value = "用户基本信息", description = "用户基本信息")
+public class WxSaasUserVo {
+    @JsonSerialize(
+            using = ToStringSerializer.class
+    )
+    @ApiModelProperty("主键id")
+    private Long id;
+    @ApiModelProperty(value = "姓名")
+    private String name;
+
+    @ApiModelProperty(value = "性别1男,2女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String contactPhone;
+
+    @ApiModelProperty(value = "证件号码")
+    private String idcard;
+
+    @ApiModelProperty(value = "手机号码")
+    private String phone;
+
+    @ApiModelProperty(value = "注册来源")
+    private Integer source;
+
+    @ApiModelProperty(value = "生日")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date birthday;
+
+    @ApiModelProperty(value = "个人照片")
+    private String pic;
+
+    @ApiModelProperty(value = "省")
+    private String contactProvince;
+    @ApiModelProperty(value = "省名称")
+    private String contactProvinceName;
+
+    @ApiModelProperty(value = "市")
+    private String contactCity;
+    @ApiModelProperty(value = "市名称")
+    private String contactCityName;
+
+    @ApiModelProperty(value = "区/县")
+    private String contactCounty;
+    @ApiModelProperty(value = "区/县名称")
+    private String contactCountyName;
+
+    @ApiModelProperty(value = "镇/街道")
+    private String contactTown;
+    @ApiModelProperty(value = "镇/街道名称")
+    private String contactTownName;
+
+    @ApiModelProperty(value = "详细地址")
+    private String contactAddress;
+
+    @ApiModelProperty(value = "允许他人查看我停车信息1允许,2不允许")
+    private Integer publicParkingBill;
+
+}

+ 98 - 0
common/park-common/pom.xml

@@ -0,0 +1,98 @@
+<?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>
+
+    <parent>
+        <artifactId>common</artifactId>
+        <groupId>com.yuchen.saas</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>park-common</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>launcher</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.yuchen.saas</groupId>
+            <artifactId>constant-common</artifactId>
+            <version>1.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.yuchen.saas</groupId>
+                    <artifactId>launcher</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-tenant</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.thinkunion.sdk.iot</groupId>
+            <artifactId>iot-api-sdk-java</artifactId>
+            <version>0.0.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.hikvision.ga</groupId>
+            <artifactId>artemis-http-client</artifactId>
+            <version>1.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.nest.springwrap</groupId>
+            <artifactId>starter-swagger</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.20</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <finalName>${project.name}</finalName>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 118 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/baseentity/MenuTypeEnum.java

@@ -0,0 +1,118 @@
+package com.thinkunion.park.service.common.baseentity;
+
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author 黄兵华
+ * @date 2022/1/10 11:33
+ * @describe
+ */
+public enum MenuTypeEnum {
+
+    PARKING_LOT(1, "停车场", true),
+    FIXED_CREWS_TAKE(2, "固定车组", true),
+    CHARGING_RULES(3, "收费规则", true),
+    RELEASE_RULES(4, "放行规则", true),
+    CAR_INFO(5, "车辆信息", true),
+    REVIEW_MONTHLY(6, "月卡审核", true),
+    ACCESS_RECORDS(7, "出入记录", false),
+    CORRECT_CAR_DATA(8, "余位矫正", false),
+    STATISTICAL_ANALYSIS(9, "统计分析", false),
+    PARKING_FAVORABLE(10, "停车优惠", false),
+    CHARGE_MERCHANTS(11, "收费商户", true),
+    MANAGEMENT_TOOL(12, "管理工具", true),
+    INVOICE_RECORD(13, "开票记录", false),
+    REFUND_APPROVE(14, "退款审核", true),
+    REFUND_APPLY(15, "退款申请", false),
+
+    PARK_INFO(16, "园区信息", false),
+    SPACE_EQUIPMENT(17, "空间设备", false),
+    ENTERPRISE_INFORMATION(18, "企业信息", false),
+    PERSON_INFORMATION(19, "人员信息", false),
+    MACHINE_INFORMATION(20, "设备信息", false),
+    ALARM_TYPE(21, "报警类型", false),
+
+    ROLE_MANAGEMENT(22, "角色管理", false),
+    DATA_ACCESS(23, "数据权限", false),
+    INTERFACE_ACCESS(24, "接口权限", false),
+
+    PERSON_MANAGEMENT(25, "用户管理", false),
+    DEPART_MANAGEMENT(26, "机构管理", false),
+    JOBS_MANAGEMENT(27, "岗位管理", false),
+    SYS_DICTIONARY(28, "系统字典", false),
+    BUSINESS_DICTIONARY(29, "业务字典", false),
+    MENU_MANAGEMENT(30, "菜单管理", false),
+    TOP_MENU(31, "顶部菜单", false),
+
+    PEOPLE_ACCESS_AUTH_track(32,"人员访问:人员轨迹",false),
+    PEOPLE_ACCESS_AUTH_video_view(33,"人员访问:视频回放",false),
+    PEOPLE_ACCESS_AUTH_video_down(34,"人员访问:视频下载",false),
+    ERROR_TIME_AUDIT(35,"错时审核",true),
+    LICENSE_PLATE_ALTERATION(36,"车牌变更",true),
+    MONTH_LICENSE_PLATE_ALTERATION(36,"月卡车牌变更",true),
+
+    ;
+
+    private Integer value;
+
+    private String desc;
+
+    private boolean use;
+
+    MenuTypeEnum(Integer value, String desc, boolean use) {
+        this.value = value;
+        this.desc = desc;
+        this.use = use;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+
+    public static MenuTypeEnum getMenuTypeByValue(Integer value) {
+        if (Objects.isNull(value)) {
+            return null;
+        }
+        MenuTypeEnum[] menus = values();
+        for (MenuTypeEnum menu : menus) {
+            if (menu.getValue().equals(value)) {
+                return menu;
+            }
+        }
+        return null;
+    }
+
+    public static MenuTypeEnum getMenuTypeByDesc(String desc) {
+        if (StringUtils.isBlank(desc)) {
+            return null;
+        }
+        MenuTypeEnum[] menus = values();
+        for (MenuTypeEnum menu : menus) {
+            if (menu.getDesc().equals(desc)) {
+                return menu;
+            }
+        }
+        return null;
+    }
+
+    public static List<MenuTypeEnum> getUserMenuName() {
+        MenuTypeEnum[] menus = values();
+        return Arrays.stream(menus).filter(var -> var.use).collect(Collectors.toList());
+    }
+
+    public static List<Integer> getUseValue(){
+        MenuTypeEnum[] menus=values();
+        return Arrays.stream(menus).filter(var-> var.use).map(MenuTypeEnum::getValue).collect(Collectors.toList());
+    }
+}

+ 16 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/constant/GroupAction.java

@@ -0,0 +1,16 @@
+package com.thinkunion.park.service.common.constant;
+
+import javax.validation.groups.Default;
+
+/**
+ * @author zhouhanwei
+ * @since 2024-01-04
+ */
+public class GroupAction {
+
+    public interface UpdateAction extends Default {
+    }
+
+    public interface InsertAction extends Default {
+    }
+}

+ 46 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/constant/PKCONSTANT.java

@@ -0,0 +1,46 @@
+package com.thinkunion.park.service.common.constant;
+
+/**
+ * @author 吕海泉
+ * @create 2021/1/7 17:31
+ */
+public class PKCONSTANT {
+
+    /**
+     * 灭火器检测器
+     */
+    public static final String FIREXTINGUISHER = "8gF31iKdiJe0NW3a";
+    /**
+     * 大树-人脸面板机
+     */
+    public static final String FACEPANEL = "mkhXD2I9UWr0J4ut";
+    /**
+     * 海康-人脸识别机
+     */
+    public static final String HIKFACERECOGNITION = "384rQ13KlTUvrx3q";
+    /**
+     * 唯传-sos
+     */
+    public static final String SOSWARNING = "bw63z6jt04p5RRTt";
+    /**
+     * 四联水表
+     */
+    public static final String WATERPK = "g0saEDt5mJRvyF3T";
+    /**
+     * 四联电表
+     */
+    public static final String AMMETERPK = "H4a2K382Ov1Ts5sd";
+    /**
+     * 唯传-雨量
+     */
+    public static final String RAINFALL_PK = "BTa863298Bp6R1y4";
+    /**
+     * 海康-道闸抓拍一体机
+     */
+    public static final String GATE_PHOTO_PK = "kWJUPZJ3vb9N7z0t";
+    /**
+     * 停车场主控程序
+     */
+    public static final String VIRTUAL_GW = "P377jx5fX6WCIlMC";
+
+}

+ 280 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/constant/ParkingConstant.java

@@ -0,0 +1,280 @@
+package com.thinkunion.park.service.common.constant;
+
+public class ParkingConstant {
+
+    public interface YesOrNo {
+        Integer YES = 1;
+        Integer NO = 0;
+    }
+
+    public interface BaseSql {
+        String GET_ONE = "LIMIT 1";
+    }
+
+    public final class EventType {
+        public static final String ENTER_DETECT_EVENT = "car_in_on_line_event";
+        public static final String ENTER_PASS_EVENT = "car_in_event";
+        public static final String EXIT_DETECT_EVENT = "car_out_on_line_event";
+        public static final String EXIT_PASS_EVENT = "car_out_event";
+    }
+
+    public final class FreePass {
+        public static final int OFF = 0;
+        public static final int ON = 1;
+    }
+
+    public final class SpecialPlate {
+        public static final String STANDARD_CIVILIAN_CAR = "标准民用车";
+        public static final String TYPE_02_CIVIL_LICENSE_PLATE = "02式民用车牌";
+        public static final String ARMED_POLICE_VEHICLE_LICENSE_PLATE = "武警车车牌";
+        public static final String THE_POLICE_CAR_LICENSE_PLATE = "警车车牌";
+        public static final String CIVIL_CAR_DOUBLE_ROW_TAIL_PLATE = "民用车双行尾牌";
+        public static final String THE_EMBASSY_OF_THE_LICENSE_PLATE = "使馆车牌";
+        public static final String LICENSE_PLATE_OF_AGRICULTURAL_VEHICLE = "农用车车牌";
+        public static final String MOTORBIKE = "摩托车";
+        public static final String NEW_ENEGRY_VEHICLE = "新能源车";
+        public static final String MILITARY_VEHICLES_LICENSE_PLATE = "军车车牌";
+    }
+
+
+    public final class Direction {
+        public static final int Enter = 0;
+        public static final String Enter_String = "0";
+        public static final int Exit = 1;
+        public static final String Exit_String = "1";
+    }
+
+    public final class RealTimeBillType {
+        //实时账单类型:1-月卡车场内失效 2-固定车场内失效
+        public static final int MothlyExpired = 1;
+        public static final int GroupExpired = 2;
+        public static final int TeamTemporary = 3;
+        public static final int TimeFreeTemporary = 4;
+        public static final int TimeFreeExpired = 5;
+    }
+
+    public final class SubBillType {
+        /**
+         * 团队车
+         */
+        public static final int TeamTemporary = 1;
+        public static final int TimeFreeTemporary = 2;
+        /**
+         * 12-AB车位
+         */
+        public static final int SharePlace = 12;
+
+        /**
+         * 23-访客车
+         */
+        public static final int VisitorCar = 23;
+
+    }
+
+    public final class Payment {
+        public static final int Clear = 1;
+        public static final int Billable = 0;
+    }
+
+    public final class BillType {
+        // 账单类型:1-临停 2-月卡 3-无牌车,4-特殊车,5-节假日,6-群组,7-异常,8--------放行规则提供,10-团队车,20-错时车
+        public static final int unknown = 0;
+        /**
+         * 1-临停
+         */
+        public static final int Temporary = 1;
+        /**
+         * 2-月卡
+         */
+        public static final int MonthlyCard = 2;
+        /**
+         * 3-无牌车
+         */
+        public static final int Anonymous = 3;
+        /**
+         * 4-特殊车
+         */
+        public static final int Special = 4;
+        /**
+         * 5-节假日
+         */
+        public static final int Holidays = 5;
+        /**
+         * 6-群组
+         */
+        public static final int Group = 6;
+        /**
+         * 7-异常
+         */
+        public static final int Exception = 7;
+        /**
+         * 8-黑名单
+         */
+        public static final int BlackListCar = 8;
+        /**
+         * 9-充电黑名单
+         */
+        public static final int SpcBlackListCar = 9;
+        /**
+         * 10-团队车
+         */
+        public static final int Team = 10;
+        /**
+         * 11-车组
+         */
+        public static final int VehicleGroup = 11;
+        /**
+         * 12-AB车位
+         */
+        public static final int SharePlace = 12;
+        /**
+         * 13-团队车位
+         */
+        public static final int TeamPlace = 13;
+        /**
+         * 20-错时车
+         */
+        public static final int TimeFree = 20;
+        /**
+         * 21-产权车
+         */
+        public static final int PropertyRight = 21;
+        /**
+         * 22-内部车
+         */
+        public static final int InsideCar = 22;
+        /**
+         * 23-访客车
+         */
+        public static final int VisitorCar = 23;
+        /**
+         * 24-免费
+         */
+        public static final int Free = 24;
+
+        /**
+         * 26-充电 (钱包支付)
+         */
+        public static final int chargePay = 26;
+
+        /**
+         * 28-钱包
+         */
+        public static final int walletPay = 28;
+
+        /**
+         * 30-占位费
+         */
+        public static final int occupyFeePay = 30;
+
+        /**
+         * 40-物业费
+         */
+        public static final int propertyFeePay = 40;
+        /**
+         * 41-物业预存款缴费
+         */
+        public static final int propertyPrepaymentFeePay = 41;
+        /**
+         * 40-装修押金
+         */
+        public static final int decorationDeposit = 42;
+    }
+
+    public final class PassRule {
+        /**
+         * 固定车自动放行
+         */
+        public static final int TIME_PERIOD_PASS = 101;
+        /**
+         * 临时车自动放行
+         */
+        public static final int TEMPORARY_PASS = 202;
+        /**
+         * 节假日自动放行
+         */
+        public static final int HOLIDAYS_PASS = 303;
+        /**
+         * 特殊车辆自动放行
+         */
+        public static final int SPECIAL_PASS = 404;
+        /**
+         * 黑名单不放行
+         */
+        public static final int FIVE = 505;
+        /**
+         * 群组车自动放行
+         */
+        public static final int SIX = 606;
+        /**
+         * 车位满了禁止放行
+         */
+        public static final int SEVEN = 707;
+        /**
+         * 收费为0禁止放行
+         */
+        public static final int EIGHT = 808;
+        /**
+         * 未知原因
+         */
+        public static final int NINE = 909;
+        /**
+         * 无牌车自动放行
+         */
+        public static final int TEN = 1010;
+        /**
+         * 未交费不放行
+         */
+        public static final int ELEVEN = 1111;
+    }
+
+    public final class BillStatus {
+        //账单状态:0-未结清状态,1-已结算(已出停车场)  ----每一次变动添加一条记录
+        public static final int WAIT_FOR_PAYMENT = 0;
+        public static final int PAID = 1;
+    }
+
+    public final class GroupPassRule {
+        //0:出场不放行,1:出场控制放行 按 日 周 时段
+        public static final int Forbid = 0;
+        public static final int Limit = 1;
+    }
+
+    /**
+     * 是否放行
+     */
+    public final class Pass {
+        /**
+         * 0:不放行
+         */
+        public static final int Forbid = 0;
+        /**
+         * 1:放行
+         */
+        public static final int Allow = 1;
+    }
+
+    public final class AnonymousPassRule {
+        //0:不放行,1:放行
+        public static final int Forbid = 0;
+        public static final int Limit = 1;
+    }
+
+    // 放行时段(0:全天候,1:按日,2:按周)
+    public final class GroupPassTime {
+        public static final int AnyDay = 0;
+        public static final int SpecialDay = 1;
+        public static final int SpecialWeek = 2;
+    }
+
+    // 车位满是否放行(0:不放行,1:放行)
+    public final class TruckSpaceFull {
+        public static final int Forbid = 0;
+        public static final int Allow = 1;
+    }
+
+    public final class GatewayCommand {
+        public static final String Open = "1";
+        public static final String Close = "0";
+    }
+}

+ 26 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/BasicEntity.java

@@ -0,0 +1,26 @@
+package com.thinkunion.park.service.common.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.nest.springwrap.core.tenant.mp.TenantEntity;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName BasicEntity
+ * @Description
+ * @author 吕海泉
+ * @Date 2021/5/1 12:40
+ * @Version 1.0
+ **/
+@Data
+public abstract class BasicEntity extends TenantEntity implements Serializable {
+
+    /**
+     * 园区id
+     */
+    @ApiModelProperty(name = "parkId", value = "园区id")
+    private Long parkId;
+}
+
+

+ 130 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/EnterPassTicket.java

@@ -0,0 +1,130 @@
+package com.thinkunion.park.service.common.entity;
+
+import com.thinkunion.park.service.common.constant.ParkingConstant;
+import com.thinkunion.park.service.common.utils.JSONPrint;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+import org.nest.springwrap.core.tool.utils.DateUtil;
+import org.nest.springwrap.core.tool.utils.StringUtil;
+
+import java.util.Date;
+
+/**
+ * @author 钱江
+ * @description 车辆入场时获取的票根
+ * @date 2022/10/1 下午8:18
+ * @version 0.3.0
+ */
+@Data
+@Accessors(chain = true)
+@Slf4j
+public class EnterPassTicket extends PassTicket {
+
+    public EnterPassTicket() {
+        super();
+    }
+
+    public EnterPassTicket(String plateNo, int passStatus, String passMessage, String monthlyCardLed, int billType) {
+        super(plateNo, passStatus, passMessage, monthlyCardLed, billType);
+    }
+
+    public EnterPassTicket(String plateNo, int passStatus, String passMessage, String monthlyCardLed, Integer billType,
+                           Integer subParkingType) {
+        super(plateNo, passStatus, passMessage, monthlyCardLed, billType, subParkingType);
+    }
+
+    @Override
+    public String getLan1() {
+        if (this.isPassForbid()) {
+            if (this.subParkingType != null && this.subParkingType == ParkingConstant.SubBillType.TeamTemporary) {
+                return "团队车位已满";
+            }
+            if (this.billType != null && this.billType == ParkingConstant.BillType.SpcBlackListCar) {
+                return "禁止放行,"+this.spcMessage;
+            }
+
+            return "禁止放行";
+        }
+        if(StringUtil.isNotBlank(this.spcMessage)){
+            return  this.spcMessage;
+        }
+        return "欢迎光临";
+    }
+
+    @Override
+    public String getLan2() {
+        if (this.isAnonymous()) {
+            return this.getPlateNoIfAnonymous();
+        }
+        return this.getPlateNo();
+    }
+
+    @Override
+    public String getLan3() {
+        if (this.isMonthlyCard()) {
+            return this.getMonthlyCardLed();
+        }
+        return this.getPassMessage();
+    }
+
+    @Override
+    public String getLan4() {
+        return "时间: " + DateUtil.formatDateTime(new Date());
+    }
+
+
+    public void printSelf() {
+        log.info("\n\n========================================================================生成入场票根 {} \n lan1 {} " +
+                        "\n lan2 {} \n lan3 {} \n lan4 {} \n {} \n" +
+                        "===================================================================================\n\n",
+                this.getPlateNo(), this.getLan1(),
+                this.getLan2(),
+                this.getLan3(), this.getLan4(), JSONPrint.printObject(this));
+    }
+
+    @Override
+    public String getVoiceContent() {
+        String voiceContent = this.getPlateNo().concat("欢迎光临");
+        if (this.isPassForbid()) {
+            voiceContent = this.getPassMessage();
+        }
+        return voiceContent;
+    }
+
+    @Override
+    public EnterPassTicket setPlateNo(String plateNo) {
+        super.setPlateNo(plateNo);
+        return this;
+    }
+
+    @Override
+    public EnterPassTicket setPassStatus(Integer passStatus) {
+        super.setPassStatus(passStatus);
+        return this;
+    }
+
+    @Override
+    public EnterPassTicket setPassMessage(String passMessage) {
+        super.setPassMessage(passMessage);
+        return this;
+    }
+
+    @Override
+    public EnterPassTicket setMonthlyCardLed(String monthlyCardLed) {
+        super.setMonthlyCardLed(monthlyCardLed);
+        return this;
+    }
+
+    @Override
+    public EnterPassTicket setBillType(Integer billType) {
+        super.setBillType(billType);
+        return this;
+    }
+
+    @Override
+    public EnterPassTicket setSubParkingType(Integer subParkingType) {
+        super.setSubParkingType(subParkingType);
+        return this;
+    }
+}

+ 216 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/ExitPassTicket.java

@@ -0,0 +1,216 @@
+package com.thinkunion.park.service.common.entity;
+
+import com.thinkunion.park.service.common.constant.ParkingConstant;
+import com.thinkunion.park.service.common.enums.parking.TicketCauseContent;
+import com.thinkunion.park.service.common.utils.JSONPrint;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+import org.nest.springwrap.core.tool.utils.DateUtil;
+import org.nest.springwrap.core.tool.utils.Func;
+
+import java.util.Date;
+
+/**
+ * @author 钱江
+ * @description 车辆出场时获取的票根
+ * @date 2022/10/1 下午8:19
+ * @version 0.3.0
+ */
+@Data
+@Accessors(chain = true)
+@Slf4j
+public class ExitPassTicket extends PassTicket {
+
+    //停车时长
+    protected Integer parkTime;
+
+    //费用金额
+    protected Integer amount;
+
+    //是否无感支付
+    public Integer isNoFeel;
+
+    protected long supposePlaceIdleCost;
+
+    protected long oldSupposePlaceIdleCost;
+
+    protected long supposeCost;
+
+    protected long placeIdleTime;
+
+    public ExitPassTicket() {
+        super();
+    }
+
+    public ExitPassTicket(String plateNo, int passStatus, String passMessage, String monthlyCardLed, int billType,
+                          int parkTime, int amount) {
+        super(plateNo, passStatus, passMessage, monthlyCardLed, billType);
+        this.parkTime = parkTime;
+        this.amount = amount;
+    }
+
+    @Override
+    public String getLan1() {
+        if (this.isPassForbid()) {
+            //无入场时间显示
+            if(TicketCauseContent.NOT_IN_EVENT.getValue().equals(this.getPassMessage())){
+                return "无入场信息,联系现场保安补录";
+            }
+            if(Func.isNotEmpty(this.getSpcMessage())&&this.spcMessage.contains("充电车位")){
+                return "禁止放行"+this.getSpcMessage();
+            }
+            return "禁止放行";
+        } else {
+            if(Func.isNotEmpty(this.getSpcMessage())&&this.spcMessage.contains("充电车位")){
+                return this.getSpcMessage();
+            }
+            return "一路顺风";
+        }
+    }
+
+    @Override
+    public String getLan2() {
+        // 判断是否是无牌车
+        if (this.isAnonymous()) {
+            return this.getPlateNoIfAnonymous();
+        }
+        return this.getPlateNo();
+    }
+
+    @Override
+    public String getLan3() {
+        if (this.hasSupposePlaceIdleCost()) {
+            if (this.isTeam() || this.isMonthlyCard() || this.isSpecial()) {
+                return "充电占用时长 " + this.placeIdleTime + " 分钟";
+            }
+        }
+
+        if (this.isTemporary()) {
+            Integer parkTime = 0;
+            if (null != this.getParkTime()) {
+                parkTime = this.getParkTime();
+            }
+            return "停车时长:" + parkTime + "分钟";
+        } else if (this.isMonthlyCard()) {
+            return "月租车辆";
+        } else {
+            return this.getPassMessage();
+        }
+    }
+
+    @Override
+    public String getLan4() {
+        if (this.hasSupposePlaceIdleCost()) {
+            if (this.isTeam() || this.isMonthlyCard() || this.isSpecial()) {
+                return "需缴占用费 " + this.oldSupposePlaceIdleCost / 100D + " 元";
+            }
+        }
+
+        if (this.isTemporary()) {
+
+            String content="";
+
+            if(this.isNoFeel==1){
+                if(this.supposeCost==0){
+                    content="已代扣 -";
+                }else{
+                    content="需付"+this.supposeCost / 100D+"优惠代扣-"+(this.amount-this.supposeCost)/ 100D+"元;";
+                }
+            }
+
+            if(this.hasSupposePlaceIdleCost()){
+                if((this.amount-this.oldSupposePlaceIdleCost)>0){
+                    content+=this.amount / 100D+"元(停车" + (this.amount-this.oldSupposePlaceIdleCost) / 100D + "元,占用费"+oldSupposePlaceIdleCost / 100D+"元)";
+                }else{
+                    content+=oldSupposePlaceIdleCost / 100D + "元占用费";
+                }
+            }else{
+                content+=(amount-oldSupposePlaceIdleCost) / 100D + "元停车费";
+            }
+
+
+            return content;
+        } else if (this.isMonthlyCard()) {
+            return this.getMonthlyCardLed();
+        } else {
+            return "时间: " + DateUtil.formatDateTime(new Date());
+        }
+    }
+
+    @Override
+    public String getVoiceContent() {
+        if (this.hasSupposePlaceIdleCost()) {
+            if (this.isTeam() || this.isMonthlyCard() || this.isSpecial()) {
+                return "需缴占用费 " + this.oldSupposePlaceIdleCost / 100D + " 元";
+            }
+        }
+
+        String voiceContent = this.getPlateNo().concat("一路顺风");
+        if (this.isPassForbid()) {
+            voiceContent = this.getPassMessage();
+        }
+        return voiceContent;
+    }
+
+    @Override
+    public ExitPassTicket setPlateNo(String plateNo) {
+        super.setPlateNo(plateNo);
+        return this;
+    }
+
+    @Override
+    public ExitPassTicket setPassStatus(Integer passStatus) {
+        super.setPassStatus(passStatus);
+        return this;
+    }
+
+    @Override
+    public ExitPassTicket setPassMessage(String passMessage) {
+        super.setPassMessage(passMessage);
+        return this;
+    }
+
+    @Override
+    public ExitPassTicket setMonthlyCardLed(String monthlyCardLed) {
+        super.setMonthlyCardLed(monthlyCardLed);
+        return this;
+    }
+
+    @Override
+    public ExitPassTicket setBillType(Integer billType) {
+        super.setBillType(billType);
+        return this;
+    }
+
+    @Override
+    public ExitPassTicket setSubParkingType(Integer subParkingType) {
+        super.setSubParkingType(subParkingType);
+        return this;
+    }
+
+    public ExitPassTicket setSupposeCost(long supposeCost) {
+        this.supposeCost = supposeCost;
+        if (this.supposeCost > 0) {
+            this.passStatus = ParkingConstant.Pass.Forbid;
+        }
+        return this;
+    }
+
+    public void printSelf() {
+        log.info("\n\n========================================================================生成离场票根 {} \n lan1 {} " +
+                        "\n lan2 {} \n lan3 {} \n lan4 {} \n {} \n" +
+                        "===================================================================================\n\n",
+                this.getPlateNo(), this.getLan1(),
+                this.getLan2(),
+                this.getLan3(), this.getLan4(), JSONPrint.printObject(this));
+    }
+
+    public boolean hasSupposePlaceIdleCost() {
+        return this.supposePlaceIdleCost > 0L;
+    }
+
+    public boolean hasSupposeParkingCost() {
+        return (this.supposeCost - this.supposePlaceIdleCost) > 0L;
+    }
+}

+ 27 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/ParkEntity.java

@@ -0,0 +1,27 @@
+package com.thinkunion.park.service.common.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.nest.springwrap.core.mp.base.BaseEntity;
+import org.nest.springwrap.core.tenant.mp.TenantEntity;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName ParkEntity
+ * @Description
+ * @author 宋少挺
+ * @Date 2021/5/1 12:40
+ * @Version 1.0
+ **/
+@Data
+public abstract  class ParkEntity extends BaseEntity implements Serializable {
+
+    /**
+     * 园区id
+     */
+    @ApiModelProperty(name = "parkId",value = "园区id")
+    private Long parkId;
+}
+
+

+ 148 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/PassTicket.java

@@ -0,0 +1,148 @@
+package com.thinkunion.park.service.common.entity;
+
+import com.thinkunion.park.service.common.constant.ParkingConstant;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author 黄辉
+ * @version 1.0
+ * @date 2021/6/15 19:24
+ * <p>
+ * 缓存放行规则返回信息
+ */
+@Data
+@Accessors(chain = true)
+public abstract class PassTicket implements Row4LedAbility, VideoAbility {
+
+    public static final Logger logger = LoggerFactory.getLogger(PassTicket.class);
+    protected long timestamp;
+
+    /**
+     * 车牌号
+     */
+    protected String plateNo;
+
+    /**
+     * 放行状态( 0 = 不允许放行, 1 = 允许放行 )
+     */
+    protected Integer passStatus;
+
+    /**
+     * 语音提示
+     */
+    protected String voice;
+
+    /**
+     * 放行原因
+     * 1、写入账单表的 outMsg 字段
+     * 2、写入账单历史表的 outMsg 字段
+     * 3、写入过车记录表的 passMessage 字段
+     * 4、作为LED显示内容
+     * 5、作为语音播报的内容
+     */
+    protected String passMessage;
+
+    protected String spcMessage;
+
+    /**
+     * 作为月卡账单的LED显示的内容
+     */
+    protected String monthlyCardLed;
+
+    /**
+     * 账单类型:1-临停 2-月卡 3-无牌车,4-特殊车,5-节假日,6-群组,7-异常,8--------放行规则提供,10-团队车,20-错时车
+     */
+    protected Integer billType;
+
+    protected Integer subParkingType;
+
+    public PassTicket() {
+        this.timestamp = System.currentTimeMillis() / 1000L;
+    }
+
+    public PassTicket(String plateNo, int passStatus, String passMessage, String monthlyCardLed, int billType) {
+        this.plateNo = plateNo;
+        this.passStatus = passStatus;
+        this.passMessage = passMessage;
+        this.monthlyCardLed = monthlyCardLed;
+        this.billType = billType;
+        this.timestamp = System.currentTimeMillis() / 1000L;
+    }
+
+    public PassTicket(String plateNo, int passStatus, String passMessage, String monthlyCardLed, Integer billType,
+                      Integer subParkingType) {
+        this.plateNo = plateNo;
+        this.passStatus = passStatus;
+        this.passMessage = passMessage;
+        this.monthlyCardLed = monthlyCardLed;
+        this.billType = billType;
+        this.subParkingType = subParkingType;
+        this.timestamp = System.currentTimeMillis() / 1000L;
+    }
+
+    public String getPlateNoIfAnonymous() {
+        if (this.isAnonymous()) {
+            return "无牌车";
+        }
+        return this.getPlateNo();
+    }
+
+    /**
+     * 可以通行
+     * @return
+     */
+    public boolean isPassAllow() {
+        return passStatus == ParkingConstant.Pass.Allow;
+    }
+
+    /**
+     * 禁止通行
+     * @return
+     */
+    public boolean isPassForbid() {
+        return passStatus == ParkingConstant.Pass.Forbid;
+    }
+
+    public boolean isUnknown() {
+        return ParkingConstant.BillType.unknown == this.billType;
+    }
+
+    public boolean isTemporary() {
+        return ParkingConstant.BillType.Temporary == this.billType;
+    }
+
+    public boolean isMonthlyCard() {
+        return ParkingConstant.BillType.MonthlyCard == this.billType;
+    }
+
+    public boolean isAnonymous() {
+        return ParkingConstant.BillType.Anonymous == this.billType;
+    }
+
+    public boolean isSpecial() {
+        return ParkingConstant.BillType.Special == this.billType;
+    }
+
+    public boolean isHolidays() {
+        return ParkingConstant.BillType.Holidays == this.billType;
+    }
+
+    public boolean isGroup() {
+        return ParkingConstant.BillType.Group == this.billType;
+    }
+
+    public boolean isException() {
+        return ParkingConstant.BillType.Exception == this.billType;
+    }
+
+    public boolean isTeam() {
+        return ParkingConstant.BillType.Team == this.billType;
+    }
+
+    public boolean isTimeFree() {
+        return ParkingConstant.BillType.TimeFree == this.billType;
+    }
+}

+ 30 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/Row4LedAbility.java

@@ -0,0 +1,30 @@
+package com.thinkunion.park.service.common.entity;
+
+/**
+ * @author 钱江
+ * @description 定义四行显示的LED能力接口
+ * @date 2022/10/1 下午8:15
+ * @version 0.3.0
+ */
+public interface Row4LedAbility {
+
+    /**
+     * 获取第一行显示内容
+     */
+    String getLan1();
+
+    /**
+     * 获取第二行显示内容
+     */
+    String getLan2();
+
+    /**
+     * 获取第三行显示内容
+     */
+    String getLan3();
+
+    /**
+     * 显示第四行显示内容
+     */
+    String getLan4();
+}

+ 15 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/entity/VideoAbility.java

@@ -0,0 +1,15 @@
+package com.thinkunion.park.service.common.entity;
+
+/**
+ * @author 钱江
+ * @description 定义语音播报能力接口
+ * @date 2022/10/1 下午8:15
+ * @version 0.3.0
+ */
+public interface VideoAbility {
+
+    /**
+     * 获取语音播报内容
+     */
+    String getVoiceContent();
+}

+ 40 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ActiveStateEnum.java

@@ -0,0 +1,40 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 月卡状态(0 未缴费 1 正常使用 2 已过期)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum ActiveStateEnum {
+
+
+    UNPAID_FEE(0, "未交费(免费未生效)"),
+    NORMAL_USE(1, "正常使用"),
+    OUT_OF_DATE(2, "已过期"),
+    DEFUNCT(3, "已失效"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        ActiveStateEnum[] enumArray = ActiveStateEnum.values();
+        for (ActiveStateEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 44 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/AppEnum.java

@@ -0,0 +1,44 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 小程序APPID枚举
+ * @author LLC
+ */
+@AllArgsConstructor
+public enum AppEnum {
+
+    HJGWH_TEST_APP("wx908e9848a2667637", "钰辰云小程序(测试)-测试小程序"),
+    HJGWH_APP("wx306ce81471effaf0", "厦门火炬智慧云平台-生产小程序"),
+    HJJT_APP("wxc1e73c5498c82608", "聚合场站-生产小程序"),
+    BBC_APP_TEST("wx047a2873b3948afb", "泊泊车-公众号"),
+    HJZHPT_APP_OFFICIAL("wx7fb754b20e275d1f", "火炬智慧平台-公众号"),
+    HJGWH_APP_TEST("wx306ce81471effaf0", "厦门火炬智慧云平台-生产小程序"),
+    HJJT_APP_TEST("wx306ce81471effaf0", "厦门火炬智慧云平台-生产小程序"),
+    HJJTFK_APP("wxc93911f775dcf247", "火炬集团访客-生产"),
+    XMHJZHPT_APP("wxedcc666fd0b2f801", "厦门火炬智慧平台-生产小程序"),
+   ;
+
+    private String code;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(String code) {
+        AppEnum[] enumArray = AppEnum.values();
+        for (AppEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 38 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/AppPrivacyEnum.java

@@ -0,0 +1,38 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import cn.hutool.core.util.StrUtil;
+import com.thinkunion.park.service.common.enums.wechat.OfficialTempEnum;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author zhouhanwei
+ * @create 2024/1/19 11:59
+ */
+@Getter
+@AllArgsConstructor
+public enum AppPrivacyEnum {
+
+    XMHJZHYPT_APPLET("wx306ce81471effaf0", "厦门火炬智慧云平台", "智慧平台"),
+    XMHJZHPT_APPLET("wxedcc666fd0b2f801", "厦门火炬智慧平台", "智慧平台"),
+    JHCZ__APPLET("wxc1e73c5498c82608", "聚合场站", "聚合场站"),
+    YCY__APPLET("wx908e9848a2667637", "钰辰云", "智慧平台"),
+
+        ;
+    private final String appId;
+
+    private final String appName;
+
+    private final String desc;
+
+    public static String getEnumDesc(String appId) {
+        if (StrUtil.isNotBlank(appId)) {
+            for (AppPrivacyEnum e : AppPrivacyEnum.values()) {
+                if (e.getAppId().equals(appId)) {
+                    return e.getDesc();
+                }
+            }
+        }
+        return "智慧平台";
+    }
+}

+ 39 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ApplySourceEnum.java

@@ -0,0 +1,39 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 申请来源(0后台添加、1用户申请)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum ApplySourceEnum {
+
+
+    BACKGROUND_ADD(0, "后台添加"),
+    USER_APPLICATION(1, "用户申请"),
+    IMPORT(2, "后台导入"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        ApplySourceEnum[] enumArray = ApplySourceEnum.values();
+        for (ApplySourceEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 43 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CarTypeEnum.java

@@ -0,0 +1,43 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 车辆类型枚举
+ * @author LLC
+ */
+@AllArgsConstructor
+public enum CarTypeEnum {
+
+
+    TEMPORARY_CAR("0", "临时车"),
+    MONTH_CAR("1", "月卡车"),
+    STAGGERED_CAR("2", "错时车"),
+    CHANGE_CAR("3", "动态车"),
+    AB_CAR("4", "AB车"),
+/*    PROPERTY_CAR("4", "产权车"),
+    FIXED_CAR("5", "固定车"),*/
+   ;
+
+    private String code;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(String code) {
+        CarTypeEnum[] enumArray = CarTypeEnum.values();
+        for (CarTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 40 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CerStatusEnum.java

@@ -0,0 +1,40 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 认证状态:0未认证,1已认证,2已过期(V-rebuild1.0新增),3认证中
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum CerStatusEnum {
+
+
+    UNCERTIFIED(0, "未认证"),
+    CERTIFIED(1, "已认证"),
+    EXPIRED(2,"已过期"),
+    AUTHENTICATING(3,"认证中"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        CerStatusEnum[] enumArray = CerStatusEnum.values();
+        for (CerStatusEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 45 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ChargePlaceEnum.java

@@ -0,0 +1,45 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * cee8a0c0-38d8-11ed-b75c-2b79dedf07db  4号车位
+ * cee8a08e-38d8-11ed-b75b-ef9375302500  3号车位
+ * cee8a020-38d8-11ed-b75a-173468cba460  2号车位
+ * cee89e72-38d8-11ed-b759-63a2426b2294  1号车位
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum ChargePlaceEnum {
+
+    //地库异常出场,地面正常结算时地库账单记录这个编码
+    ONE("cee89e72-38d8-11ed-b759-63a2426b2294", "1号车位"),
+    //地库异常出场,地面正常结算时地面账单记录这个编码
+    TWO("cee8a020-38d8-11ed-b75a-173468cba460", "2号车位"),
+    THREE("cee8a08e-38d8-11ed-b75b-ef9375302500", "3号车位"),
+    FOUR("cee8a0c0-38d8-11ed-b75c-2b79dedf07db", "4号车位"),
+
+   ;
+
+    private String code;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(String code) {
+        ChargePlaceEnum[] enumArray = ChargePlaceEnum.values();
+        for (ChargePlaceEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return code;
+    }
+}

+ 44 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ChargeRuleEnum.java

@@ -0,0 +1,44 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 刘通
+ * @version 1.0
+ * @date 2021/4/16 16:27
+ * 0 其他车; 1 小型车; 2 大型车; 3 摩托车; 4 全部
+ */
+public enum ChargeRuleEnum {
+    /**
+     * 其他车
+     */
+    OTHER("0"),
+
+    /**
+     * 小型车
+     */
+    SMALL("1"),
+
+    /**
+     * 大型车
+     */
+    BIG("2"),
+
+    /**
+     * 摩托车motorcycle
+     */
+    MOTORCYCLE("3"),
+    /**
+     * 全部
+     */
+    All("-1");
+
+
+    private String value;
+
+    ChargeRuleEnum(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}

+ 26 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CouponEnum.java

@@ -0,0 +1,26 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 陈晖
+ * @version 1.0
+ * @date 2021/9/15 17:37
+ */
+public enum CouponEnum {
+    Parking("停车优惠",1);
+
+    private String name;
+    private int value;
+
+    CouponEnum(String name, int value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName(){
+        return name;
+    }
+
+    public int getValue(){
+        return value;
+    }
+}

+ 28 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/CouponStatusEnum.java

@@ -0,0 +1,28 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 陈晖
+ * @version 1.0
+ * @date 2021/9/15 17:55
+ */
+public enum CouponStatusEnum {
+    NOT_USE("未使用",0),
+    USED("已使用",1);
+
+    private String description;
+    private int value;
+
+    CouponStatusEnum(String description, int value){
+        this.description = description;
+        this.value = value;
+    }
+
+    public String getDescription(){
+        return description;
+    }
+
+    public int getValue(){
+        return value;
+    }
+
+}

+ 39 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/DeptApplySourceEnum.java

@@ -0,0 +1,39 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 组织申请来源(0后台添加、1小程序申请,2公众号申请)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum DeptApplySourceEnum {
+
+
+    BACKGROUND_ADD(0, "后台添加"),
+    APPLET_REQUEST(1, "小程序申请"),
+    PUBLIC_ACCOUNT_APPLICATION(2, "公众号申请"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        DeptApplySourceEnum[] enumArray = DeptApplySourceEnum.values();
+        for (DeptApplySourceEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 40 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/DiscountTypeEnum.java

@@ -0,0 +1,40 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 优惠类型
+ * 1:固定优惠金额
+ * 2:全免优惠金额
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum DiscountTypeEnum {
+
+
+    FIXED_DISCOUNT_AMOUNT(1, "固定优惠金额"),
+    FULL_DISCOUNT_AMOUNT_FREE(2, "全免优惠金额"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        DiscountTypeEnum[] enumArray = DiscountTypeEnum.values();
+        for (DiscountTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 40 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/EnergyTypeEnum.java

@@ -0,0 +1,40 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 车辆类型(0:其他车、1:小型车、2:大型车、3:摩托车)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum EnergyTypeEnum {
+
+
+    OTHER_CARS(0, "其他车"),
+    SMALL_CAR(1, "小型车"),
+    LARGE_CAR(2, "大型车"),
+    MOTORCYCLE(3, "摩托车"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        EnergyTypeEnum[] enumArray = EnergyTypeEnum.values();
+        for (EnergyTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 46 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/GateLedContentEnum.java

@@ -0,0 +1,46 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+
+/**
+ * @author 黄辉
+ * @version 1.0
+ * @date 2021/5/26 11:20
+ */
+public enum GateLedContentEnum {
+    ENTER_WELCOME("欢迎光临"),
+    /**
+     * 无车牌禁止自动放行
+     */
+    ANONYMOUS_PLATE_NO_ENTER_FORBID_CONTENT("无车牌禁止自动放行"),
+    ANONYMOUS_PLATE_NO_EXIT_FORBID_CONTENT("无车牌请在公众号出园放行"),
+    TEMPORARY_CAR_PASS_ALLOWED("临停放行"),
+    INSIDE_CAR_PASS_ALLOWED("内部车放行"),
+    PARKING_IS_FULL("车位已满"),
+    GROUP_OUT_TIME("群组不在规定的放行时段"),
+    UNLICENSED_CARS("无牌车"),
+    GROUP_CAR_PASS_FORBID("群组设置禁止放行"),
+    GROUP_CAR_NEED_TO_PAY_YUAN("群组需缴费%s元"),
+    GROUP_CAR_PAID_RELEASE("群组车已缴费放行"),
+    NO_PLATE_NOT_PASS("无车牌禁止自动放行"),
+    LEFT_SPACE("余位%s"),
+
+    TEAM_PASS_ALLOWED("团队车放行"),
+
+    SHARE_PLACE_PASS_ALLOWED("AB车位放行"),
+    VISITOR_CAR_PASS_ALLOWED("访客车放行"),
+    TEAM_PLACE_PASS_ALLOWD("团队车位放行"),
+
+    PLACE_IDLE_COST_LED("需缴占位费%s元"),
+
+
+    ;
+    private String value;
+
+    GateLedContentEnum(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}

+ 22 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/GateVoiceContentEnum.java

@@ -0,0 +1,22 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+
+/**
+ * @author 黄辉
+ * @version 1.0
+ * @date 2021/5/26 11:20
+ */
+public enum GateVoiceContentEnum {
+    EXIT_WELCOME_BACK("一路顺风"),
+
+    ;
+    private String value;
+
+    GateVoiceContentEnum(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}

+ 50 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/NumberEnum.java

@@ -0,0 +1,50 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 刘通
+ * @version 1.0
+ * @date 2021/3/17 19:43
+ */
+public enum NumberEnum {
+    ZERO(0),
+
+    ONE(1),
+
+    TWO(2),
+
+    THREE(3),
+
+    FOUR(4),
+
+    FIVE(5),
+
+    SIX(6),
+
+    SEVEN(7),
+
+    EIGHT(8),
+
+    NINE(9),
+
+    TEN(10),
+
+    FOURTEEN(14),
+
+    FIFTEEN(15),
+
+    TWENTY_NINE(29),
+
+    THIRTY(30),;
+
+
+    private int value;
+
+    NumberEnum(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+}

+ 38 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkBillLogExceptionTypeEnum.java

@@ -0,0 +1,38 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+
+@AllArgsConstructor
+public enum ParkBillLogExceptionTypeEnum {
+
+
+    GATE_AND_PARKING_SPACE(0, "闸门与车位事件时间冲突异常"),
+    EVENT_TIME_ERROR(1, "事时间重叠或者闭环缺失(进出成对存在)"),
+    NUMBER_OF_CHARGING_VEHICLE(2, "充电车牌号填错"),
+    PARKING_SPACE_CHARGING_ERROR(3, "车牌在本车位的事件时间里有其他车位的充电记录"),
+    CHARGING_ERROR(4, "没停车事件但是有充电记录"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        ParkBillLogExceptionTypeEnum[] enumArray = ParkBillLogExceptionTypeEnum.values();
+        for (ParkBillLogExceptionTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 52 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkIdEnum.java

@@ -0,0 +1,52 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import com.google.common.collect.Lists;
+import lombok.AllArgsConstructor;
+
+import java.util.List;
+
+/**
+ *
+ *
+ */
+@AllArgsConstructor
+public enum ParkIdEnum {
+
+
+    TXYQ(1371400533973180417L, "同翔一期-地面"),
+    TXYQ_DM(1371400533973170001L, "同翔一期-地库"),
+    BFTY(1405484512917372929L, "八方通用厂房"),
+    JGZX(1407312494715768834L, "火炬加工中心"),
+   ;
+
+    private Long code;
+
+    public Long getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Long code) {
+        ParkIdEnum[] enumArray = ParkIdEnum.values();
+        for (ParkIdEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+
+    public static List<Long> getCodeList() {
+        ParkIdEnum[] enumArray = ParkIdEnum.values();
+        List<Long> list= Lists.newArrayList();
+        for (ParkIdEnum e : enumArray) {
+            list.add(e.code);
+        }
+        return list;
+    }
+}

+ 42 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkingBillExceptionTypeEnum.java

@@ -0,0 +1,42 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 针对场中场地库异常出场处理枚举
+ *
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum ParkingBillExceptionTypeEnum {
+
+    //地库异常出场,地面正常结算时地库账单记录这个编码
+    PRESENCE_OF_ABNORMAL_OUTPUT(1, "存在异常出场"),
+    //地库异常出场,地面正常结算时地面账单记录这个编码
+    VEHICLE_READY_FOR_DEPARTURE(2, "检测到车辆准备出场,关联账单存在异常,请及时处理。处理完成之后,当前账单费用将自动更新。"),
+    UNCLEARED_ENTER_AGAIN(3, "存在未结清账单,再次入场"),
+
+    ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        ParkingBillExceptionTypeEnum[] enumArray = ParkingBillExceptionTypeEnum.values();
+        for (ParkingBillExceptionTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 71 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ParkingCarEventEnum.java

@@ -0,0 +1,71 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 陈晖
+ * @version 1.0
+ * @date 2021/5/27 10:40
+ * @Description: 关于车辆事件的一些标识
+ */
+
+
+public enum ParkingCarEventEnum {
+
+    /**
+     * 进场压线事件:car_in_on_line_event
+     */
+    CAR_IN_ON_LINE_EVENT("car_in_on_line_event"),
+    /**
+     * 进场放行事件:car_in_event
+     */
+    CAR_IN_EVENT("car_in_event"),
+    /**
+     * 出厂压线事件:car_out_on_line_event
+     */
+    CAR_OUT_ON_LINE_EVENT("car_out_on_line_event"),
+    /**
+     * 出厂放行时间:car_out_event
+     */
+    CAR_OUT_EVENT("car_out_event"),
+
+    /**
+     * 压线事件:1
+     */
+    DETECT_WITHOUT_PICTURE("1"),
+
+    /**
+     * 图片事件:2
+     */
+    DETECT_WITH_PICTURE("2"),
+
+    /**
+     * 入场事件:3
+     */
+    ENTER_PASS_EVENT("3"),
+
+    /**
+     * 出场事件:4
+     */
+    EXIT_PASS_EVENT("4"),
+
+    /**
+     * 车牌矫正:5
+     */
+    PLATE_CORRECT("5"),
+
+    /**
+     * 图片重传:6
+     */
+    IMAGE_CORRECT("6");
+
+
+
+    private String value;
+
+    ParkingCarEventEnum(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}

+ 69 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PassRuleEnum.java

@@ -0,0 +1,69 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 黄辉
+ * @version 1.0
+ * @date 2021/5/27 18:45
+ * <p>
+ * 放行状态码
+ */
+@Deprecated
+public enum PassRuleEnum {
+
+
+    /**
+     * 固定车自动放行
+     */
+    TIME_PERIOD_PASS(101),
+    /**
+     * 临时车自动放行
+     */
+    TEMPORARY_PASS(202),
+    /**
+     * 节假日自动放行
+     */
+    HOLIDAYS_PASS(303),
+    /**
+     * 特殊车辆自动放行
+     */
+    SPECIAL_PASS(404),
+    /**
+     * 黑名单不放行
+     */
+    FIVE(505),
+    /**
+     * 群组车自动放行
+     */
+    SIX(606),
+    /**
+     * 车位满了禁止放行
+     */
+    SEVEN(707),
+    /**
+     * 收费为0禁止放行
+     */
+    EIGHT(808),
+    /**
+     * 未知原因
+     */
+    NINE(909),
+    /**
+     * 无牌车自动放行
+     */
+    TEN(1010),
+    /**
+     * 未交费不放行
+     */
+    ELEVEN(1111);
+
+
+    private int value;
+
+    PassRuleEnum(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return value;
+    }
+}

+ 25 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PayTypeEnum.java

@@ -0,0 +1,25 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 陈晖
+ * @version 1.0
+ * @date 2021/5/27 19:20
+ */
+public enum PayTypeEnum {
+    WECHAT("微信支付","WHCHAT_JSAPI"),ALI("支付宝支付","ali_pay"),UNKNOW("支付类型未知","pay type unknow");
+
+    private String name;
+    private String value;
+
+    PayTypeEnum(String name, String value){
+        this.value = value;
+        this.name = name;
+    }
+    public String getValue() {
+        return value;
+    }
+    public String getName(){
+        return name;
+    }
+
+}

+ 48 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/PlaceUsedTypeEnum.java

@@ -0,0 +1,48 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 车辆类型枚举
+ * @author LLC
+ */
+@AllArgsConstructor
+public enum PlaceUsedTypeEnum {
+
+
+
+//    MONTH_CAR_PLACE("1", "月卡车车位"),
+//    STAGGERED_CAR_PLACE("2", "错时车位"),
+//    CHANGE_CAR_PLACE("3", "动态车位"),
+//    AB_CAR_PLACE("4", "AB车位"),
+//    PROPERTY_CAR_PLACE("4", "产权车"),
+//    FIXED_CAR_PLACE("5", "内部车"),
+    MONTH_CAR_PLACE("1", "月卡车位"),
+    STAGGERED_CAR_PLACE("2", "错时车位"),
+    FIXED_CAR_PLACE("3", "内部车"),
+    PROPERTY_CAR_PLACE("4", "产权车"),
+    TEMPORARY_CAR_PLACE("5", "临时车"),
+   ;
+
+    private String code;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(String code) {
+        PlaceUsedTypeEnum[] enumArray = PlaceUsedTypeEnum.values();
+        for (PlaceUsedTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 60 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ProportionEnum.java

@@ -0,0 +1,60 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 颜艺波
+ * @date 2021/11/16 18:22
+ * @Description 物业分成比例枚举
+ */
+public enum ProportionEnum {
+
+    ZERO("", 0.0, "0%"),
+    /**
+     * 艾德物业分成
+     */
+    AIDE("艾德停车场", 0.3, "30%"),
+    /**
+     * 通用厂房-地面
+     */
+    GROUND_PLANT("通用厂房-地面", 0.0, "0%"),
+    /**
+     * 通用厂房-地库
+     */
+    UNDER_PLANT("通用厂房-地库", 0.3, "30%"),
+    /**
+     * 五州停车场
+     */
+    WU("五洲停车场", 0.3, "30%");
+    /**
+     * 停车场名称
+     */
+    private String parkingName;
+
+    /**
+     * 分成比率,不带%
+     */
+    private double rate;
+
+    /**
+     * 分成比率,带%
+     */
+    private String ratePercentage;
+
+    public String getParkingName() {
+        return parkingName;
+    }
+
+    public double getRate() {
+        return rate;
+    }
+
+    public String getRatePercentage() {
+        return ratePercentage;
+    }
+
+    ProportionEnum(String parkingName, double rate, String ratePercentage) {
+        this.parkingName = parkingName;
+        this.rate = rate;
+        this.ratePercentage = ratePercentage;
+    }
+
+}

+ 67 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/ReviewStateEnum.java

@@ -0,0 +1,67 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 审核状态(0 待审核 1 审核通过 2 拒绝,3进行中)
+ * @author CXJ
+ */
+@Getter
+@AllArgsConstructor
+public enum ReviewStateEnum {
+
+
+    TO_BE_REVIEWED(0, "待审核","0",0),
+    PASS_THE_AUDIT(2, "审核通过","2",2),
+    REFUSED(4, "拒绝","4",4),
+    RUNNING(1, "进行中","1",1),
+    WITHDRAWN(3, "已撤回","3",3),
+   ;
+
+    private final Integer code;
+
+
+    private final String description;
+
+    /**
+     * 审批流的结果(审批流对应业务的结果)
+     */
+    private final String actStateCode;
+
+    private final Integer flowStateCode;
+
+
+    public static String getDescByCode(Integer code) {
+        ReviewStateEnum[] enumArray = ReviewStateEnum.values();
+        for (ReviewStateEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+
+    /**
+     * 根据审批流本身的结果转换成业务的结果
+     */
+    public static Integer getCodeByActStateCode(String actState) {
+        ReviewStateEnum[] enumArray = ReviewStateEnum.values();
+        for (ReviewStateEnum e : enumArray) {
+            if (e.getActStateCode().equals(actState)) {
+                return e.getCode();
+            }
+        }
+        return null;
+    }
+
+    public static Integer getCodeByFlowStateCode(Integer nodeStatus) {
+        ReviewStateEnum[] enumArray = ReviewStateEnum.values();
+        for (ReviewStateEnum e : enumArray) {
+            if (e.getFlowStateCode().equals(nodeStatus)) {
+                return e.getCode();
+            }
+        }
+        return null;
+    }
+}

+ 73 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/TicketCauseContent.java

@@ -0,0 +1,73 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+
+/**
+ * @author 周光耀
+ * @version 1.0
+ * @date 2021/9/14 16:20
+ * 车牌类型(0:标准民用车,1:02式民用车牌,2:武警车车牌,3:警车车牌,4:民用车双行尾牌,5:使馆车牌,6:农用车车牌,7:摩托车,8:新能源车,13:军车车牌)
+ */
+public enum TicketCauseContent {
+
+    IDENTIFICATION_PASS_FORBID("未识别不放行"),
+    TEMPORARY_CAR_PASS_FORBID("临停不放行"),
+    VISITOR_CAR_PASS_FORBID("访客车不放行"),
+    BLACK_CAR_PASS_FORBID("黑名单不放行"),
+    BLACK_CAR_PASS("黑名单放行"),
+    TEMPORARY_CAR_PARKING_SPACE_IS_FULL_PASS_FORBID("临停车位满不放行"),
+    TEMPORARY_CAR_PARKING_FIXED_SPACE_IS_FULL_PASS_FORBID("固定车位满不放行"),
+    TEMPORARY_CAR_CHARGE_OF_0_PASS_FORBID("临停收费为0不放行"),
+    TEMPORARY_CAR_DID_NOT_PAY_PASS_FORBID("临停未缴费不放行"),
+    TEMPORARY_TIME_FREE_NEED_PAY_PASS_FORBID("错时临停需缴费%s元"),
+    TEMPORARY_TIME_FREE_NOT_PAY_PASS_FORBID("错时临停未缴费不放行"),
+    ON_THE_TRUCK_PARKING_SPACE_IS_FULL_PASS_FORBID("月卡车位满不放行"),
+    ON_THE_TRUCK_CHARGE_OF_0_PASS_FORBID("月卡收费为0不放行"),
+    NEED_TO_PAY_YUAN("需缴费%s元"),
+    MONTHLY_REMAINING_DAYS("有效期: 剩余%s天"),
+    HOLIDAYS_FREE_PASS_ALLOWD("节假日免费放行"),
+    SPECIAL_CAR_PASS_ALLOWED("特殊车牌放行"),
+    VEHICLE_GROUP_PASS_ALLOWED("车组放行"),
+    SHARE_PLACE_PASS_ALLOWED("AB车位放行"),
+    VEHICLE_GROUP_PASS_FORBID("车组禁止放行"),
+    SPC_BLACK_CAR_PASS_FORBID("电站黑名单不放行"),
+    /**
+     * 请在公众号入园放行
+     */
+    ANONYMOUS_PLATE_NO_ENTER_FORBID_CONTENT("请在公众号入园放行"),
+    ANONYMOUS_PLATE_NO_EXIT_FORBID_CONTENT("请在公众号出园放行"),
+    TEMP_PASS("临停放行"),
+    PUBLIC_ACCOUNT_AUTOMATIC_RELEASE("公众号放行"),
+    TEMP_NOT_PAY("临停未缴费"),
+    TEMP_PAYED("临停已缴费"),
+    TEMP_FREE_TIME("临停免费时间"),
+    MONTH_CAR("有效月卡"),
+
+    TIME_FREE_CAR("有效错时卡"),
+    GROUP_FREE("固定车免费"),
+    NOT_IN_EVENT("无入场时间"),
+    GLOBAL_FREE_PASS("暂未收费免费放行"),
+    LOGIC_ABNORMAL("业务异常自动放行"),
+
+    TEAM_PASS_ALLOWD("团队车放行"),
+    SHARE_PLACE_PASS_ALLOWD("AB车位放行"),
+    TEAM_PLACE_PASS_ALLOWD("团队车位放行"),
+    TIME_FREE_PASS_ALLOWD("错时车放行"),
+    PROPERTY_RIGHT_PASS_ALLOWD("产权车放行"),
+    INSIDE_CAR_PASS_ALLOWD("内部车放行"),
+    FREE_PASS_ALLOWD("免费放行"),
+    VISITOR_PASS_ALLOWD("访客车放行"),
+    ;
+
+    private String value;
+
+
+    TicketCauseContent(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+
+}

+ 39 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/VehicleGroupEnum.java

@@ -0,0 +1,39 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 车辆分组(1 月卡车 2 错时车 3 临时车)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum VehicleGroupEnum {
+
+
+    THE_MOON_CAR(1, "月卡车"),
+    WRONG_TIME_CAR(2, "错时车"),
+    TEMPORARY_CAR(3, "临时车"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        VehicleGroupEnum[] enumArray = VehicleGroupEnum.values();
+        for (VehicleGroupEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 39 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/VehicleTypeEnum.java

@@ -0,0 +1,39 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * 能源类型(0:其他类型、1:汽油车、2:新能源)
+ * @author CXJ
+ */
+@AllArgsConstructor
+public enum VehicleTypeEnum {
+
+
+    OTHER(0, "其他类型"),
+    GASOLINE_CAR(1, "汽油车"),
+    NEW_ENERGY(2, "新能源"),
+   ;
+
+    private Integer code;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    private String description;
+
+    public static String getDescByCode(Integer code) {
+        VehicleTypeEnum[] enumArray = VehicleTypeEnum.values();
+        for (VehicleTypeEnum e : enumArray) {
+            if (e.getCode().equals(code)) {
+                return e.getDescription();
+            }
+        }
+        return "";
+    }
+}

+ 21 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/parking/WeiXinMessageEnum.java

@@ -0,0 +1,21 @@
+package com.thinkunion.park.service.common.enums.parking;
+
+/**
+ * @author 陈晖
+ * @version 1.0
+ * @date 2021/9/15 17:37
+ */
+public enum WeiXinMessageEnum {
+
+    PARKING_EXIT("您的车已驶出停车场");
+
+    private String content;
+
+    WeiXinMessageEnum(String content) {
+        this.content = content;
+    }
+
+    public String getContent() {
+        return content;
+    }
+}

+ 47 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/enums/wechat/OfficialTempEnum.java

@@ -0,0 +1,47 @@
+package com.thinkunion.park.service.common.enums.wechat;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author zhouhanwei
+ * @create 2024/1/5 16:59
+ */
+@Getter
+@AllArgsConstructor
+public enum OfficialTempEnum {
+
+    PARKING_IN_OUT_TEMP_MESSAGE("parking_in_out_temp_message"),
+
+    PARKING_BUSINESS_TRANSACT_TEMP_MESSAGE("parking_business_transact_temp_message"),
+    CHARGING_START_TEMP_MESSAGE("charging_start_temp_message"),
+    CHARGING_STOP_TEMP_MESSAGE("charging_stop_temp_message"),
+
+
+
+
+
+    PAY_SUCCEED_TEMP_MESSAGE("pay_succeed_temp_message"),
+
+    REFUND_SUCCEED_TEMP_MESSAGE("refund_succeed_temp_message"),
+
+    CHARGING_OCCUPY_TEMP_MESSAGE("charging_occupy_temp_message"),
+    CHARGING_DEVICE_WARN_TEMP_MESSAGE("charging_device_warn_message"),
+    PROPERTY_BILL_REMINDER_MESSAGE("property_bill_reminder_message"),//催缴(物业账单)
+    ;
+
+    private final String tempCode;
+
+    public static OfficialTempEnum getEnum(String tempCode) {
+        if (StrUtil.isNotBlank(tempCode)) {
+            for (OfficialTempEnum e : OfficialTempEnum.values()) {
+                if (e.getTempCode().equals(tempCode)) {
+                    return e;
+                }
+            }
+        }
+        return null;
+    }
+
+}

+ 132 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/api/DeviceBasicData.java

@@ -0,0 +1,132 @@
+package com.thinkunion.park.service.common.iot.capability.api;
+
+import com.thinkunion.park.service.common.iot.util.TextHelper;
+
+public class DeviceBasicData implements Cloneable {
+
+    private String modelType;
+    private String pk;
+    private String name;
+    private transient String desc;
+    private transient String addr;
+    private transient String deviceModelJson;
+    private transient String iotId;
+    private transient int port;
+    private transient boolean isLocal;
+
+    public DeviceBasicData() {
+        this.isLocal = false;
+    }
+
+    public DeviceBasicData(boolean isLocal) {
+        this.isLocal = isLocal;
+    }
+
+    public DeviceBasicData(DeviceBasicData basicData) {
+        this.modelType = basicData.modelType;
+        this.pk = basicData.getPk();
+        this.name = basicData.getName();
+        this.desc = basicData.getDesc();
+        this.addr = basicData.getAddr();
+        this.deviceModelJson = basicData.getDeviceModelJson();
+        this.iotId = basicData.getIotId();
+        this.port = basicData.getPort();
+        this.isLocal = basicData.isLocal;
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public String getProdKey() {
+        return this.getPk();
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public void setProdKey(String prodKey) {
+        this.setPk(prodKey);
+    }
+
+    public int getPort() {
+        return this.port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+        return super.clone();
+    }
+
+    public boolean isLocal() {
+        return this.isLocal;
+    }
+
+    public void setLocal(boolean local) {
+        this.isLocal = local;
+    }
+
+    public String getDeviceModelJson() {
+        return this.deviceModelJson;
+    }
+
+    public void setDeviceModelJson(String deviceModelJson) {
+        this.deviceModelJson = deviceModelJson;
+    }
+
+    public String getAddr() {
+        return this.addr;
+    }
+
+    public void setAddr(String addr) {
+        this.addr = addr;
+    }
+
+    public String getModelType() {
+        return this.modelType;
+    }
+
+    public void setModelType(String model) {
+        this.modelType = model;
+    }
+
+    public String getPk() {
+        return this.pk;
+    }
+
+    public void setPk(String pk) {
+        this.pk = pk;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDevId() {
+        return TextHelper.combineStr(this.getPk(), this.getName());
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public String getIotId() {
+        return this.iotId;
+    }
+
+    public void setIotId(String iotId) {
+        this.iotId = iotId;
+    }
+}

+ 117 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/discovery/DiscoveryResponsePayload.java

@@ -0,0 +1,117 @@
+package com.thinkunion.park.service.common.iot.capability.device.discovery;
+
+import com.google.gson.*;
+import com.thinkunion.park.service.common.iot.capability.api.DeviceBasicData;
+import com.thinkunion.park.service.common.iot.capability.device.payload.CommonResponsePayload;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.Profile;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+public class DiscoveryResponsePayload extends CommonResponsePayload<DiscoveryResponsePayload.DiscoveryResponseData> {
+
+    protected static final String TAG = "[Tmp]DiscoveryResponsePayload";
+
+    public DiscoveryResponsePayload() {
+    }
+
+    public DeviceBasicData getDeviceInfo() {
+        return this.data == null ? null : this.data.getDeviceBasicData();
+    }
+
+    public String getDeviceModel() {
+        return this.data.getDeviceModel();
+    }
+
+    public static class DiscoveryResponseDataDeserializer implements
+            JsonDeserializer<DiscoveryResponseData> {
+
+        public DiscoveryResponseDataDeserializer() {
+        }
+
+        public DiscoveryResponseData deserialize(JsonElement json, Type typeOfT,
+                                                 JsonDeserializationContext context) throws JsonParseException {
+            DiscoveryResponseData responseData = null;
+            if (json == null) {
+                return responseData;
+            } else if (!json.isJsonObject()) {
+                return responseData;
+            } else {
+                responseData = new DiscoveryResponseData();
+                JsonObject dataObject = json.getAsJsonObject();
+                JsonElement deviceModelEle = dataObject.get("deviceModel");
+                if (deviceModelEle != null && deviceModelEle.isJsonObject()) {
+                    JsonObject deviceModelObj = deviceModelEle.getAsJsonObject();
+                    JsonElement profileEle = deviceModelObj.get("info");
+                    Profile profile = null;
+                    if (profileEle != null) {
+                        profile = (Profile) context.deserialize(profileEle, Profile.class);
+                    }
+
+                    if (profile != null) {
+                        DeviceBasicData basicData = new DeviceBasicData();
+                        basicData.setPk(profile.getProductKey());
+                        basicData.setName(profile.getVersion());
+                        basicData.setLocal(true);
+                        responseData.setDeviceBasicData(basicData);
+                    }
+
+                    JsonElement propEle = deviceModelObj.get("props");
+                    JsonElement serviceEle = deviceModelObj.get("services");
+                    JsonElement eventEle = deviceModelObj.get("events");
+                    if (propEle != null && propEle.isJsonArray() || serviceEle != null && serviceEle.isJsonArray()
+                            || eventEle != null && eventEle.isJsonArray()) {
+                        responseData.setDeviceModel(deviceModelEle.toString());
+                    } else {
+                        // TODO
+                    }
+                }
+
+                JsonElement devices = dataObject.get("devices");
+                if (devices != null) {
+                    MulDevicesData mulDevicesData = (MulDevicesData) context
+                            .deserialize(devices, MulDevicesData.class);
+                    responseData.devices = mulDevicesData;
+                }
+
+                return responseData;
+            }
+        }
+    }
+
+    public static class MulDevicesData {
+
+        public String addr;
+        public int port;
+        public List<Profile> profile;
+
+        public MulDevicesData() {
+        }
+    }
+
+    public static class DiscoveryResponseData {
+
+        protected String deviceModel;
+        protected DeviceBasicData deviceBasicData;
+        public MulDevicesData devices;
+
+        public DiscoveryResponseData() {
+        }
+
+        public String getDeviceModel() {
+            return this.deviceModel;
+        }
+
+        public void setDeviceModel(String deviceModel) {
+            this.deviceModel = deviceModel;
+        }
+
+        public DeviceBasicData getDeviceBasicData() {
+            return this.deviceBasicData;
+        }
+
+        public void setDeviceBasicData(DeviceBasicData deviceBasicData) {
+            this.deviceBasicData = deviceBasicData;
+        }
+    }
+}

+ 122 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/CommonRequestPayload.java

@@ -0,0 +1,122 @@
+package com.thinkunion.park.service.common.iot.capability.device.payload;
+
+import com.google.gson.*;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Map;
+
+public class CommonRequestPayload<T> {
+    protected String sessionKey;
+    protected String id;
+    protected String version;
+    protected String method;
+    protected T params;
+
+    public CommonRequestPayload(String productKey, String deviceName) {
+        this();
+    }
+
+    private CommonRequestPayload() {
+        this.version = "1.0";
+        this.id = String.valueOf((new SecureRandom()).nextInt(1000000000));
+    }
+
+    public T getParams() {
+        return this.params;
+    }
+
+    public void setParams(T params) {
+        this.params = params;
+    }
+
+    public String getSessionKey() {
+        return this.sessionKey;
+    }
+
+    public void setSessionKey(String sessionKey) {
+        this.sessionKey = sessionKey;
+    }
+
+    public String getVersion() {
+        return this.version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getMethod() {
+        return this.method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public static class CommonRequestPayloadJsonDeSerializer implements JsonDeserializer<CommonRequestPayload> {
+        public CommonRequestPayloadJsonDeSerializer() {
+        }
+
+        public CommonRequestPayload deserialize(JsonElement json, Type typeOfT,
+                                                JsonDeserializationContext context) throws JsonParseException {
+            if (json == null) {
+                return null;
+            } else {
+                CommonRequestPayload payload = null;
+                if (!json.isJsonObject()) {
+                    return payload;
+                } else {
+                    JsonObject payloadObject = json.getAsJsonObject();
+                    if (payloadObject == null) {
+                        return payload;
+                    } else {
+                        payload = new CommonRequestPayload();
+                        Object params = null;
+                        JsonElement paramsEle = payloadObject.get("params");
+                        if (paramsEle != null) {
+                            if (paramsEle.isJsonArray()) {
+                                params = context.deserialize(paramsEle, (new TypeToken<List<String>>() {
+                                }).getType());
+                            } else if (paramsEle.isJsonObject()) {
+                                params = context.deserialize(paramsEle, (new TypeToken<Map<String, ValueWrapper>>() {
+                                }).getType());
+                            } else {
+                                params = context.deserialize(paramsEle, (new TypeToken<Object>() {
+                                }).getType());
+                            }
+                        }
+
+                        payload.setParams(params);
+                        JsonElement idEle = payloadObject.get("id");
+                        if (idEle != null && idEle.isJsonPrimitive()) {
+                            payload.setId(idEle.getAsJsonPrimitive().getAsString());
+                        }
+
+                        JsonElement versionEle = payloadObject.get("version");
+                        if (versionEle != null && versionEle.isJsonPrimitive()) {
+                            payload.setVersion(versionEle.getAsJsonPrimitive().getAsString());
+                        }
+
+                        JsonElement methodEle = payloadObject.get("action");
+                        if (methodEle != null && methodEle.isJsonPrimitive()) {
+                            payload.setMethod(methodEle.getAsJsonPrimitive().getAsString());
+                        }
+
+                        return payload;
+                    }
+                }
+            }
+        }
+    }
+}

+ 47 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/CommonResponsePayload.java

@@ -0,0 +1,47 @@
+package com.thinkunion.park.service.common.iot.capability.device.payload;
+
+public class CommonResponsePayload<T> {
+    protected int code;
+    protected String id;
+    protected String message;
+    protected T data;
+
+    public CommonResponsePayload() {
+    }
+
+    public T getData() {
+        return this.data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public boolean isSuccess() {
+        return this.code >= 200 && this.code < 300;
+    }
+}

+ 136 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/KeyValuePair.java

@@ -0,0 +1,136 @@
+package com.thinkunion.park.service.common.iot.capability.device.payload;
+
+import com.google.gson.*;
+import com.thinkunion.park.service.common.iot.util.TextUtils;
+
+import java.lang.reflect.Type;
+import java.util.Iterator;
+import java.util.Set;
+
+public class KeyValuePair {
+
+    private String key;
+    private ValueWrapper valueWrapper;
+
+    public KeyValuePair(String name, ValueWrapper value) {
+        this.key = name;
+        this.valueWrapper = value;
+    }
+
+    public KeyValuePair(String name, int value) {
+        this.key = name;
+        this.valueWrapper = new ValueWrapper.IntValueWrapper(value);
+    }
+
+    public KeyValuePair(String name, String value) {
+        this.key = name;
+        this.valueWrapper = new ValueWrapper.StringValueWrapper(value);
+    }
+
+    public KeyValuePair(String name, boolean value) {
+        this.key = name;
+        this.valueWrapper = new ValueWrapper.BooleanValueWrapper(value ? 1 : 0);
+    }
+
+    public String getKey() {
+        return this.key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public ValueWrapper getValueWrapper() {
+        return this.valueWrapper;
+    }
+
+    public void setValueWrapper(ValueWrapper valueWrapper) {
+        this.valueWrapper = valueWrapper;
+    }
+
+    public static class KeyValuePairJsonDeSerializer implements JsonDeserializer<KeyValuePair> {
+
+        public KeyValuePairJsonDeSerializer() {
+        }
+
+        public KeyValuePair deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+                throws JsonParseException {
+            if (json == null) {
+                return null;
+            } else {
+                KeyValuePair propertyPair = null;
+                if (!json.isJsonObject()) {
+                    return propertyPair;
+                } else {
+                    JsonObject jsonObject = json.getAsJsonObject();
+                    Set<String> keySet = jsonObject.keySet();
+                    if (keySet != null && jsonObject.size() >= 1) {
+                        Iterator var7 = keySet.iterator();
+
+                        while (var7.hasNext()) {
+                            String key = (String) var7.next();
+                            JsonElement valueElement = jsonObject.get(key);
+                            if (valueElement != null && !valueElement.isJsonNull() && valueElement.isJsonPrimitive()) {
+                                JsonPrimitive jsonPrimitive = (JsonPrimitive) valueElement;
+                                if (jsonPrimitive.isString()) {
+                                    String valueStr = valueElement.getAsString();
+                                    if (!TextUtils.isEmpty(valueStr)) {
+                                        propertyPair = new KeyValuePair(key, valueStr);
+                                        break;
+                                    }
+                                } else if (jsonPrimitive.isNumber()) {
+                                    Integer valueInt = valueElement.getAsInt();
+                                    if (valueInt != null) {
+                                        propertyPair = new KeyValuePair(key, valueInt);
+                                        break;
+                                    }
+                                } else if (jsonPrimitive.isBoolean()) {
+                                    Boolean valueBool = valueElement.getAsBoolean();
+                                    if (valueBool != null) {
+                                        propertyPair = new KeyValuePair(key, valueBool);
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+
+                        return propertyPair;
+                    } else {
+                        return propertyPair;
+                    }
+                }
+            }
+        }
+    }
+
+    public static class KeyValuePairJsonSerializer implements JsonSerializer<KeyValuePair> {
+
+        public KeyValuePairJsonSerializer() {
+        }
+
+        public JsonElement serialize(KeyValuePair src, Type typeOfSrc, JsonSerializationContext context) {
+            JsonObject jsonObject = null;
+            if (src == null) {
+                return jsonObject;
+            } else {
+                if (src != null && !TextUtils.isEmpty(src.getKey()) && src.getValueWrapper() != null) {
+                    jsonObject = new JsonObject();
+                    if ("int".equalsIgnoreCase(src.getValueWrapper().getType())) {
+                        ValueWrapper.IntValueWrapper intValue = (ValueWrapper.IntValueWrapper) src.getValueWrapper();
+                        jsonObject.addProperty(src.getKey(), intValue.getValue());
+                    } else if ("string".equalsIgnoreCase(src.getValueWrapper().getType())) {
+                        ValueWrapper.StringValueWrapper strValue = (ValueWrapper.StringValueWrapper) src
+                                .getValueWrapper();
+                        jsonObject.addProperty(src.getKey(), strValue.getValue());
+                    } else if ("bool".equalsIgnoreCase(src.getValueWrapper().getType())) {
+                        ValueWrapper.BooleanValueWrapper boolValue = (ValueWrapper.BooleanValueWrapper) src
+                                .getValueWrapper();
+                        jsonObject.addProperty(src.getKey(), boolValue.getValue());
+                    }
+                }
+
+                return jsonObject;
+            }
+        }
+    }
+}

+ 351 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/device/payload/ValueWrapper.java

@@ -0,0 +1,351 @@
+package com.thinkunion.park.service.common.iot.capability.device.payload;
+
+import com.google.gson.*;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.Map.Entry;
+
+public class ValueWrapper<T> {
+
+    private static final String TAG = "[Tmp]ValueWrapper";
+    protected String type;
+    protected T value;
+    private static Method isIntegralMethod = null;
+
+    public ValueWrapper(T valuePar) {
+        this.value = valuePar;
+    }
+
+    public ValueWrapper() {
+    }
+
+    public T getValue() {
+        return this.value;
+    }
+
+    public void setValue(T value) {
+        this.value = value;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String t) {
+        this.type = t;
+    }
+
+    public static boolean isIntegral(JsonPrimitive primitive) {
+        try {
+            if (isIntegralMethod == null) {
+                Class<?> threadClazz = Class.forName("com.google.gson.JsonPrimitive");
+                isIntegralMethod = threadClazz.getDeclaredMethod("isIntegral", JsonPrimitive.class);
+                isIntegralMethod.setAccessible(true);
+            }
+
+            return (Boolean) isIntegralMethod.invoke(JsonPrimitive.class, primitive);
+        } catch (Exception var2) {
+            var2.printStackTrace();
+            return false;
+        }
+    }
+
+    public static boolean isInteger(JsonPrimitive primitive) {
+        String numberStr = primitive.getAsString();
+        return !numberStr.contains(".") && !numberStr.contains("e") && !numberStr.contains("E");
+    }
+
+    public static class ValueWrapperJsonDeSerializer implements JsonDeserializer<ValueWrapper> {
+
+        public ValueWrapperJsonDeSerializer() {
+        }
+
+        public ValueWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+                throws JsonParseException {
+            if (json == null) {
+                return null;
+            } else {
+                ValueWrapper valueWrapper = null;
+                if (json.isJsonObject()) {
+                    StructValueWrapper structValueWrapper = new StructValueWrapper();
+                    JsonObject jsonObject = json.getAsJsonObject();
+                    Set<String> keySets = jsonObject.keySet();
+                    Iterator iterator = keySets.iterator();
+
+                    while (iterator.hasNext()) {
+                        String key = (String) iterator.next();
+                        structValueWrapper
+                                .addValue(key, context.deserialize(jsonObject.get(key), ValueWrapper.class));
+                    }
+
+                    valueWrapper = structValueWrapper;
+                } else if (json.isJsonArray()) {
+                    ArrayValueWrapper arrayValueWrapper = new ArrayValueWrapper();
+                    JsonArray jsonArray = json.getAsJsonArray();
+
+                    for (int i = 0; i < jsonArray.size(); ++i) {
+                        JsonElement jsonArrayElement = jsonArray.get(i);
+                        arrayValueWrapper.add(context.deserialize(jsonArrayElement, ValueWrapper.class));
+                    }
+
+                    valueWrapper = arrayValueWrapper;
+                } else if (json.isJsonPrimitive()) {
+                    JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
+                    if (jsonPrimitive == null) {
+                        return null;
+                    }
+
+                    if (jsonPrimitive.isBoolean()) {
+                        valueWrapper = new BooleanValueWrapper(jsonPrimitive.getAsInt());
+                    } else if (jsonPrimitive.isString()) {
+                        valueWrapper = new StringValueWrapper(jsonPrimitive.getAsString());
+                    } else if (jsonPrimitive.isNumber()) {
+                        if (ValueWrapper.isInteger(jsonPrimitive)) {
+                            valueWrapper = new IntValueWrapper(jsonPrimitive.getAsInt());
+                        } else {
+                            valueWrapper = new DoubleValueWrapper(jsonPrimitive.getAsDouble());
+                        }
+                    } else if (jsonPrimitive.isJsonObject()) {
+                        StructValueWrapper structValueWrapper = new StructValueWrapper();
+                        JsonObject jsonObject = jsonPrimitive.getAsJsonObject();
+                        Set<String> keySets = jsonObject.keySet();
+                        Iterator iterator = keySets.iterator();
+
+                        while (iterator.hasNext()) {
+                            String key = (String) iterator.next();
+                            structValueWrapper
+                                    .addValue(key, context.deserialize(jsonObject.get(key), ValueWrapper.class));
+                        }
+
+                        valueWrapper = structValueWrapper;
+                    }
+                }
+
+                return valueWrapper;
+            }
+        }
+    }
+
+    public static class ValueWrapperJsonSerializer implements JsonSerializer<ValueWrapper> {
+
+        public ValueWrapperJsonSerializer() {
+        }
+
+        public JsonElement serialize(ValueWrapper src, Type typeOfSrc, JsonSerializationContext context) {
+            JsonElement jsonElement = null;
+            if (src == null) {
+                return jsonElement;
+            } else {
+                if (src != null) {
+                    if (!"int".equalsIgnoreCase(src.getType()) && !"enum".equalsIgnoreCase(src.getType())) {
+                        if (!"string".equalsIgnoreCase(src.getType()) && !"date".equalsIgnoreCase(src.getType())) {
+                            if ("bool".equalsIgnoreCase(src.getType())) {
+                                jsonElement = new JsonPrimitive((Integer) src.getValue());
+                            } else if (!"double".equalsIgnoreCase(src.getType()) && !"float"
+                                    .equalsIgnoreCase(src.getType())) {
+                                Iterator iterator;
+                                if ("array".equalsIgnoreCase(src.getType())) {
+                                    List<ValueWrapper> objectList = (List) src.getValue();
+                                    JsonArray jsonArray = new JsonArray();
+                                    if (objectList != null && !objectList.isEmpty()) {
+                                        iterator = objectList.iterator();
+
+                                        while (iterator.hasNext()) {
+                                            ValueWrapper obj = (ValueWrapper) iterator.next();
+                                            jsonArray.add(context.serialize(obj, (new TypeToken<ValueWrapper>() {
+                                            }).getType()));
+                                        }
+                                    } else {
+                                        // TODO
+                                    }
+
+                                    jsonElement = jsonArray;
+                                } else if ("struct".equalsIgnoreCase(src.getType())) {
+                                    JsonObject jsonObject = new JsonObject();
+                                    StructValueWrapper structValueWrapper = (StructValueWrapper) src;
+                                    if (src.getValue() != null) {
+                                        iterator = structValueWrapper.getValue().entrySet().iterator();
+
+                                        while (iterator.hasNext()) {
+                                            Entry<String, ValueWrapper> entry = (Entry) iterator.next();
+                                            jsonObject.add(entry.getKey(),
+                                                    context.serialize(entry.getValue(), (new TypeToken<ValueWrapper>() {
+                                                    }).getType()));
+                                        }
+                                    }
+
+                                    jsonElement = jsonObject;
+                                } else {
+                                    jsonElement = context.serialize(src.getValue());
+                                }
+                            } else {
+                                jsonElement = new JsonPrimitive((Double) src.getValue());
+                            }
+                        } else {
+                            jsonElement = new JsonPrimitive((String) src.getValue());
+                        }
+                    } else {
+                        jsonElement = new JsonPrimitive((Integer) src.getValue());
+                    }
+                }
+
+                return jsonElement;
+            }
+        }
+    }
+
+    public static class StructValueWrapper extends ValueWrapper<Map<String, ValueWrapper>> {
+
+        public StructValueWrapper() {
+            this(new HashMap());
+        }
+
+        public StructValueWrapper(Map<String, ValueWrapper> valueParam) {
+            this.type = "struct";
+            this.value = valueParam;
+        }
+
+        public ValueWrapper addValue(String key, ValueWrapper valueWrapper) {
+            if (this.value == null) {
+                this.value = new HashMap();
+            }
+
+            return (ValueWrapper) ((Map) this.value).put(key, valueWrapper);
+        }
+
+        public Map<String, ValueWrapper> getValue() {
+            return (Map) this.value;
+        }
+
+        public void setValue(Map<String, ValueWrapper> valueList) {
+            this.value = valueList;
+        }
+    }
+
+    public static class ArrayValueWrapper extends ValueWrapper<List<ValueWrapper>> {
+
+        public ArrayValueWrapper() {
+            this.type = "array";
+        }
+
+        public ArrayValueWrapper(List<ValueWrapper> valueParam) {
+            this();
+            this.value = valueParam;
+        }
+
+        public List<ValueWrapper> getValue() {
+            return this.value;
+        }
+
+        public void add(ValueWrapper obj) {
+            if (this.value == null) {
+                this.value = new ArrayList();
+            }
+
+            (this.value).add(obj);
+        }
+
+        public void setValue(List<ValueWrapper> valueParam) {
+            this.value = valueParam;
+        }
+    }
+
+    public static class DoubleValueWrapper extends ValueWrapper<Double> {
+
+        public DoubleValueWrapper() {
+            this.type = "double";
+        }
+
+        public DoubleValueWrapper(Double valueParam) {
+            this();
+            this.value = valueParam;
+        }
+
+        public Double getValue() {
+            return (Double) this.value;
+        }
+
+        public void setValue(Double valueParam) {
+            this.value = valueParam;
+        }
+    }
+
+    public static class BooleanValueWrapper extends IntValueWrapper {
+
+        public BooleanValueWrapper() {
+            this.type = "bool";
+        }
+
+        public BooleanValueWrapper(Integer valueParam) {
+            this();
+            this.value = valueParam;
+        }
+    }
+
+    public static class StringValueWrapper extends ValueWrapper<String> {
+
+        public StringValueWrapper() {
+            this.type = "string";
+        }
+
+        public StringValueWrapper(String valuePar) {
+            this();
+            this.value = valuePar;
+        }
+
+        public String getValue() {
+            return (String) this.value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+
+    public static class EnumValueWrapper extends IntValueWrapper {
+
+        public EnumValueWrapper() {
+            this.type = "enum";
+        }
+
+        public EnumValueWrapper(int valuePar) {
+            this();
+            this.setValue(valuePar);
+        }
+    }
+
+    public static class DateValueWrapper extends StringValueWrapper {
+
+        public DateValueWrapper() {
+            this.type = "date";
+        }
+
+        public DateValueWrapper(String valuePar) {
+            this();
+            this.setValue(valuePar);
+        }
+    }
+
+    public static class IntValueWrapper extends ValueWrapper<Integer> {
+
+        public IntValueWrapper() {
+            this.type = "int";
+        }
+
+        public IntValueWrapper(int valueParam) {
+            this();
+            this.value = valueParam;
+        }
+
+        public Integer getValue() {
+            return this.value;
+        }
+
+        public void setValue(int value) {
+            this.value = value;
+        }
+    }
+}

+ 32 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Arg.java

@@ -0,0 +1,32 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+public class Arg {
+    private String name;
+    private String id;
+    private DataType data;
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public DataType getData() {
+        return this.data;
+    }
+
+    public void setData(DataType data) {
+        this.data = data;
+    }
+}
+

+ 114 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DataType.java

@@ -0,0 +1,114 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+import com.google.gson.*;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.ArrayRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.EnumRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.MetaRule;
+import com.thinkunion.park.service.common.iot.util.TextUtils;
+
+
+import java.lang.reflect.Type;
+
+public class DataType<T> {
+
+    private String type;
+    private T rules;
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public T getRules() {
+        return this.rules;
+    }
+
+    public void setRules(T rules) {
+        this.rules = rules;
+    }
+
+    public static class DataTypeJsonDeSerializer
+            implements JsonDeserializer<DataType> {
+
+        @Override
+        public DataType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+                throws JsonParseException {
+            if (json == null) {
+                return null;
+            }
+            DataType<Object> dataType = null;
+            if (!json.isJsonObject()) {
+                return dataType;
+            }
+            JsonObject jsonObject = json.getAsJsonObject();
+            JsonElement typeElement = jsonObject.get("type");
+            JsonElement specsElement = jsonObject.get("rules");
+            if (typeElement == null) {
+                return dataType;
+            }
+            String type = typeElement.getAsString();
+            if (TextUtils.isEmpty(type)) {
+                return dataType;
+            }
+            dataType = new DataType<>();
+            dataType.setType(type);
+            if ("string".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type) || "int"
+                    .equalsIgnoreCase(type) || "float"
+                    .equalsIgnoreCase(type) || "double"
+                    .equalsIgnoreCase(type) || "text".equalsIgnoreCase(type) || "date".equalsIgnoreCase(type)) {
+                MetaRule metaRule = context.deserialize(specsElement, (MetaRule.class));
+                dataType.setRules(metaRule);
+                return dataType;
+            }
+            if ("array".equalsIgnoreCase(type)) {
+                ArrayRule arrayRule = context.deserialize(specsElement, (ArrayRule.class));
+                dataType.setRules(arrayRule);
+                return dataType;
+            }
+            if ("enum".equalsIgnoreCase(type)) {
+                EnumRule enumRule = context.deserialize(specsElement, (EnumRule.class));
+                dataType.setRules(enumRule);
+                return dataType;
+            }
+            if (!"object".equalsIgnoreCase(type)) {
+                return dataType;
+            }
+            //String objectSpec = context.deserialize(specsElement, (String.class));
+            dataType.setRules(null);
+            return dataType;
+        }
+    }
+
+    public static class DataTypeJsonSerializer
+            implements JsonSerializer<DataType> {
+
+        @Override
+        public JsonElement serialize(DataType src, Type typeOfSrc, JsonSerializationContext context) {
+            JsonElement jsonElement = null;
+            if (src == null) {
+                return jsonElement;
+            }
+            JsonObject jsonObject = new JsonObject();
+            if ("string".equalsIgnoreCase(src.getType()) || "bool".equalsIgnoreCase(src.getType()) || "int"
+                    .equalsIgnoreCase(src.getType()) || "float".equalsIgnoreCase(src.getType()) || "double"
+                    .equalsIgnoreCase(src.getType()) || "text".equalsIgnoreCase(src.getType()) || "date"
+                    .equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (MetaRule.class));
+            } else if ("array".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (ArrayRule.class));
+            } else if ("enum".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (EnumRule.class));
+            } else if ("object".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize("", (String.class));
+            }
+            jsonObject.addProperty("type", src.getType());
+            jsonObject.add("rules", jsonElement);
+            return jsonObject;
+        }
+    }
+
+}
+

+ 114 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DataTypeBak.java

@@ -0,0 +1,114 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+import com.google.gson.*;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.ArrayRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.EnumRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.MetaRule;
+import com.thinkunion.park.service.common.iot.util.TextUtils;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+public class DataTypeBak<T> {
+
+    private String type;
+    private T rules;
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public T getRules() {
+        return this.rules;
+    }
+
+    public void setRules(T rules) {
+        this.rules = rules;
+    }
+
+    public static class DataTypeJsonDeSerializer
+            implements JsonDeserializer<DataTypeBak> {
+
+        @Override
+        public DataTypeBak deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+                throws JsonParseException {
+            if (json == null) {
+                return null;
+            }
+            DataTypeBak<Object> dataType = null;
+            if (!json.isJsonObject()) {
+                return dataType;
+            }
+            JsonObject jsonObject = json.getAsJsonObject();
+            JsonElement typeElement = jsonObject.get("type");
+            JsonElement specsElement = jsonObject.get("rules");
+            if (typeElement == null) {
+                return dataType;
+            }
+            String type = typeElement.getAsString();
+            if (TextUtils.isEmpty(type)) {
+                return dataType;
+            }
+            dataType = new DataTypeBak<>();
+            dataType.setType(type);
+            if ("string".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type) || "int"
+                    .equalsIgnoreCase(type) || "float"
+                    .equalsIgnoreCase(type) || "double"
+                    .equalsIgnoreCase(type) || "text".equalsIgnoreCase(type) || "date".equalsIgnoreCase(type)) {
+                MetaRule metaRule = context.deserialize(specsElement, (MetaRule.class));
+                dataType.setRules(metaRule);
+                return dataType;
+            }
+            if ("array".equalsIgnoreCase(type)) {
+                ArrayRule arrayRule = context.deserialize(specsElement, (ArrayRule.class));
+                dataType.setRules(arrayRule);
+                return dataType;
+            }
+            if ("enum".equalsIgnoreCase(type)) {
+                EnumRule enumRule = context.deserialize(specsElement, (EnumRule.class));
+                dataType.setRules(enumRule);
+                return dataType;
+            }
+            if (!"struct".equalsIgnoreCase(type)) {
+                return dataType;
+            }
+            List structSpec = context.deserialize(specsElement, (List.class));
+            dataType.setRules(structSpec);
+            return dataType;
+        }
+    }
+
+    public static class DataTypeJsonSerializer
+            implements JsonSerializer<DataTypeBak> {
+
+        @Override
+        public JsonElement serialize(DataTypeBak src, Type typeOfSrc, JsonSerializationContext context) {
+            JsonElement jsonElement = null;
+            if (src == null) {
+                return jsonElement;
+            }
+            JsonObject jsonObject = new JsonObject();
+            if ("string".equalsIgnoreCase(src.getType()) || "bool".equalsIgnoreCase(src.getType()) || "int"
+                    .equalsIgnoreCase(src.getType()) || "float".equalsIgnoreCase(src.getType()) || "double"
+                    .equalsIgnoreCase(src.getType()) || "text".equalsIgnoreCase(src.getType()) || "date"
+                    .equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (MetaRule.class));
+            } else if ("array".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (ArrayRule.class));
+            } else if ("enum".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (EnumRule.class));
+            } else if ("struct".equalsIgnoreCase(src.getType())) {
+                jsonElement = context.serialize(src.getRules(), (List.class));
+            }
+            jsonObject.addProperty("type", src.getType());
+            jsonObject.add("rules", jsonElement);
+            return jsonObject;
+        }
+    }
+
+}
+

+ 340 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/DeviceModel.java

@@ -0,0 +1,340 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+import com.google.gson.JsonElement;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.ArrayRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.EnumRule;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.rules.MetaRule;
+import com.thinkunion.park.service.common.iot.constant.ParamDataType;
+import com.thinkunion.park.service.common.iot.exception.ApiRuntimeException;
+import com.thinkunion.park.service.common.iot.exception.DataErrorException;
+import com.thinkunion.park.service.common.iot.util.GsonUtils;
+import com.thinkunion.park.service.common.iot.util.TextUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.nest.springwrap.core.tool.api.DeviceCode;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class DeviceModel {
+
+    private String id;
+    private Profile profile;
+    private List<Property> properties;
+    private List<Event> events;
+    private List<Service> services;
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Profile getProfile() {
+        return this.profile;
+    }
+
+    public void setProfile(Profile profile) {
+        this.profile = profile;
+    }
+
+    public List<Property> getProperties() {
+        return this.properties;
+    }
+
+    public void setProperties(List<Property> properties) {
+        this.properties = properties;
+    }
+
+    public List<Event> getEvents() {
+        return this.events;
+    }
+
+    public void setEvents(List<Event> events) {
+        this.events = events;
+    }
+
+    public List<Service> getServices() {
+        return this.services;
+    }
+
+    public void setServices(List<Service> services) {
+        this.services = services;
+    }
+
+    public Service getServiceForAction(String action) {
+        if (services.isEmpty()) {
+            return null;
+        }
+        for (Service service : services) {
+            if (service.getAction().equals(action)) {
+                return service;
+            }
+        }
+        return null;
+    }
+
+    public Event getEventForAction(String action) {
+        if (events.isEmpty()) {
+            return null;
+        }
+        for (Event event : events) {
+            if (event.getAction().equals(action)) {
+                return event;
+            }
+        }
+        return null;
+    }
+
+    public Object getPropertyValue(String identify, String valueString) {
+        Property property = getProp(identify);
+        if (property == null) {
+            throw new ApiRuntimeException(DeviceCode.IOT_PROPERTY_NOT_FOUND);
+        }
+        return getValue(identify, property.getData(), valueString);
+    }
+
+    public static Object getValue(String identify, DataType dataType, String valueString) {
+        if (dataType == null || valueString == null) {
+            return null;
+        }
+
+        if (dataType.getType().equals(ParamDataType.INT.value)) {
+            MetaRule metaRule = (MetaRule) dataType.getRules();
+            int value = Integer.valueOf(valueString);
+            if (metaRule != null && ((StringUtils.isNotBlank(metaRule.getMax()) && value > Integer
+                    .valueOf(metaRule.getMax()))
+                    || StringUtils.isNotBlank(metaRule.getMin()) && value < Integer.valueOf(metaRule.getMin()))) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            return value;
+        }
+        // double
+        else if (dataType.getType().equals(ParamDataType.DOUBLE.value)) {
+            MetaRule metaRule = (MetaRule) dataType.getRules();
+            double value = Double.valueOf(valueString);
+            if (metaRule != null && ((StringUtils.isNotBlank(metaRule.getMax()) && value > Double
+                    .valueOf(metaRule.getMax()))
+                    || StringUtils.isNotBlank(metaRule.getMin()) && value < Double.valueOf(metaRule.getMin()))) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            return value;
+        }
+
+        // float
+        else if (dataType.getType().equals(ParamDataType.FLOAT.value)) {
+            MetaRule metaRule = (MetaRule) dataType.getRules();
+            float value = Float.valueOf(valueString);
+            // TODO 支持步长校验
+            if (metaRule != null && ((StringUtils.isNotBlank(metaRule.getMax()) && value > Float
+                    .valueOf(metaRule.getMax()))
+                    || StringUtils.isNotBlank(metaRule.getMin()) && value < Float.valueOf(metaRule.getMin()))) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            return value;
+        }
+
+        // time
+        else if (dataType.getType().equals(ParamDataType.TIME.value)) {
+            if (Pattern.matches("(b[0-9]{10})", valueString)) {
+                return valueString;
+            }
+            throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+        }
+
+        // text
+        else if (dataType.getType().equals(ParamDataType.TEXT.value)) {
+            MetaRule metaRule = (MetaRule) dataType.getRules();
+            if (metaRule != null && (StringUtils.isNotBlank(metaRule.getLength()) && valueString.length() > Integer
+                    .valueOf(metaRule.getLength()))) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            return valueString;
+        }
+
+        // boolean
+        else if (dataType.getType().equals(ParamDataType.BOOL.value)) {
+            return valueString.equals("0") || valueString.equals("1") ? valueString : null;
+        }
+
+        // array
+        else if (dataType.getType().equals(ParamDataType.ARRAY.value)) {
+            ArrayRule metaRule = (ArrayRule) dataType.getRules();
+
+            Object[] value = null;
+
+            if (metaRule == null) {
+                value = GsonUtils.fromJson(valueString, String[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.INT.value)) {
+                value = GsonUtils.fromJson(valueString, Integer[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.DOUBLE.value)) {
+                value = GsonUtils.fromJson(valueString, Double[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.FLOAT.value)) {
+                value = GsonUtils.fromJson(valueString, Float[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.TEXT.value)) {
+                value = GsonUtils.fromJson(valueString, String[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.BOOL.value)) {
+                value = GsonUtils.fromJson(valueString, Boolean[].class);
+            } else if (metaRule.item.type.equals(ParamDataType.TIME.value)) {
+                value = GsonUtils.fromJson(valueString, String[].class);
+            } else {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            if (value == null || value.length < 1 || (metaRule != null && (value.length > Integer
+                    .valueOf(metaRule.size)))) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+            return value;
+        }
+
+        // enum
+        else if (dataType.getType().equals(ParamDataType.ENUM.value)) {
+            EnumRule metaRule = (EnumRule) dataType.getRules();
+            if (metaRule.containsKey(valueString)) {
+                return valueString;
+            } else {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            }
+        }
+
+        // object
+        else if (dataType.getType().equals(ParamDataType.OBJECT.value)) {
+            JsonElement element = GsonUtils.fromJson(valueString, JsonElement.class);
+            if (element.isJsonNull()) {
+                throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+            } else {
+                return valueString;
+            }
+        }
+
+        // error type
+        else {
+            throw new DataErrorException(String.format(" Value of arg '%s' is wrong ", identify));
+        }
+    }
+
+    public String getServiceAction(String serviceId) {
+        Service service;
+        if (TextUtils.isEmpty(serviceId)) {
+            return null;
+        }
+        if (this.services == null) {
+            return null;
+        }
+        if (this.services.isEmpty()) {
+            return null;
+        }
+        Iterator<Service> iterator = this.services.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return null;
+            }
+        } while (!serviceId.equalsIgnoreCase((service = iterator.next()).getId()));
+        return service.getAction();
+    }
+
+    public String getEventAction(String eventId) {
+        Event event;
+        if (TextUtils.isEmpty(eventId)) {
+            return null;
+        }
+        if (this.events == null) {
+            return null;
+        }
+        if (this.events.isEmpty()) {
+            return null;
+        }
+        Iterator<Event> iterator = this.events.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return null;
+            }
+        } while (!eventId.equalsIgnoreCase((event = iterator.next()).getId()));
+        return event.getAction();
+    }
+
+    public Event getEvent(String eventId) {
+        Event event;
+        if (TextUtils.isEmpty(eventId)) {
+            return null;
+        }
+        if (this.events == null) {
+            return null;
+        }
+        if (this.events.isEmpty()) {
+            return null;
+        }
+        Iterator<Event> iterator = this.events.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return null;
+            }
+        } while (!eventId.equalsIgnoreCase((event = iterator.next()).getId()));
+        return event;
+    }
+
+    public Service getService(String serviceId) {
+
+        Service service;
+
+        if (TextUtils.isEmpty(serviceId)) {
+            return null;
+        }
+        if (this.services == null) {
+            return null;
+        }
+        if (this.services.isEmpty()) {
+            return null;
+        }
+        Iterator<Service> iterator = this.services.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return null;
+            }
+        } while (!serviceId.equalsIgnoreCase((service = iterator.next()).getId()));
+        return service;
+    }
+
+    public Property getProp(String propId) {
+        Property property;
+        if (TextUtils.isEmpty(propId)) {
+            return null;
+        }
+        if (this.properties == null) {
+            return null;
+        }
+        if (this.properties.isEmpty()) {
+            return null;
+        }
+        Iterator<Property> iterator = this.properties.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return null;
+            }
+        } while (!propId.equalsIgnoreCase((property = iterator.next()).getId()));
+        return property;
+    }
+
+    public boolean hasProp(String propId) {
+        Property property;
+        if (TextUtils.isEmpty(propId)) {
+            return false;
+        }
+        if (this.properties == null) {
+            return false;
+        }
+        if (this.properties.isEmpty()) {
+            return false;
+        }
+        Iterator<Property> iterator = this.properties.iterator();
+        do {
+            if (!iterator.hasNext()) {
+                return false;
+            }
+        } while (!propId.equalsIgnoreCase((property = iterator.next()).getId()));
+        return true;
+    }
+}
+

+ 74 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Event.java

@@ -0,0 +1,74 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+import java.util.List;
+
+public class Event {
+
+    private String name;
+    private String id;
+    private String desc;
+    private String type;
+    private String action;
+    private List<Arg> out;
+
+    public Arg getArg(String id) {
+        if (out == null || out.isEmpty()) {
+            return null;
+        }
+        for (Arg arg : out) {
+            if (arg.getId().equals(id)) {
+                return arg;
+            }
+        }
+        return null;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public String getAction() {
+        return this.action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public List<Arg> getOut() {
+        return this.out;
+    }
+
+    public void setOut(List<Arg> out) {
+        this.out = out;
+    }
+}
+

+ 6 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/GetService.java

@@ -0,0 +1,6 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+public class GetService
+        extends Service<String> {
+}
+

+ 6 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/NormalService.java

@@ -0,0 +1,6 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+public class NormalService
+        extends Service<Arg> {
+}
+

+ 24 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Profile.java

@@ -0,0 +1,24 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+public class Profile {
+
+    private String version;
+    private String productKey;
+
+    public String getVersion() {
+        return this.version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getProductKey() {
+        return this.productKey;
+    }
+
+    public void setProductKey(String prodKey) {
+        this.productKey = prodKey;
+    }
+}
+

+ 70 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Property.java

@@ -0,0 +1,70 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+public class Property {
+    private String name;
+    private String id;
+    private String mode;
+    private boolean optional;
+    private String desc;
+    private boolean required;
+    private DataType data;
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getMode() {
+        return this.mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    @Deprecated
+    public boolean isOptional() {
+        return this.optional;
+    }
+
+    @Deprecated
+    public void setOptional(boolean optional) {
+        this.optional = optional;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public boolean isRequired() {
+        return this.required;
+    }
+
+    public void setRequired(boolean required) {
+        this.required = required;
+    }
+
+    public DataType getData() {
+        return this.data;
+    }
+
+    public void setData(DataType data) {
+        this.data = data;
+    }
+}
+

+ 138 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/Service.java

@@ -0,0 +1,138 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel;
+
+import com.google.gson.*;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+public class Service<T> {
+    private String name;
+    private String id;
+    private String desc;
+    private String action;
+    private String type;
+    private List<T> in;
+    private List<Arg> out;
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAction() {
+        return this.action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public List<T> getIn() {
+        return this.in;
+    }
+
+    public void setIn(List<T> in) {
+        this.in = in;
+    }
+
+    public List<Arg> getOut() {
+        return this.out;
+    }
+
+    public void setOut(List<Arg> out) {
+        this.out = out;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public static class ServiceJsonDeSerializer
+            implements JsonDeserializer<Service> {
+        @Override
+        public Service deserialize(JsonElement json, Type typeOfT,
+                                   JsonDeserializationContext context) throws JsonParseException {
+            JsonElement outputParamsEle;
+            JsonElement callTypeEle;
+            JsonElement descEle;
+            JsonElement methodEle;
+            if (json == null) {
+                return null;
+            }
+            Service service = null;
+            if (!json.isJsonObject()) {
+                return service;
+            }
+            JsonObject payloadObject = json.getAsJsonObject();
+            if (payloadObject == null) {
+                return service;
+            }
+            JsonElement identifierEle = payloadObject.get("id");
+            String identifier = null;
+            if (identifierEle != null && identifierEle.isJsonPrimitive()) {
+                identifier = identifierEle.getAsJsonPrimitive().getAsString();
+            }
+            JsonElement inputParamsEle = payloadObject.get("in");
+            if ("get".equalsIgnoreCase(identifier)) {
+                service = new GetService();
+                if (inputParamsEle != null) {
+                    service.setIn(context.deserialize(inputParamsEle, new TypeToken<List<String>>() {
+                    }.getType()));
+                }
+            } else {
+                service = new NormalService();
+                if (inputParamsEle != null) {
+                    service.setIn(context.deserialize(inputParamsEle, new TypeToken<List<Arg>>() {
+                    }.getType()));
+                }
+            }
+            service.setId(identifier);
+            JsonElement nameEle = payloadObject.get("name");
+            if (nameEle != null && nameEle.isJsonPrimitive()) {
+                service.setName(nameEle.getAsJsonPrimitive().getAsString());
+            }
+            if ((methodEle = payloadObject.get("action")) != null && methodEle.isJsonPrimitive()) {
+                service.setAction(methodEle.getAsJsonPrimitive().getAsString());
+            }
+            if ((descEle = payloadObject.get("desc")) != null && descEle.isJsonPrimitive()) {
+                service.setDesc(descEle.getAsJsonPrimitive().getAsString());
+            }
+            if ((outputParamsEle = payloadObject.get("out")) != null) {
+                service.setOut(context.deserialize(outputParamsEle, new TypeToken<List<Arg>>() {
+                }.getType()));
+            }
+            if ((callTypeEle = payloadObject.get("type")) == null) {
+                return service;
+            }
+            service.setType(callTypeEle.getAsJsonPrimitive().getAsString());
+            return service;
+        }
+
+    }
+
+}
+

+ 22 - 0
common/park-common/src/main/java/com/thinkunion/park/service/common/iot/capability/devicemodel/loader/DeviceModelSerializer.java

@@ -0,0 +1,22 @@
+package com.thinkunion.park.service.common.iot.capability.devicemodel.loader;
+
+import com.google.gson.reflect.TypeToken;
+import com.thinkunion.park.service.common.iot.capability.devicemodel.DeviceModel;
+import com.thinkunion.park.service.common.iot.util.ModelGsonUtils;
+
+public abstract class DeviceModelSerializer {
+
+    public abstract String serialize(DeviceModel deviceModel);
+
+    public abstract DeviceModel deserialize(String json);
+
+    protected DeviceModel deserializeInner(String json) {
+        return (DeviceModel) ModelGsonUtils.fromJson(json, new TypeToken<DeviceModel>() {
+        }.getType());
+    }
+
+    protected String serializeInner(DeviceModel model) {
+        return ModelGsonUtils.toJson(model);
+    }
+}
+

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