ken 1 mesiac pred
commit
18b6519c09
100 zmenil súbory, kde vykonal 3038 pridanie a 0 odobranie
  1. 20 0
      .gitignore
  2. 61 0
      README.md
  3. 57 0
      common/common-core/pom.xml
  4. 11 0
      common/common-core/src/main/java/cn/poyee/common/base/BasePageQuery.java
  5. 53 0
      common/common-core/src/main/java/cn/poyee/common/base/IBaseEnum.java
  6. 89 0
      common/common-core/src/main/java/cn/poyee/common/config/OkHttpConfiguration.java
  7. 35 0
      common/common-core/src/main/java/cn/poyee/common/constant/Constants.java
  8. 6 0
      common/common-core/src/main/java/cn/poyee/common/result/IResultCode.java
  9. 77 0
      common/common-core/src/main/java/cn/poyee/common/result/Result.java
  10. 107 0
      common/common-core/src/main/java/cn/poyee/common/result/ResultCode.java
  11. 223 0
      common/common-core/src/main/java/cn/poyee/common/util/DateUtil.java
  12. 32 0
      common/common-core/src/main/java/cn/poyee/common/util/DecimalUtil.java
  13. 102 0
      common/common-core/src/main/java/cn/poyee/common/util/GZIPUtils.java
  14. 138 0
      common/common-core/src/main/java/cn/poyee/common/util/JsonUtil.java
  15. 167 0
      common/common-core/src/main/java/cn/poyee/common/util/OkHttpUtils.java
  16. 3 0
      common/common-core/src/main/resources/META-INF/spring.factories
  17. 0 0
      common/common-elasticsearch/README.md
  18. 24 0
      common/common-elasticsearch/pom.xml
  19. 10 0
      common/common-elasticsearch/src/main/java/cn/poyee/common/elasticsearch/config/ElasticProperties.java
  20. 28 0
      common/common-elasticsearch/src/main/java/cn/poyee/common/elasticsearch/config/ElasticSearchConfig.java
  21. 1 0
      common/common-elasticsearch/src/main/resources/META-INF/spring.factories
  22. 35 0
      common/common-mybatis/pom.xml
  23. 22 0
      common/common-mybatis/src/main/java/cn/poyee/common/mybatis/config/MybatisPlusConfig.java
  24. 2 0
      common/common-mybatis/src/main/resources/META-INF/spring.factories
  25. 29 0
      common/common-openapi/pom.xml
  26. 38 0
      common/common-openapi/src/main/java/cn/poyee/common/openapi/config/OpenApiConfig.java
  27. 2 0
      common/common-openapi/src/main/resources/META-INF/spring.factories
  28. 57 0
      common/common-redis/pom.xml
  29. 39 0
      common/common-redis/src/main/java/cn/poyee/common/redis/cache/CustomRedisCacheManager.java
  30. 41 0
      common/common-redis/src/main/java/cn/poyee/common/redis/cache/RedisTemplateConfig.java
  31. 27 0
      common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoPool.java
  32. 71 0
      common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoRedisSerializer.java
  33. 109 0
      common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoUtil.java
  34. 246 0
      common/common-redis/src/main/java/cn/poyee/common/redis/service/RedisService.java
  35. 5 0
      common/common-redis/src/main/resources/META-INF/spring.factories
  36. 39 0
      common/common-web/pom.xml
  37. 40 0
      common/common-web/src/main/java/cn/poyee/common/web/exception/BusinessException.java
  38. 115 0
      common/common-web/src/main/java/cn/poyee/common/web/exception/GlobalExceptionHandler.java
  39. 2 0
      common/common-web/src/main/resources/META-INF/spring.factories
  40. 35 0
      common/pom.xml
  41. 98 0
      persist/pom.xml
  42. 11 0
      persist/src/main/java/cn/poyee/datapersist/DataPersistApplication.java
  43. 25 0
      persist/src/main/java/cn/poyee/datapersist/config/ESConfiguration.java
  44. 6 0
      persist/src/main/java/cn/poyee/datapersist/config/MessagingConfiguration.java
  45. 36 0
      persist/src/main/java/cn/poyee/datapersist/config/PipelineConfig.java
  46. 103 0
      persist/src/main/java/cn/poyee/datapersist/config/RabbitMQConfiguration.java
  47. 31 0
      persist/src/main/java/cn/poyee/datapersist/config/ThreadPoolConfiguration.java
  48. 48 0
      persist/src/main/java/cn/poyee/datapersist/config/ThreadPoolExecutorShutdownDefinition.java
  49. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/$AppEnd.java
  50. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/$AppStart.java
  51. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/$SignUp.java
  52. 8 0
      persist/src/main/java/cn/poyee/datapersist/dto/AdClick.java
  53. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/AdDetailView.java
  54. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/AdShow.java
  55. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/AppCrashed.java
  56. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/AppWebSocket.java
  57. 10 0
      persist/src/main/java/cn/poyee/datapersist/dto/AppleIDLoginClick.java
  58. 13 0
      persist/src/main/java/cn/poyee/datapersist/dto/AuctionBid.java
  59. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/BannerShareClick.java
  60. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/BannerShareSuccess.java
  61. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/BlacklistClick.java
  62. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/BlacklistConfirmClick.java
  63. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/BottomMessageClick.java
  64. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/BottomMineClick.java
  65. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/BottomZBClick.java
  66. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/BottomZTCKClick.java
  67. 8 0
      persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductClick.java
  68. 8 0
      persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductLikes.java
  69. 8 0
      persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductShare.java
  70. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductView.java
  71. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/CalendarView.java
  72. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/CancelCollectProductClick.java
  73. 14 0
      persist/src/main/java/cn/poyee/datapersist/dto/CancelFollowShopClick.java
  74. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/CardPlaybackClick.java
  75. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/CardReportClick.java
  76. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/CardlistClick.java
  77. 30 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickBuy.java
  78. 30 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickGroup.java
  79. 14 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupBuy.java
  80. 11 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupBuy2.java
  81. 20 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupRoom.java
  82. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupTab.java
  83. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickMall.java
  84. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickOnTheTeamSearchBar.java
  85. 27 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickProduct.java
  86. 13 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickRoom.java
  87. 10 0
      persist/src/main/java/cn/poyee/datapersist/dto/ClickRoomShoppingCart.java
  88. 7 0
      persist/src/main/java/cn/poyee/datapersist/dto/CollectProductClick.java
  89. 10 0
      persist/src/main/java/cn/poyee/datapersist/dto/ConfirmExpressClick.java
  90. 12 0
      persist/src/main/java/cn/poyee/datapersist/dto/ConfirmShipmentClick.java
  91. 12 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentClick.java
  92. 13 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentDetail.java
  93. 5 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchClick.java
  94. 6 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchRequest.java
  95. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchResultClick.java
  96. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentShare.java
  97. 13 0
      persist/src/main/java/cn/poyee/datapersist/dto/ContentView.java
  98. 4 0
      persist/src/main/java/cn/poyee/datapersist/dto/Event.java
  99. 9 0
      persist/src/main/java/cn/poyee/datapersist/dto/ExchangeActionConfirmExClick.java
  100. 8 0
      persist/src/main/java/cn/poyee/datapersist/dto/ExchangeActionExProductClick.java

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+target/
+.idea
+*.iml
+out
+gen
+target
+*.log
+
+### Nacos
+!**/nacos/target
+**/nacos/bin/work
+**/nacos/data
+logs
+**/nacos/LICENSE
+**/nacos/NOTICE
+
+
+### Canal
+h2.mv.db
+**/meta.dat

+ 61 - 0
README.md

@@ -0,0 +1,61 @@
+## 待办事项:
+- [ ] 网关增加MQTT连接的身份校验
+- [ ] TrackWeb
+    - [ ] 准备演示材料
+    - [x] 预约会议室
+
+### elasticsearch calendar_interval
+- year(1y)年
+- quarter(1q)季度
+- month(1M)月份
+- week(1w)星期
+- day(1d)天
+- hour(1h)小时
+- minute(1m)分钟
+- second(1s)秒
+
+### 组队状态
+* 组队状态
+* 101 提交 未审核
+* 102 审核不通过
+* 103 商家已确认
+* 201 已审核 审核通过 投入市场
+* 202 团卡超时(未组满)
+* 203 队伍组满 等待开奖(直播等)
+* 204 直播中
+* 205 直播结束
+* 2051 公示卡片待审核
+* 206 公布结果
+* 301 团卡完成
+* 999 锁定/下架
+
+### 订单状态
+* 100 待支付
+* 101 已支付 待开奖
+* 102 已开奖
+* 103 待发货
+* 104 已发货
+* 105 运货中
+* 106 待收货
+* 201 订单超时 取消
+* 202 用户取消
+* 203 支付失败
+* 204 退款中
+* 205 退款完成
+* 206 退款失败
+* 301 订单完成
+* 302 未中卡
+* 303 订单已关闭
+
+## 埋点测试环境地址
+curl --location 'http://track-dev.hobbystocks.cn/api/tracking' \
+--header 'Authorization: Bearer eyJraWQiOiI5ZWIw' \
+--header 'Content-Type: application/x-www-form-urlencoded' \
+--data-urlencode 'crc=1281171596' \
+--data-urlencode 'data_list=H4sIAAAAAAAA/7'
+
+## 
+* 查看运行时内存情况
+```
+/actuator/metrics/jvm.memory.used
+```

+ 57 - 0
common/common-core/pom.xml

@@ -0,0 +1,57 @@
+<?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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-core</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>4.10.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 11 - 0
common/common-core/src/main/java/cn/poyee/common/base/BasePageQuery.java

@@ -0,0 +1,11 @@
+package cn.poyee.common.base;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class BasePageQuery implements Serializable {
+    private int pageNum = 1;
+    private int pageSize = 10;
+}

+ 53 - 0
common/common-core/src/main/java/cn/poyee/common/base/IBaseEnum.java

@@ -0,0 +1,53 @@
+package cn.poyee.common.base;
+
+import java.util.EnumSet;
+import java.util.Objects;
+
+public interface IBaseEnum<T> {
+
+    T getValue();
+
+    String getLabel();
+
+    static <E extends Enum<E> & IBaseEnum> E getEnumByValue(Object value, Class<E> clazz) {
+        Objects.requireNonNull(value);
+        EnumSet<E> allEnums = EnumSet.allOf(clazz);
+        E matchEnum = allEnums.stream()
+                .filter(e -> Objects.equals(e.getValue(), value))
+                .findFirst()
+                .orElse(null);
+        return matchEnum;
+    }
+
+    static <E extends Enum<E> & IBaseEnum> String getLabelByValue(Object value, Class<E> clazz) {
+        Objects.requireNonNull(value);
+        EnumSet<E> allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举
+        E matchEnum = allEnums.stream()
+                .filter(e -> Objects.equals(e.getValue(), value))
+                .findFirst()
+                .orElse(null);
+
+        String label = null;
+        if (matchEnum != null) {
+            label = matchEnum.getLabel();
+        }
+        return label;
+    }
+
+    static <E extends Enum<E> & IBaseEnum> Object getValueByLabel(String label, Class<E> clazz) {
+        Objects.requireNonNull(label);
+        EnumSet<E> allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举
+        String finalLabel = label;
+        E matchEnum = allEnums.stream()
+                .filter(e -> Objects.equals(e.getLabel(), finalLabel))
+                .findFirst()
+                .orElse(null);
+
+        Object value = null;
+        if (matchEnum != null) {
+            value = matchEnum.getValue();
+        }
+        return value;
+    }
+
+}

+ 89 - 0
common/common-core/src/main/java/cn/poyee/common/config/OkHttpConfiguration.java

@@ -0,0 +1,89 @@
+package cn.poyee.common.config;
+
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class OkHttpConfiguration {
+
+    @Value("${okhttp.connect-timeout:3}")
+    private Integer connectTimeout;
+
+    @Value("${okhttp.read-timeout:3}")
+    private Integer readTimeout;
+
+    @Value("${okhttp.write-timeout:3}")
+    private Integer writeTimeout;
+
+    @Value("${okhttp.max-idle-connections:20}")
+    private Integer maxIdleConnections;
+
+    @Value("${okhttp.keep-alive-duration:45}")
+    private Long keepAliveDuration;
+
+    @Bean
+    public OkHttpClient okHttpClient() {
+        return new OkHttpClient.Builder()
+                .sslSocketFactory(sslSocketFactory(), x509TrustManager())
+                .retryOnConnectionFailure(false)
+                .connectionPool(pool())
+                .connectTimeout(connectTimeout, TimeUnit.SECONDS)
+                .readTimeout(readTimeout, TimeUnit.SECONDS)
+                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
+                .hostnameVerifier((hostname, session) -> true)
+                .build();
+    }
+
+    @Bean
+    public X509TrustManager x509TrustManager() {
+        return new X509TrustManager() {
+            @Override
+            public void checkClientTrusted(X509Certificate[] chain, String authType)
+                    throws CertificateException {
+            }
+
+            @Override
+            public void checkServerTrusted(X509Certificate[] chain, String authType)
+                    throws CertificateException {
+            }
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+        };
+    }
+
+    @Bean
+    public SSLSocketFactory sslSocketFactory() {
+        try {
+            // 信任任何链接
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
+            return sslContext.getSocketFactory();
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Bean
+    public ConnectionPool pool() {
+        return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
+    }
+}

+ 35 - 0
common/common-core/src/main/java/cn/poyee/common/constant/Constants.java

@@ -0,0 +1,35 @@
+package cn.poyee.common.constant;
+
+public interface Constants {
+
+    // 唤起支付事件
+    String GROUP_PAY_ORDER_TRACK = "GROUP_PAY_ORDER_TRACK::";
+
+    // 用户ID列表
+    String USER_ID_LIST = "USER_ID_LIST";
+
+    // 用户ID列表
+    String USER_DETAIL_LIST = "USER_DETAIL_LIST";
+
+    // 热门商家
+    String HOT_STORE_RANK = "HOT_STORE_RANK::";
+
+    // 热门拼团
+    String HOT_GROUP_RANK = "HOT_GROUP_RANK::";
+    // 拼团分数 - 不过期
+    String HOT_STORE_PER = "HOT_STORE_PER::";
+
+    String HOT_STORE_SPORT_SET_RANK = "HOT_STORE_SPORT_SET_RANK::";
+    // 商家列表
+    String STORE_LIST = "STORE_LIST::";
+
+    // 热门商品
+    String HOT_PRODUCT_RANK = "HOT_PRODUCT_RANK::";
+
+    // 组队状态
+    String TEAM_STATUS_ING = "拼团中";
+    // 产品状态
+    String PRODUCT_STATUS_UP = "已上架";
+
+    String SELF_SUPPORT = "327";
+}

+ 6 - 0
common/common-core/src/main/java/cn/poyee/common/result/IResultCode.java

@@ -0,0 +1,6 @@
+package cn.poyee.common.result;
+
+public interface IResultCode {
+    Integer getCode();
+    String getMsg();
+}

+ 77 - 0
common/common-core/src/main/java/cn/poyee/common/result/Result.java

@@ -0,0 +1,77 @@
+package cn.poyee.common.result;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Result<T> implements Serializable {
+
+    private Integer code;
+    private T data;
+    private String msg;
+    private Long total;
+
+    public static <T> Result<T> success() {
+        return success(null);
+    }
+
+    public static <T> Result<T> success(T data) {
+        Result<T> result = new Result<>();
+        result.setCode(ResultCode.SUCCESS.getCode());
+        result.setMsg(ResultCode.SUCCESS.getMsg());
+        result.setData(data);
+        return result;
+    }
+
+    public static <T> Result<T> success(T data, Long total) {
+        Result<T> result = new Result<>();
+        result.setCode(ResultCode.SUCCESS.getCode());
+        result.setMsg(ResultCode.SUCCESS.getMsg());
+        result.setData(data);
+        result.setTotal(total);
+        return result;
+    }
+
+    public static <T> Result<T> failed() {
+        return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), ResultCode.SYSTEM_EXECUTION_ERROR.getMsg(), null);
+    }
+
+    public static <T> Result<T> failed(String msg) {
+        return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), msg, null);
+    }
+
+    public static <T> Result<T> judge(boolean status) {
+        if (status) {
+            return success();
+        } else {
+            return failed();
+        }
+    }
+
+    public static <T> Result<T> failed(IResultCode resultCode) {
+        return result(resultCode.getCode(), resultCode.getMsg(), null);
+    }
+
+    public static <T> Result<T> failed(IResultCode resultCode, String msg) {
+        return result(resultCode.getCode(), msg, null);
+    }
+
+    private static <T> Result<T> result(IResultCode resultCode, T data) {
+        return result(resultCode.getCode(), resultCode.getMsg(), data);
+    }
+
+    private static <T> Result<T> result(Integer code, String msg, T data) {
+        Result<T> result = new Result<>();
+        result.setCode(code);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+
+    public static boolean isSuccess(Result<?> result) {
+        return result != null && ResultCode.SUCCESS.getCode().equals(result.getCode());
+    }
+}

+ 107 - 0
common/common-core/src/main/java/cn/poyee/common/result/ResultCode.java

@@ -0,0 +1,107 @@
+package cn.poyee.common.result;
+
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@AllArgsConstructor
+@NoArgsConstructor
+public enum ResultCode implements IResultCode, Serializable {
+
+    USER_ERROR(100, "用户端错误"),
+    INTERFACE_NOT_EXIST(113, "接口不存在"),
+    MESSAGE_SERVICE_ERROR(120, "消息服务出错"),
+    MESSAGE_DELIVERY_ERROR(121, "消息投递出错"),
+    MESSAGE_CONSUMPTION_ERROR(122, "消息消费出错"),
+    MESSAGE_SUBSCRIPTION_ERROR(123, "消息订阅出错"),
+    MESSAGE_GROUP_NOT_FOUND(124, "消息分组未查到"),
+
+    SUCCESS(200, "SUCCESS"),
+    AFFECTED_ROWS_IS_EMPTY(200, "执行成功,受影响行数为空"),
+    USER_LOGIN_ERROR(200, "用户登录异常"),
+    USER_NOT_EXIST(201, "用户不存在"),
+    LOGIC_LAYER_ERROR(200, "逻辑层异常,请联系开发人员"),
+
+    USER_ACCOUNT_LOCKED(202, "用户账户被冻结"),
+    USER_ACCOUNT_INVALID(203, "用户账户已作废"),
+    FLOW_LIMITING(204, "系统限流"),
+    DEGRADATION(205, "系统功能降级"),
+    PAY_ERROR(206, "支付异常"),
+    USERNAME_OR_PASSWORD_ERROR(210, "用户名或密码错误"),
+    PASSWORD_ENTER_EXCEED_LIMIT(211, "用户输入密码次数超限"),
+    CLIENT_AUTHENTICATION_FAILED(212, "客户端认证失败"),
+    TOKEN_INVALID_OR_EXPIRED(230, "token无效或已过期"),
+    TOKEN_ACCESS_FORBIDDEN(231, "token已被禁止访问"),
+    SMS_CODE_TIMEOUT(251, "验证码已过期"),
+    SMS_CODE_ERROR(252, "验证码错误"),
+    COURSE_EXIST(261, "当前科目下已有课程,请确认是否删除"),
+
+    AUTHORIZED_ERROR(300, "访问权限异常"),
+    ACCESS_UNAUTHORIZED(301, "访问未授权"),
+    FORBIDDEN_OPERATION(302, "演示环境禁止修改、删除重要数据,请本地部署后测试"),
+    SYSTEM_RESOURCE_ERROR(303, "系统资源异常"),
+    SYSTEM_RESOURCE_EXHAUSTION(304, "系统资源耗尽"),
+    SYSTEM_RESOURCE_ACCESS_ERROR(305, "系统资源访问异常"),
+    SYSTEM_READ_DISK_FILE_ERROR(306, "系统读取磁盘文件失败"),
+    DATABASE_ERROR(307, "数据库服务出错"),
+    REPEAT_OPERATION(308, "重复操作"),
+    DATABASE_TABLE_NOT_EXIST(311, "表不存在"),
+    DATABASE_COLUMN_NOT_EXIST(312, "列不存在"),
+    DATABASE_DUPLICATE_COLUMN_NAME(321, "多表关联中存在多个相同名称的列"),
+    DATABASE_DEADLOCK(331, "数据库死锁"),
+    DATABASE_PRIMARY_KEY_CONFLICT(341, "主键冲突"),
+
+    PARAM_ERROR(400, "用户请求参数错误"),
+    RESOURCE_NOT_FOUND(401, "请求资源不存在"),
+    INVALID_OPERATION(402, "无效操作,与业务逻辑不符"),
+    COLLECTION_IS_EMPTY(403, "集合为空"),
+    CONTEXT_IS_NULL(404, "流程上下文为空"),
+    PARAM_IS_NULL(410, "请求必填参数为空"),
+
+    MOBILE_FORMAT_ERROR(450, "手机号格式错误"),
+
+    USER_UPLOAD_FILE_ERROR(700, "用户上传文件异常"),
+    USER_UPLOAD_FILE_TYPE_NOT_MATCH(701, "用户上传文件类型不匹配"),
+    USER_UPLOAD_FILE_SIZE_EXCEEDS(702, "用户上传文件太大"),
+    USER_UPLOAD_IMAGE_SIZE_EXCEEDS(703, "用户上传图片太大"),
+
+    SYSTEM_EXECUTION_ERROR(500, "系统执行出错"),
+    SYSTEM_EXECUTION_TIMEOUT(501, "系统执行超时"),
+    SYSTEM_ORDER_PROCESSING_TIMEOUT(502, "系统订单处理超时"),
+    SYSTEM_DISASTER_RECOVERY_TRIGGER(503, "系统容灾功能被出发"),
+    CALL_THIRD_PARTY_SERVICE_ERROR(504, "调用第三方服务出错"),
+    MIDDLEWARE_SERVICE_ERROR(505, "中间件服务出错");
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    @Override
+    public String getMsg() {
+        return msg;
+    }
+
+    private int code;
+
+    private String msg;
+
+    @Override
+    public String toString() {
+        return "{" +
+                "\"code\":\"" + code + '\"' +
+                ", \"msg\":\"" + msg + '\"' +
+                '}';
+    }
+
+
+    public static ResultCode getValue(int code) {
+        for (ResultCode value : values()) {
+            if (value.getCode() == code) {
+                return value;
+            }
+        }
+        return SYSTEM_EXECUTION_ERROR;
+    }
+}

+ 223 - 0
common/common-core/src/main/java/cn/poyee/common/util/DateUtil.java

@@ -0,0 +1,223 @@
+package cn.poyee.common.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+public class DateUtil {
+
+    public static final String DATETIME_FORMAT_yyyy_MM_dd = "yyyy-MM-dd";
+
+    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    public static final String DATE_FORMAT_DAY = "yyyy-MM-dd";
+    public static final String DATE_FORMAT_DAY_NO_GAPS = "yyyyMMdd";
+    public static final String DATE_FORMAT_HOUR_NO_GAPS = "yyyyMMddHH";
+
+    public static final String DATE_FORMAT_MONTH = "yyyy-MM";
+    public static final String DATE_FORMAT_HOUR = "yyyy-MM-dd HH:00:00";
+
+    private static final ThreadLocal<Map<String, DateFormat>> dateFormatThreadLocal = new ThreadLocal<>();
+
+    public static Long dateToStamp(String s) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_FORMAT);
+            Date date = sdf.parse(s);
+            return date.getTime();
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String timestampToDate(Long timestamp, String format) {
+
+        LocalDateTime dateTime = Instant.ofEpochMilli(timestamp)
+                .atZone(ZoneId.systemDefault())
+                .toLocalDateTime();
+
+        if (Objects.isNull(format)) {
+            format = DATETIME_FORMAT;
+        }
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
+        return dateTime.format(formatter);
+    }
+
+    private static DateFormat getDateFormat(String pattern) {
+        if (pattern == null || pattern.trim().length() == 0) {
+            throw new IllegalArgumentException("pattern cannot be empty.");
+        }
+
+        Map<String, DateFormat> dateFormatMap = dateFormatThreadLocal.get();
+        if (dateFormatMap != null && dateFormatMap.containsKey(pattern)) {
+            return dateFormatMap.get(pattern);
+        }
+
+        synchronized (dateFormatThreadLocal) {
+            if (dateFormatMap == null) {
+                dateFormatMap = new HashMap<>();
+            }
+            dateFormatMap.put(pattern, new SimpleDateFormat(pattern));
+            dateFormatThreadLocal.set(dateFormatMap);
+        }
+
+        return dateFormatMap.get(pattern);
+    }
+
+    public static Date parse(String date, String format) {
+        try {
+            if (format == null || format.length() == 0) {
+                format = DATE_FORMAT_DAY;
+            }
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            return sdf.parse(date);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Date parse(String date) {
+        return parse(date, null);
+    }
+
+    public static LocalDateTime parseInstant(String date) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
+        return LocalDateTime.parse(date, formatter).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
+    }
+
+    public static String format(Date date, String patten) {
+        return getDateFormat(patten).format(date);
+    }
+
+    public static long differentTimeStamp(String startTime, String endTime) {
+
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            long from = sdf.parse(startTime).getTime();
+            long to = sdf.parse(endTime).getTime();
+            return to - from;
+        } catch (Exception e) {
+            throw new RuntimeException();
+        }
+    }
+
+    public static int differentHour(String startTime, String endTime) {
+
+        try {
+            SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            long from = simpleFormat.parse(startTime).getTime();
+            long to = simpleFormat.parse(endTime).getTime();
+            return (Integer) (int) ((to - from) / (1000 * 60 * 60 * 1.0));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    public static int differentDays(String startTime, String endTime) {
+
+        Calendar cal1 = Calendar.getInstance();
+        cal1.setTime(parse(startTime));
+
+        Calendar cal2 = Calendar.getInstance();
+        cal2.setTime(parse(endTime));
+
+        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
+        int day2 = cal2.get(Calendar.DAY_OF_YEAR);
+
+        int year1 = cal1.get(Calendar.YEAR);
+        int year2 = cal2.get(Calendar.YEAR);
+        if (year1 != year2) {
+            int timeDistance = 0;
+            for (int i = year1; i < year2; i++) {
+                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
+                    timeDistance += 366;
+                } else {
+                    timeDistance += 365;
+                }
+            }
+
+            return timeDistance + (day2 - day1);
+        } else {
+            return day2 - day1;
+        }
+    }
+
+    public static long differentMonth(String startTime, String endTime) {
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalDateTime sTime = LocalDateTime.parse(startTime, formatter);
+        LocalDateTime eTime = LocalDateTime.parse(endTime, formatter);
+        return ChronoUnit.MONTHS.between(sTime, eTime);
+    }
+
+    public static Date addMinute(Date date, int amount) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        calendar.add(Calendar.MINUTE, amount);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static Date addHour(Date date) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        calendar.add(Calendar.HOUR, 1);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static Date addDay(Date date) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, 1);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static Date addDay(Date date, int day) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, day);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static Date addMonth(Date date) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        calendar.add(Calendar.MONTH, 1);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static boolean isBefore(String d1, String d2) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtil.DATETIME_FORMAT);
+        LocalDateTime date1 = LocalDateTime.parse(d1, formatter), date2 = LocalDateTime.parse(d2, formatter);
+        return date1.isBefore(date2);
+    }
+
+    public static String now(String format) {
+        // 获取当前 UTC 时间
+        Instant nowUtc = Instant.now();
+        // 转换为北京时间(UTC+8),并格式化
+        LocalDateTime dateTime = LocalDateTime.ofInstant(nowUtc, ZoneOffset.ofHours(8));
+        return dateTime.format(DateTimeFormatter.ofPattern(format));
+    }
+
+    public static void main(String[] args) {
+        // 使用北京时间(UTC+8)
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.ofHours(8));
+
+        // 使用 'yyyyMMddHH' 格式进行格式化
+        String formatted = dateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHH"));
+
+        System.out.println(formatted);  // 输出格式应为 'yyyyMMddHH',比如 '2024110500'
+    }
+}

+ 32 - 0
common/common-core/src/main/java/cn/poyee/common/util/DecimalUtil.java

@@ -0,0 +1,32 @@
+package cn.poyee.common.util;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class DecimalUtil {
+
+    public static BigDecimal decimalTrans(double number, int digit) {
+        try {
+            if (Double.isInfinite(number)) {
+                number = 0;
+            }
+
+            BigDecimal decimal = new BigDecimal(number);
+            decimal = decimal.setScale(digit, RoundingMode.HALF_UP);
+            return decimal;
+        } catch (NumberFormatException e) {
+            throw new NumberFormatException("数值转换错误:非数值类型");
+        }
+    }
+
+    public static BigDecimal decimalTrans(String number, int digit) {
+        try {
+            BigDecimal decimal = new BigDecimal(number);
+            decimal = decimal.setScale(digit, RoundingMode.HALF_UP);
+            return decimal;
+        } catch (NumberFormatException e) {
+            throw new NumberFormatException("数值转换错误:非数值类型");
+        }
+
+    }
+}

+ 102 - 0
common/common-core/src/main/java/cn/poyee/common/util/GZIPUtils.java

@@ -0,0 +1,102 @@
+package cn.poyee.common.util;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Base64;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class GZIPUtils {
+
+    public static void main(String[] args) {
+
+        String msg = "[\n" +
+                "    {\n" +
+                "        \"event\": \"ClickProduct\",\n" +
+                "        \"login_id\": \"93301\",\n" +
+                "        \"lib\": {\n" +
+                "            \"$lib_method\": \"code\",\n" +
+                "            \"$lib\": \"Android\",\n" +
+                "            \"$lib_version\": \"6.8.0\",\n" +
+                "            \"$app_version\": \"2.2.63\"\n" +
+                "        },\n" +
+                "        \"properties\": {\n" +
+                "            \"params\": \"{\\\\\"paniniBaseId\\\\\":\\\\\"1887\\\\\",\\\\\"groupId\\\\\":237733,\\\\\"groupCode\\\\\":\\\\\"GI202407062050156233\\\\\",\\\\\"groupName\\\\\":\\\\\"23-24 足球 Panini Select Premier League Hobby  #1【原箱】星集卡社 Star Collection\\\\\",\\\\\"groupType\\\\\":\\\\\"随机球员\\\\\",\\\\\"groupQuantity\\\\\":321,\\\\\"storeId\\\\\":865,\\\\\"storeName\\\\\":\\\\\"星集卡社 Star Collection\\\\\",\\\\\"listCode\\\\\":\\\\\"CK682024070620345470\\\\\",\\\\\"groupYear\\\\\":\\\\\"2023-24\\\\\",\\\\\"groupManufacturer\\\\\":\\\\\"Panini\\\\\",\\\\\"groupSets\\\\\":\\\\\"Select Premier League\\\\\",\\\\\"groupSpecifications\\\\\":\\\\\"原箱\\\\\",\\\\\"groupSport\\\\\":\\\\\"Soccer\\\\\",\\\\\"groupSource\\\\\":\\\\\"推荐\\\\\",\\\\\"groupState\\\\\":\\\\\"拼团中\\\\\",\\\\\"groupPrice\\\\\":\\\\\"128\\\\\",\\\\\"groupPlay\\\\\":\\\\\"拼团\\\\\",\\\\\"groupProgress\\\\\":5,\\\\\"recId\\\\\":\\\\\"0_23_42_142715213827_859944\\\\\"}\",\n" +
+                "            \"userId\": 93301,\n" +
+                "            \"$is_channel_callback_event\": false,\n" +
+                "            \"$channel_device_info\": \"1\",\n" +
+                "            \"$lib_method\": \"code\",\n" +
+                "            \"$is_first_day\": true,\n" +
+                "            \"$os\": \"Android\",\n" +
+                "            \"$os_version\": \"12\",\n" +
+                "            \"$lib\": \"Android\",\n" +
+                "            \"$lib_version\": \"6.8.0\",\n" +
+                "            \"$manufacturer\": \"VIVO\",\n" +
+                "            \"$model\": \"V2238A\",\n" +
+                "            \"$brand\": \"VIVO\",\n" +
+                "            \"$app_version\": \"2.2.63\",\n" +
+                "            \"$screen_width\": 1080,\n" +
+                "            \"$screen_height\": 1920,\n" +
+                "            \"$timezone_offset\": -480,\n" +
+                "            \"$app_id\": \"com.hobbystocks\",\n" +
+                "            \"$app_name\": \"HOBBY STOCKS\",\n" +
+                "            \"$wifi\": true,\n" +
+                "            \"$network_type\": \"WIFI\",\n" +
+                "            \"userLevel\": \"\",\n" +
+                "            \"wgtVersion\": \"2.2.63\",\n" +
+                "            \"userName\": \"\",\n" +
+                "            \"$device_id\": \"bfbead347aa14cc8\"\n" +
+                "        },\n" +
+                "        \"_flush_time\": 1720523558178\n" +
+                "    }\n" +
+                "]";
+        byte[] compress = GZIPUtils.compress(msg.getBytes());
+
+        byte[] uncompress = GZIPUtils.uncompress(compress);
+//        System.err.println(new String(uncompress));
+
+        byte[] gzip = Base64.getEncoder().encode(compress);
+
+        System.err.println(new String(gzip));
+        System.err.println(new String(gzip).hashCode());
+    }
+
+    public static byte[] compress(byte[] bytes) {
+        if (bytes == null || bytes.length == 0) {
+            return null;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        GZIPOutputStream gzip;
+        try {
+            gzip = new GZIPOutputStream(out);
+            gzip.write(bytes);
+            gzip.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        return out.toByteArray();
+    }
+
+    public static byte[] uncompress(byte[] bytes) {
+        if (bytes == null || bytes.length == 0) {
+            return null;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+        try {
+            GZIPInputStream ungzip = new GZIPInputStream(in);
+            byte[] buffer = new byte[256];
+            int n;
+            while ((n = ungzip.read(buffer)) >= 0) {
+                out.write(buffer, 0, n);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return out.toByteArray();
+    }
+}

+ 138 - 0
common/common-core/src/main/java/cn/poyee/common/util/JsonUtil.java

@@ -0,0 +1,138 @@
+package cn.poyee.common.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import lombok.NonNull;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.*;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Map;
+
+public class JsonUtil {
+
+    private static final ObjectMapper mapper = new ObjectMapper();
+    private static final Log log = LogFactory.getLog(JsonUtil.class);
+
+    static {
+        // 对象的所有字段全部列入
+        mapper.setDefaultPropertyInclusion(JsonInclude.Include.ALWAYS);
+        // 取消默认转换timestamps形式
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        // 忽略空Bean转json的错误
+        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+        // 所有的日期格式都统一为以下的样式(yyyy-MM-dd HH:mm:ss)
+        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+        // 忽略在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
+
+        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
+
+        mapper.registerModule(new JavaTimeModule());
+    }
+
+    public static boolean isValid(String json) {
+        try {
+            mapper.readTree(json);
+        } catch (JacksonException e) {
+            return false;
+        }
+        return true;
+    }
+
+    public static <T> Map<String, T> toMap(String json, Class<T> clz) {
+        try {
+            return mapper.readValue(json, collectionType(Map.class, String.class, clz));
+        } catch (JsonProcessingException e) {
+            return null;
+        }
+    }
+
+    public static ObjectNode createObjectNode() {
+        return mapper.createObjectNode();
+    }
+
+    public static String toStr(@NonNull Object o) {
+        try {
+            return format(mapper.writeValueAsString(o));
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("toStr转换异常");
+        }
+    }
+
+    public static <T> T toBean(String json, Class<T> clz) {
+        try {
+            return mapper.readValue(format(json), clz);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T toBean(String json, TypeReference<T> typeRef) {
+        try {
+            return mapper.readValue(format(json), typeRef);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T toBean(Object o, Class<T> clz) {
+        try {
+            return mapper.readValue(o.toString(), clz);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> List<T> convertJsonNodeToList(JsonNode jsonNode, Class<T> clazz) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        return objectMapper.convertValue(jsonNode, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
+    }
+
+    private static JavaType collectionType(Class<?> collectionClz, Class<?>... elementClz) {
+        return mapper.getTypeFactory().constructParametricType(collectionClz, elementClz);
+    }
+
+    private static String format(String str) {
+        return str.replaceAll("\r|\n", "");
+    }
+
+
+    public static String serializeObjectToString(Object object) {
+        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+
+            oos.writeObject(object);
+
+            // 使用Base64编码将字节数组转换为字符串
+            return java.util.Base64.getEncoder().encodeToString(bos.toByteArray());
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    // 将字符串反序列化为对象
+    public static <T> T deserializeStringToObject(String serializedString) {
+        try (ByteArrayInputStream bis = new ByteArrayInputStream(java.util.Base64.getDecoder().decode(serializedString));
+             ObjectInputStream ois = new ObjectInputStream(bis)) {
+
+            // 读取对象
+            return (T) ois.readObject();
+
+        } catch (IOException | ClassNotFoundException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

+ 167 - 0
common/common-core/src/main/java/cn/poyee/common/util/OkHttpUtils.java

@@ -0,0 +1,167 @@
+package cn.poyee.common.util;
+
+import okhttp3.*;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
+@Component
+public class OkHttpUtils {
+    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+    private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
+
+    @Resource
+    private OkHttpClient okHttpClient;
+
+    /**
+     * get 请求
+     *
+     * @param url 请求url地址
+     * @return string
+     */
+    public String doGet(String url) {
+        return doGet(url, null, null);
+    }
+
+
+    /**
+     * get 请求
+     *
+     * @param url    请求url地址
+     * @param params 请求参数 map
+     * @return string
+     */
+    public String doGet(String url, Map<String, Object> params) {
+        return doGet(url, params, null);
+    }
+
+    /**
+     * get 请求
+     *
+     * @param url     请求url地址
+     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
+     * @return string
+     */
+    public String doGetWithHeaders(String url, Map<String, Object> headers) {
+        return doGet(url, null, headers);
+    }
+
+
+    /**
+     * get 请求
+     *
+     * @param url     请求url地址
+     * @param params  请求参数 map
+     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
+     * @return string
+     */
+    public String doGet(String url, Map<String, Object> params, Map<String, Object> headers) {
+        StringBuilder sb = new StringBuilder(url);
+        if (params != null && params.keySet().size() > 0) {
+            boolean firstFlag = true;
+            for (String key : params.keySet()) {
+                if (firstFlag) {
+                    sb.append("?").append(key).append("=").append(params.get(key));
+                    firstFlag = false;
+                } else {
+                    sb.append("&").append(key).append("=").append(params.get(key));
+                }
+            }
+        }
+        Request.Builder builder = getBuilderWithHeaders(headers);
+        Request request = builder.url(sb.toString()).build();
+        return execute(request);
+    }
+
+    /**
+     * post 请求
+     *
+     * @param url     请求url地址
+     * @param params  请求参数 map
+     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
+     * @return string
+     */
+    public String doPost(String url, Map<String, Object> params, Map<String, Object> headers) {
+        FormBody.Builder formBuilder = new FormBody.Builder();
+
+        if (params != null && params.keySet().size() > 0) {
+            for (String key : params.keySet()) {
+                formBuilder.add(key, params.get(key).toString());
+            }
+        }
+        Request.Builder builder = getBuilderWithHeaders(headers);
+
+        Request request = builder.url(url).post(formBuilder.build()).build();
+        return execute(request);
+    }
+
+    private Request.Builder getBuilderWithHeaders(Map<String, Object> headers) {
+        Request.Builder builder = new Request.Builder();
+        if (!headers.isEmpty()) {
+            for (Map.Entry<String, Object> entry : headers.entrySet()) {
+                builder.addHeader(entry.getKey(), entry.getValue().toString());
+            }
+        }
+        return builder;
+    }
+
+
+    /**
+     * post 请求, 请求数据为 json 的字符串
+     *
+     * @param url  请求url地址
+     * @param json 请求数据, json 字符串
+     * @return string
+     */
+    public String doPostJson(String url, String json) {
+        return executePost(url, json, JSON, Collections.EMPTY_MAP);
+    }
+
+    /**
+     * post 请求, 请求数据为 json 的字符串
+     *
+     * @param url     请求url地址
+     * @param json    请求数据, json 字符串
+     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
+     * @return string
+     */
+    public String doPostJsonWithHeaders(String url, String json, Map<String, Object> headers) {
+        return executePost(url, json, JSON, headers);
+    }
+
+    /**
+     * post 请求, 请求数据为 xml 的字符串
+     *
+     * @param url 请求url地址
+     * @param xml 请求数据, xml 字符串
+     * @return string
+     */
+    public String doPostXml(String url, String xml) {
+        return executePost(url, xml, XML, null);
+    }
+
+    private String executePost(String url, String data, MediaType contentType, Map<String, Object> headers) {
+        RequestBody requestBody = RequestBody.create(contentType, data.getBytes(StandardCharsets.UTF_8));
+        Request.Builder builder = getBuilderWithHeaders(headers);
+        Request request = builder.url(url).post(requestBody).build();
+
+        return execute(request);
+    }
+
+    private String execute(Request request) {
+        try (Response response = okHttpClient.newCall(request).execute()) {
+            if (response.isSuccessful()) {
+                return response.body().string();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e.getMessage());
+        }
+        return null;
+    }
+
+}
+

+ 3 - 0
common/common-core/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  cn.poyee.common.config.OkHttpConfiguration,\
+  cn.poyee.common.util.OkHttpUtils

+ 0 - 0
common/common-elasticsearch/README.md


+ 24 - 0
common/common-elasticsearch/pom.xml

@@ -0,0 +1,24 @@
+<?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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-elasticsearch</artifactId>
+
+    <dependencies>
+        <!-- elasticsearch -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 10 - 0
common/common-elasticsearch/src/main/java/cn/poyee/common/elasticsearch/config/ElasticProperties.java

@@ -0,0 +1,10 @@
+package cn.poyee.common.elasticsearch.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "spring.elasticsearch")
+public class ElasticProperties {
+    private String[] nodes;
+}

+ 28 - 0
common/common-elasticsearch/src/main/java/cn/poyee/common/elasticsearch/config/ElasticSearchConfig.java

@@ -0,0 +1,28 @@
+package cn.poyee.common.elasticsearch.config;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
+import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
+import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
+
+import javax.annotation.Resource;
+
+@Configuration
+@EnableConfigurationProperties({ElasticProperties.class})
+public class ElasticSearchConfig {
+
+    @Resource
+    public ElasticProperties properties;
+
+    @Bean
+    public ElasticsearchConverter elasticsearchConverter() {
+        return new MappingElasticsearchConverter(elasticsearchMappingContext());
+    }
+
+    @Bean
+    public SimpleElasticsearchMappingContext elasticsearchMappingContext() {
+        return new SimpleElasticsearchMappingContext();
+    }
+}

+ 1 - 0
common/common-elasticsearch/src/main/resources/META-INF/spring.factories

@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

+ 35 - 0
common/common-mybatis/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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-mybatis</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.2.15</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.2</version>
+        </dependency>
+    </dependencies>
+</project>

+ 22 - 0
common/common-mybatis/src/main/java/cn/poyee/common/mybatis/config/MybatisPlusConfig.java

@@ -0,0 +1,22 @@
+package cn.poyee.common.mybatis.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration
+@RequiredArgsConstructor
+@EnableTransactionManagement
+public class MybatisPlusConfig {
+
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+}

+ 2 - 0
common/common-mybatis/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+    cn.poyee.common.mybatis.config.MybatisPlusConfig

+ 29 - 0
common/common-openapi/pom.xml

@@ -0,0 +1,29 @@
+<?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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-openapi</artifactId>
+
+    <dependencies>
+
+        <!--SpringDoc-->
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-ui</artifactId>
+            <version>1.6.14</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-springdoc-ui</artifactId>
+            <version>3.0.3</version>
+        </dependency>
+    </dependencies>
+</project>

+ 38 - 0
common/common-openapi/src/main/java/cn/poyee/common/openapi/config/OpenApiConfig.java

@@ -0,0 +1,38 @@
+package cn.poyee.common.openapi.config;
+
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import lombok.RequiredArgsConstructor;
+import org.springdoc.core.GroupedOpenApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@RequiredArgsConstructor
+@Configuration
+public class OpenApiConfig {
+
+    private String title = "埋点数据分析系统";
+    private String description = "埋点数据分析系统";
+    private String version = "v0.0.1";
+    private String websiteName = "上海珀懿电子商务有限公司";
+    private String websiteUrl = "http://www.poyee.com";
+
+    @Bean
+    public OpenAPI openAPI() {
+        return new OpenAPI()
+                .info(new Info().title(title)
+                        .description(description)
+                        .version(version))
+                .externalDocs(new ExternalDocumentation().description(websiteName)
+                        .url(websiteUrl));
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi() {
+        return GroupedOpenApi.builder()
+                .group("埋点数据分析系统")
+                .pathsToMatch("/**")
+                .build();
+    }
+}

+ 2 - 0
common/common-openapi/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+    cn.poyee.common.openapi.config.OpenApiConfig

+ 57 - 0
common/common-redis/pom.xml

@@ -0,0 +1,57 @@
+<?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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-redis</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.hobbystocks</groupId>
+            <artifactId>common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!-- redisson -->
+<!--        <dependency>-->
+<!--            <groupId>org.redisson</groupId>-->
+<!--            <artifactId>redisson</artifactId>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-cache</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.esotericsoftware</groupId>
+            <artifactId>kryo</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 39 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/cache/CustomRedisCacheManager.java

@@ -0,0 +1,39 @@
+package cn.poyee.common.redis.cache;
+
+import org.springframework.data.redis.cache.RedisCache;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.util.StringUtils;
+
+import java.time.Duration;
+import java.util.Objects;
+
+public class CustomRedisCacheManager extends RedisCacheManager {
+
+    public CustomRedisCacheManager(RedisCacheWriter cacheWriter,
+                                   RedisCacheConfiguration defaultCacheConfiguration) {
+
+        super(cacheWriter, defaultCacheConfiguration);
+    }
+
+    @Override
+    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
+
+        String[] cells = StringUtils.delimitedListToStringArray(name, "#");
+        if (0 == cells.length || 1 == cells.length) {
+            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(-1));
+        } else if (cells.length > 2) {
+            throw new RuntimeException("Cacheable注解中不能包含两个#号");
+        } else {
+            name = cells[0];
+            if (Objects.isNull(cells[1])) {
+                throw new RuntimeException("Cacheable注解中#后必须要有整数型的过期时间值(或更换value的值)");
+            }
+            long ttl = Long.parseLong(cells[1]);
+            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
+        }
+
+        return super.createRedisCache(name, cacheConfig);
+    }
+}

+ 41 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/cache/RedisTemplateConfig.java

@@ -0,0 +1,41 @@
+package cn.poyee.common.redis.cache;
+
+import cn.poyee.common.redis.kryo.KryoRedisSerializer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Slf4j
+@Configuration
+@AutoConfigureBefore(RedisAutoConfiguration.class)
+public class RedisTemplateConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(factory);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        KryoRedisSerializer<Object> kryoRedisSerializer = new KryoRedisSerializer<>(Object.class);
+
+        template.setKeySerializer(stringRedisSerializer);
+        template.setValueSerializer(kryoRedisSerializer);
+
+        template.setHashKeySerializer(stringRedisSerializer);
+        template.setHashValueSerializer(stringRedisSerializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    RedisMessageListenerContainer container(LettuceConnectionFactory factory) {
+        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(factory);
+        return container;
+    }
+}

+ 27 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoPool.java

@@ -0,0 +1,27 @@
+package cn.poyee.common.redis.kryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.util.Pool;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class KryoPool extends Pool<Kryo> {
+
+    private List<Class> clz = new ArrayList<>();
+
+    public KryoPool(Class... cl) {
+        super(true, true);
+        Collections.addAll(clz, cl);
+    }
+
+    @Override
+    protected Kryo create() {
+        Kryo kryo = new Kryo();
+        // 可自定义配置
+        kryo.setReferences(true);
+        kryo.setRegistrationRequired(false);
+        return kryo;
+    }
+}

+ 71 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoRedisSerializer.java

@@ -0,0 +1,71 @@
+package cn.poyee.common.redis.kryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+import java.io.ByteArrayOutputStream;
+
+@Slf4j
+public class KryoRedisSerializer<T> implements RedisSerializer<T> {
+
+    public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    private Class<T> clazz;
+
+    private final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {
+        Kryo kryo = new Kryo();
+        // 检测循环依赖,默认值为true,避免版本变化显式设置
+        kryo.setReferences(true);
+        // 默认值为true,避免版本变化显式设置
+        kryo.setRegistrationRequired(false);
+        kryo.register(clazz);
+        return kryo;
+    });
+
+    public KryoRedisSerializer(Class<T> clazz) {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException {
+        if (t == null) {
+            return EMPTY_BYTE_ARRAY;
+        }
+
+        Kryo kryo = getKryo();
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             Output output = new Output(baos)) {
+            kryo.writeClassAndObject(output, t);
+            output.flush();
+            return baos.toByteArray();
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException {
+
+        if (bytes == null || bytes.length <= 0) {
+            return null;
+        }
+
+        Kryo kryo = getKryo();
+        try (Input input = new Input(bytes)) {
+            return (T) kryo.readClassAndObject(input);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return null;
+    }
+
+    private Kryo getKryo() {
+        return kryoLocal.get();
+    }
+}

+ 109 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/kryo/KryoUtil.java

@@ -0,0 +1,109 @@
+package cn.poyee.common.redis.kryo;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisConnectionUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+
+@Slf4j
+@Component
+public class KryoUtil<T> {
+
+    private static final String DEFAULT_ENCODING = "UTF-8";
+
+    @Resource
+    private StringRedisTemplate template;
+
+    public KryoUtil() {
+
+    }
+
+    /**
+     * 获取缓存的key * * @param id * @return
+     */
+    private <T> byte[] getKey(String prefix, T id) {
+        RedisSerializer serializer = template.getKeySerializer();
+        byte[] idBytes = serializer.serialize(id);
+        byte[] prefixBytes = (prefix + ":").getBytes();
+        byte[] key = new byte[prefixBytes.length + idBytes.length];
+        System.arraycopy(prefixBytes, 0, key, 0, prefixBytes.length);
+        System.arraycopy(idBytes, 0, key, prefixBytes.length, idBytes.length);
+        return key;
+    }
+
+    public boolean set(String prefix, String key, T t, Class<T> clz) {
+
+        RedisSerializer serializer = new KryoRedisSerializer<>(clz);
+        RedisConnection connection = getConnection();
+
+        if (null != connection) {
+            try {
+                return connection.set(getKey(prefix, key), serializer.serialize(t));
+            } finally {
+                releaseConnection(connection);
+            }
+        } else {
+            log.error("1. can not get valid connection");
+        }
+
+        return false;
+    }
+
+    public <T> T get(String prefix, String key, Class<T> clz) {
+
+        RedisConnection connection = getConnection();
+        byte[] result;
+        byte[] serializeKey = getKey(prefix, key);
+        try {
+            result = connection.get(serializeKey);
+        } finally {
+            releaseConnection(connection);
+        }
+        return (T) new KryoRedisSerializer<>(clz).deserialize(result);
+    }
+
+    /**
+     * 删除指定对象
+     *
+     * @param key
+     * @return
+     */
+    public long del(String prefix, String key) {
+        RedisConnection connection = getConnection();
+        long rlt = 0L;
+        if (null != connection) {
+            try {
+                rlt = connection.del(getKey(prefix, key));
+            } finally {
+                releaseConnection(connection);
+            }
+        } else {
+            log.error("1. can not get valid connection");
+        }
+        return rlt;
+    }
+
+    private RedisConnection getConnection() {
+        return Objects.requireNonNull(template.getConnectionFactory()).getConnection();
+    }
+
+    /**
+     * 释放连接
+     *
+     * @param redisConnection
+     */
+    private void releaseConnection(RedisConnection redisConnection) {
+        if (null != redisConnection && null != template) {
+            RedisConnectionFactory redisConnectionFactory = template.getConnectionFactory();
+            if (null != redisConnectionFactory) {
+                RedisConnectionUtils.releaseConnection(redisConnection, redisConnectionFactory);
+            }
+        }
+    }
+}

+ 246 - 0
common/common-redis/src/main/java/cn/poyee/common/redis/service/RedisService.java

@@ -0,0 +1,246 @@
+package cn.poyee.common.redis.service;
+
+import cn.poyee.common.util.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Component
+public class RedisService {
+
+    private static final String LOCK_SCRIPT = "if redis.call('set', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2]) then return true else return false end";
+    private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
+
+    @Resource
+    private StringRedisTemplate template;
+
+    public void set(String key, Object object, long exp, TimeUnit unit) {
+        template.opsForValue().set(key, Objects.requireNonNull(JsonUtil.toStr(object)), exp, unit);
+    }
+
+    public void set(String key, String str, long exp, TimeUnit unit) {
+        template.opsForValue().set(key, Objects.requireNonNull(str), exp, unit);
+    }
+
+    public void set(String key, Object object) {
+        template.opsForValue().set(key, Objects.requireNonNull(JsonUtil.toStr(object)));
+    }
+
+    public void set(String key, String val) {
+        template.opsForValue().set(key, val);
+    }
+
+    public <T> T get(String category, String key, Class<T> clazz) {
+        String v = template.opsForValue().get(category.concat(key));
+        T t = JsonUtil.toBean(v, clazz);
+        return t;
+    }
+
+    /**
+     * lpush 方法 并指定过期时间
+     */
+    public void lPush(String key, String value, Long seconds) {
+        try {
+            template.executePipelined((RedisCallback<String>) connection -> {
+                connection.lPush(key.getBytes(), value.getBytes());
+                connection.expire(key.getBytes(), seconds);
+                return null;
+            });
+        } catch (Exception ex) {
+            log.error("RedisUtils#pipelineSetEx fail! e:{}", ex.getMessage());
+        }
+    }
+
+    public void pipelineSetEx(Map<String, String> keyValues, Long seconds) {
+        try {
+            template.executePipelined((RedisCallback<String>) connection -> {
+                for (Map.Entry<String, String> entry : keyValues.entrySet()) {
+                    connection.setEx(entry.getKey().getBytes(), seconds,
+                            entry.getValue().getBytes());
+                }
+                return null;
+            });
+        } catch (Exception ex) {
+            log.error("RedisUtils#pipelineSetEx fail! e:{}", ex.getMessage());
+        }
+    }
+
+    public Long lastIndexOf(String key, String value) {
+        return template.opsForList().lastIndexOf(key, value);
+    }
+
+    public Long listRemove(String key, long count, String value) {
+        return template.opsForList().remove(key, count, value);
+    }
+
+    public Long listSize(String key) {
+        return template.opsForList().size(key);
+    }
+
+    public <T> T get(String key, Class<T> clazz) {
+        String v = template.opsForValue().get(key);
+        if (Objects.isNull(v)) {
+            return null;
+        }
+        return JsonUtil.toBean(v, clazz);
+    }
+
+    public String get(String key) {
+        String v = template.opsForValue().get(key);
+        if (Objects.isNull(v)) {
+            return null;
+        }
+        return v;
+    }
+
+    public String get(String category, String key) {
+        return template.opsForValue().get(category.concat(key));
+    }
+
+    //
+    public void delete(String key) {
+        template.delete(key);
+    }
+
+    public void delete(Collection<String> keys) {
+        template.delete(keys);
+    }
+
+    public void delete(List<String> keys) {
+        template.delete(keys);
+    }
+
+    public Set<String> keys(String pattern) {
+        return template.keys(pattern);
+    }
+
+    public Set<String> keys(String category, String pattern) {
+        return template.keys(category + pattern);
+    }
+
+    public List<String> multiGet(Set<String> pattern) {
+        return template.opsForValue().multiGet(pattern);
+    }
+
+    public void multiSet(Map<String, String> pattern) {
+        template.opsForValue().multiSet(pattern);
+    }
+
+    public Map<Object, Object> hmget(String key) {
+        template.opsForHash().entries(key);
+        return template.opsForHash().entries(key);
+    }
+
+    public String hmget(String key, String hmkey) {
+        Object obj = template.opsForHash().get(key, hmkey);
+
+        return String.valueOf(obj);
+    }
+
+    public Set<Object> hmkeys(String key) {
+        return template.opsForHash().keys(key);
+    }
+
+    public boolean putAll(String key, Object object) {
+        try {
+            set(key, object);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public long hmdel(String key, String hkey) {
+        return template.opsForHash().delete(key, hkey);
+    }
+
+    public boolean hmhas(String key, String hkey) {
+        return template.opsForHash().hasKey(key, hkey);
+    }
+
+    public long leftPush(String key, String values) {
+        return template.opsForList().leftPush(key, values);
+
+    }
+
+    public Boolean hasKey(String key) {
+        return template.hasKey(key);
+    }
+
+    public Long setRemove(String key, String... v) {
+        return template.opsForSet().remove(key, v);
+    }
+
+    public Long setAdd(String key, String... v) {
+        return template.opsForSet().add(key, v);
+    }
+
+    public Long setSize(String key) {
+        return template.opsForSet().size(key);
+    }
+
+    public boolean expire(String key, long exp, TimeUnit unit) {
+        return Boolean.TRUE.equals(template.expire(key, exp, unit));
+    }
+
+
+    public Long removeRange(String key, long start, long end) {
+        return template.opsForZSet().removeRange(key, start, end);
+    }
+
+    public Set reverseRange(String key, long start, long end) {
+        return template.opsForZSet().reverseRange(key, start, end);
+    }
+
+    public Long increment(String key, Long val, final long timeout, final TimeUnit unit) {
+        if (null == val) {
+            val = 1L;
+        }
+        final Long increment = template.opsForValue().increment(key, val);
+        template.expire(key, timeout, unit);
+        return increment;
+    }
+
+    public Double increment(String key, Double val, final long timeout, final TimeUnit unit) {
+        if (null == val) {
+            val = 1D;
+        }
+        final Double increment = template.opsForValue().increment(key, val);
+        template.expire(key, timeout, unit);
+        return increment;
+    }
+
+    public Long decrement(String key, final long timeout, final TimeUnit unit) {
+        final Long decrement = template.opsForValue().decrement(key);
+        template.expire(key, timeout, unit);
+        return decrement;
+    }
+
+    public boolean setBit(String key, int idx, boolean bool) {
+        return template.opsForValue().setBit(key, idx, bool);
+    }
+
+    public boolean getBit(String key, int idx) {
+        return template.opsForValue().getBit(key, idx);
+    }
+
+    public boolean acquireLock(String lockKey, String requestId, int expireTime) {
+        RedisScript<Boolean> script = new DefaultRedisScript<>(LOCK_SCRIPT, Boolean.class);
+        Boolean result = template.execute(script, Collections.singletonList(lockKey), requestId, String.valueOf(expireTime));
+        return result != null && result;
+    }
+
+    public void releaseLock(String lockKey, String requestId) {
+        RedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
+        template.execute(script, Collections.singletonList(lockKey), requestId);
+    }
+}

+ 5 - 0
common/common-redis/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,5 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+    cn.poyee.common.redis.kryo.KryoUtil,\
+    cn.poyee.common.redis.service.RedisService,\
+    cn.poyee.common.redis.cache.RedisTemplateConfig,\
+    cn.poyee.common.redis.kryo.KryoUtil

+ 39 - 0
common/common-web/pom.xml

@@ -0,0 +1,39 @@
+<?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>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>common-web</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>cn.hobbystocks</groupId>
+            <artifactId>common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+
+    </dependencies>
+</project>

+ 40 - 0
common/common-web/src/main/java/cn/poyee/common/web/exception/BusinessException.java

@@ -0,0 +1,40 @@
+package cn.poyee.common.web.exception;
+
+import cn.poyee.common.result.IResultCode;
+import lombok.Getter;
+
+/**
+ * 自定义业务异常
+ *
+ * @author haoxr
+ * @date 2022/7/31
+ */
+@Getter
+public class BusinessException extends RuntimeException {
+
+    public IResultCode resultCode;
+
+    public BusinessException(IResultCode errorCode) {
+        super(errorCode.getMsg());
+        this.resultCode = errorCode;
+    }
+
+    public BusinessException(IResultCode errorCode,String errorMsg) {
+        super(errorMsg);
+        this.resultCode = errorCode;
+    }
+
+    public BusinessException(String message) {
+        super(message);
+    }
+
+    public BusinessException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public BusinessException(Throwable cause) {
+        super(cause);
+    }
+
+
+}

+ 115 - 0
common/common-web/src/main/java/cn/poyee/common/web/exception/GlobalExceptionHandler.java

@@ -0,0 +1,115 @@
+package cn.poyee.common.web.exception;
+
+import cn.poyee.common.result.Result;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.core.NestedRuntimeException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.ServletException;
+import java.util.concurrent.CompletionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(ServletException.class)
+    public <T> Result<T> processException(ServletException e) {
+        log.error(e.getMessage(), e);
+        return Result.failed(e.getMessage());
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(IllegalArgumentException.class)
+    public <T> Result<T> handleIllegalArgumentException(IllegalArgumentException e) {
+        log.error("非法参数异常,异常原因:{}", e.getMessage(), e);
+        return Result.failed(e.getMessage());
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(JsonProcessingException.class)
+    public <T> Result<T> handleJsonProcessingException(JsonProcessingException e) {
+        log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
+        return Result.failed(e.getMessage());
+    }
+
+    /**
+     * HttpMessageNotReadableException
+     */
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public <T> Result<T> processException(HttpMessageNotReadableException e) {
+        log.error(e.getMessage(), e);
+        String errorMessage = "请求体不可为空";
+        Throwable cause = e.getCause();
+        if (cause != null) {
+            errorMessage = convertMessage(cause);
+        }
+        return Result.failed(errorMessage);
+    }
+
+    /**
+     * TypeMismatchException
+     */
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(TypeMismatchException.class)
+    public <T> Result<T> processException(TypeMismatchException e) {
+        log.error(e.getMessage(), e);
+        return Result.failed(e.getMessage());
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(CompletionException.class)
+    public <T> Result<T> processException(CompletionException e) {
+        if (e.getMessage().startsWith("feign.FeignException")) {
+            return Result.failed("微服务调用异常");
+        }
+        return handleException(e);
+    }
+
+    @ResponseStatus(HttpStatus.OK)
+    @ExceptionHandler(BusinessException.class)
+    public <T> Result<T> handleBizException(BusinessException e) {
+        log.error("业务异常,异常原因:{}", e.getMessage(), e);
+        if (e.getResultCode() != null) {
+            return Result.failed(e.getResultCode());
+        }
+        return Result.failed(e.getMessage());
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(NestedRuntimeException.class)
+    public <T> Result<T> nestedRuntimeException(CompletionException e) {
+        log.error(e.getMessage(), e);
+        return Result.failed(e.getMessage());
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(Exception.class)
+    public <T> Result<T> handleException(Exception e) {
+        return Result.failed(e.getLocalizedMessage());
+    }
+
+    private String convertMessage(Throwable throwable) {
+        String error = throwable.toString();
+        String regulation = "\\[\"(.*?)\"]+";
+        Pattern pattern = Pattern.compile(regulation);
+        Matcher matcher = pattern.matcher(error);
+        String group = "";
+        if (matcher.find()) {
+            String matchString = matcher.group();
+            matchString = matchString.replace("[", "").replace("]", "");
+            matchString = matchString.replaceAll("\"", "") + "字段类型错误";
+            group += matchString;
+        }
+        return group;
+    }
+}

+ 2 - 0
common/common-web/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  cn.poyee.common.web.exception.GlobalExceptionHandler

+ 35 - 0
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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>cn.hobbystocks</groupId>
+        <artifactId>UserTracking</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>common</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>common-core</module>
+        <module>common-web</module>
+        <module>common-redis</module>
+        <module>common-elasticsearch</module>
+        <module>common-mybatis</module>
+        <module>common-openapi</module>
+
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>cn.hobbystocks</groupId>
+                <artifactId>common-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>

+ 98 - 0
persist/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">
+    <parent>
+        <artifactId>UserTracking</artifactId>
+        <groupId>cn.hobbystocks</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>persist</artifactId>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+
+        <!-- elasticsearch -->
+        <dependency>
+            <groupId>cn.hobbystocks</groupId>
+            <artifactId>common-elasticsearch</artifactId>
+        </dependency>
+
+        <!-- amqp -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+
+        <!-- logback fluentd -->
+        <dependency>
+            <groupId>org.codehaus.janino</groupId>
+            <artifactId>janino</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sndyuk</groupId>
+            <artifactId>logback-more-appenders</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.fluentd</groupId>
+            <artifactId>fluent-logger</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>cn.hobbystocks</groupId>-->
+<!--            <artifactId>receiver-api</artifactId>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>cn.dynamictp</groupId>
+            <artifactId>dynamic-tp-core</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hobbystocks</groupId>
+            <artifactId>common-redis</artifactId>
+        </dependency>
+
+        <!-- prometheus actuator -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.micrometer</groupId>
+            <artifactId>micrometer-registry-prometheus</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 11 - 0
persist/src/main/java/cn/poyee/datapersist/DataPersistApplication.java

@@ -0,0 +1,11 @@
+package cn.poyee.datapersist;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DataPersistApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(DataPersistApplication.class, args);
+    }
+}

+ 25 - 0
persist/src/main/java/cn/poyee/datapersist/config/ESConfiguration.java

@@ -0,0 +1,25 @@
+package cn.poyee.datapersist.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
+import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
+import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
+
+@Configuration
+public class ESConfiguration {
+
+    @Value("${spring.data.elasticsearch.client.reactive.endpoints}")
+    private String[] esEndpoints;
+
+    @Bean
+    public ElasticsearchConverter elasticsearchConverter() {
+        return new MappingElasticsearchConverter(elasticsearchMappingContext());
+    }
+
+    @Bean
+    public SimpleElasticsearchMappingContext elasticsearchMappingContext() {
+        return new SimpleElasticsearchMappingContext();
+    }
+}

+ 6 - 0
persist/src/main/java/cn/poyee/datapersist/config/MessagingConfiguration.java

@@ -0,0 +1,6 @@
+package cn.poyee.datapersist.config;
+
+public class MessagingConfiguration {
+    public static final String QUEUE_FRONTEND = "frontend";
+    public static final String QUEUE_PAY_CONFIRM = "pay-confirm";
+}

+ 36 - 0
persist/src/main/java/cn/poyee/datapersist/config/PipelineConfig.java

@@ -0,0 +1,36 @@
+package cn.poyee.datapersist.config;
+
+import cn.poyee.datapersist.pending.ProcessController;
+import cn.poyee.datapersist.pending.ProcessTemplate;
+import cn.poyee.datapersist.pending.action.TraceHandlerAction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class PipelineConfig {
+
+    @Autowired
+    private TraceHandlerAction chatHandlerAction;
+
+    @Bean("commonSendTemplate")
+    public ProcessTemplate commonSendTemplate() {
+        ProcessTemplate processTemplate = new ProcessTemplate();
+        processTemplate.setProcessList(Arrays.asList(chatHandlerAction));
+        return processTemplate;
+    }
+
+    @Bean
+    public ProcessController processController() {
+        ProcessController processController = new ProcessController();
+        Map<String, ProcessTemplate> templateConfig = new HashMap<>(1);
+        templateConfig.put("TRACE", commonSendTemplate());
+        processController.setTemplateConfig(templateConfig);
+        return processController;
+    }
+
+}

+ 103 - 0
persist/src/main/java/cn/poyee/datapersist/config/RabbitMQConfiguration.java

@@ -0,0 +1,103 @@
+package cn.poyee.datapersist.config;
+
+import org.springframework.amqp.core.AcknowledgeMode;
+import org.springframework.amqp.rabbit.config.RetryInterceptorBuilder;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.retry.RetryCallback;
+import org.springframework.retry.RetryContext;
+import org.springframework.retry.RetryListener;
+import org.springframework.retry.backoff.ExponentialBackOffPolicy;
+import org.springframework.retry.policy.SimpleRetryPolicy;
+import org.springframework.retry.support.RetryTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RabbitMQConfiguration {
+
+    @Autowired
+    private CachingConnectionFactory cachingConnectionFactory;
+
+    @Bean
+    SimpleRabbitListenerContainerFactory consumerBatchContainerFactory() {
+
+        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+        factory.setConnectionFactory(cachingConnectionFactory);
+        factory.setBatchListener(true);
+        factory.setBatchSize(10);
+        factory.setReceiveTimeout(1000L * 5);
+        factory.setConsumerBatchEnabled(true);
+        return factory;
+    }
+
+    @Bean
+    SimpleRabbitListenerContainerFactory batchContainerFactory() {
+
+        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+        factory.setConnectionFactory(cachingConnectionFactory);
+        factory.setBatchListener(true);
+        factory.setConsumerBatchEnabled(true);
+        // 并发消费者数量
+        factory.setConcurrentConsumers(50);
+        factory.setMaxConcurrentConsumers(50);
+        // 自动应答
+        factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
+        factory.setChannelTransacted(true);
+
+        factory.setAdviceChain(
+                RetryInterceptorBuilder.stateless()
+                        .recoverer(new RejectAndDontRequeueRecoverer())
+                        .retryOperations(rabbitRetryTemplate())
+                        .build());
+        return factory;
+    }
+
+    @Bean
+    public RetryTemplate rabbitRetryTemplate() {
+        RetryTemplate retryTemplate = new RetryTemplate();
+
+        // 设置监听(不是必须)
+        retryTemplate.registerListener(new RetryListener() {
+            @Override
+            public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
+                // 执行之前调用 (返回false时会终止执行)
+                return true;
+            }
+
+            @Override
+            public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
+                // 重试结束的时候调用 (最后一次重试 )
+            }
+
+            @Override
+            public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
+            }
+        });
+
+        retryTemplate.setBackOffPolicy(backOffPolicyByProperties());
+        retryTemplate.setRetryPolicy(retryPolicyByProperties());
+        return retryTemplate;
+    }
+
+    @Bean
+    public ExponentialBackOffPolicy backOffPolicyByProperties() {
+        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
+        // 重试间隔
+        backOffPolicy.setInitialInterval(30 * 1000);
+        // 重试最大间隔
+        backOffPolicy.setMaxInterval(10 * 60 * 1000);
+        // 重试间隔乘法策略
+        backOffPolicy.setMultiplier(2);
+        return backOffPolicy;
+    }
+
+    @Bean
+    public SimpleRetryPolicy retryPolicyByProperties() {
+        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
+        retryPolicy.setMaxAttempts(3);
+        return retryPolicy;
+    }
+}

+ 31 - 0
persist/src/main/java/cn/poyee/datapersist/config/ThreadPoolConfiguration.java

@@ -0,0 +1,31 @@
+package cn.poyee.datapersist.config;
+
+import com.dtp.common.em.QueueTypeEnum;
+import com.dtp.common.em.RejectedTypeEnum;
+import com.dtp.core.support.ThreadPoolBuilder;
+import com.dtp.core.thread.DtpExecutor;
+
+import java.util.concurrent.TimeUnit;
+
+public class ThreadPoolConfiguration {
+
+    public static final Integer COMMON_CORE_POOL_SIZE = 20;
+    public static final Integer COMMON_MAX_POOL_SIZE = 150;
+    public static final Integer COMMON_KEEP_LIVE_TIME = 50;
+    public static final Integer COMMON_QUEUE_SIZE = 128;
+
+    private static final String PRE_FIX = "track.";
+
+    public static DtpExecutor getExecutor(String groupId) {
+        return ThreadPoolBuilder.newBuilder()
+                .threadPoolName(PRE_FIX + groupId)
+                .corePoolSize(COMMON_CORE_POOL_SIZE)
+                .maximumPoolSize(COMMON_MAX_POOL_SIZE)
+                .keepAliveTime(COMMON_KEEP_LIVE_TIME)
+                .timeUnit(TimeUnit.SECONDS)
+                .rejectedExecutionHandler(RejectedTypeEnum.CALLER_RUNS_POLICY.getName())
+                .allowCoreThreadTimeOut(false)
+                .workQueue(QueueTypeEnum.VARIABLE_LINKED_BLOCKING_QUEUE.getName(), COMMON_QUEUE_SIZE, false)
+                .buildDynamic();
+    }
+}

+ 48 - 0
persist/src/main/java/cn/poyee/datapersist/config/ThreadPoolExecutorShutdownDefinition.java

@@ -0,0 +1,48 @@
+package cn.poyee.datapersist.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+@Slf4j
+public class ThreadPoolExecutorShutdownDefinition implements ApplicationListener<ContextClosedEvent> {
+
+    private final List<ExecutorService> POOLS = Collections.synchronizedList(new ArrayList<>(12));
+    private final long AWAIT_TERMINATION = 20;
+    private final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
+
+    public void registryExecutor(ExecutorService executor) {
+        POOLS.add(executor);
+    }
+
+    @Override
+    public void onApplicationEvent(ContextClosedEvent event) {
+        if (CollectionUtils.isEmpty(POOLS)) {
+            return;
+        }
+        for (ExecutorService pool : POOLS) {
+            pool.shutdown();
+            try {
+                if (!pool.awaitTermination(AWAIT_TERMINATION, TIME_UNIT)) {
+                    if (log.isWarnEnabled()) {
+                        log.warn("Timed out while waiting for executor [{}] to terminate", pool);
+                    }
+                }
+            } catch (InterruptedException ex) {
+                if (log.isWarnEnabled()) {
+                    log.warn("Timed out while waiting for executor [{}] to terminate", pool);
+                }
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/$AppEnd.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class $AppEnd implements Event {
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/$AppStart.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class $AppStart implements Event {
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/$SignUp.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class $SignUp implements Event {
+}

+ 8 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AdClick.java

@@ -0,0 +1,8 @@
+package cn.poyee.datapersist.dto;
+
+public class AdClick implements Event {
+    private String adId;
+    private String adName;
+    private String adUrl;
+    private String adType;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AdDetailView.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class AdDetailView implements Event {
+    private String adId;
+    private String adName;
+    private String adUrl;
+    private String adType;
+    private String addetailDuration;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AdShow.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class AdShow implements Event {
+    private String adId;
+    private String adName;
+    private String adType;
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AppCrashed.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class AppCrashed implements Event {
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AppWebSocket.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class AppWebSocket implements Event {
+    private String log;
+}

+ 10 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AppleIDLoginClick.java

@@ -0,0 +1,10 @@
+package cn.poyee.datapersist.dto;
+
+public class AppleIDLoginClick implements Event {
+    private String userCode;
+    private String isLoginSuccess;
+    private String failReason;
+    private String loginSource;
+    private String isNewRegister;
+    private String recId;
+}

+ 13 - 0
persist/src/main/java/cn/poyee/datapersist/dto/AuctionBid.java

@@ -0,0 +1,13 @@
+package cn.poyee.datapersist.dto;
+
+public class AuctionBid implements Event {
+    private String auctionID;
+    private String auctionName;
+    private String storeId;
+    private String storeName;
+    private String roomId;
+    private String roomName;
+    private String bidType;
+    private String bidSource;
+    private String bidResult;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BannerShareClick.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class BannerShareClick implements Event {
+    private String bannerId;
+    private String bannerName;
+    private String shareType;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BannerShareSuccess.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class BannerShareSuccess implements Event {
+    private String bannerId;
+    private String bannerName;
+    private String shareType;
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BlacklistClick.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class BlacklistClick implements Event {
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BlacklistConfirmClick.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class BlacklistConfirmClick implements Event {
+    private String userType;
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BottomMessageClick.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class BottomMessageClick implements Event {
+
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BottomMineClick.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class BottomMineClick implements Event {
+
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BottomZBClick.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class BottomZBClick implements Event {
+
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/BottomZTCKClick.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class BottomZTCKClick implements Event {
+}

+ 8 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductClick.java

@@ -0,0 +1,8 @@
+package cn.poyee.datapersist.dto;
+
+public class CalendarProductClick implements Event {
+    private String calendarProductId;
+    private String calendarProductName;
+    private String calendarProductListId;
+    private String calendarProductSource;
+}

+ 8 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductLikes.java

@@ -0,0 +1,8 @@
+package cn.poyee.datapersist.dto;
+
+public class CalendarProductLikes implements Event {
+    private String calendarProductId;
+    private String calendarProductName;
+    private String calendarLikesStatus;
+    private String calendarLikesSource;
+}

+ 8 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductShare.java

@@ -0,0 +1,8 @@
+package cn.poyee.datapersist.dto;
+
+public class CalendarProductShare implements Event {
+    private String calendarProductId;
+    private String calendarProductName;
+    private String shareSource;
+    private String shareType;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CalendarProductView.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class CalendarProductView implements Event {
+    private String calendarProductId;
+    private String calendarProductName;
+    private String calendarProductListId;
+    private String calendarProductSource;
+    private int calendarProductDuration;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CalendarView.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class CalendarView implements Event {
+    private String calendarName;
+    private int calendarDuration;
+    private String calendarSource;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CancelCollectProductClick.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class CancelCollectProductClick implements Event {
+    private String productId;
+    private String productName;
+    private String collectSouce;
+}

+ 14 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CancelFollowShopClick.java

@@ -0,0 +1,14 @@
+package cn.poyee.datapersist.dto;
+
+public class CancelFollowShopClick implements Event {
+    private Integer shopId;
+    private String shopName;
+    private String followSouce;
+
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String productId;
+    private String productCode;
+    private String productName;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CardPlaybackClick.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class CardPlaybackClick implements Event {
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String orderId;
+    private String cardName;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CardReportClick.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class CardReportClick implements Event {
+    private String orderId;
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String cardreportSouce;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CardlistClick.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class CardlistClick implements Event {
+    private String groupId;
+    private String groupName;
+    private String isBuyCard;
+}

+ 30 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickBuy.java

@@ -0,0 +1,30 @@
+package cn.poyee.datapersist.dto;
+
+import lombok.Getter;
+
+@Getter
+public class ClickBuy implements Event {
+
+    private String productId;
+    private String productCode;
+    private String productName;
+    private String productType;
+    private String[] productTag;
+    private float productPrice;
+    private float productReferenceprice;
+    private int productIntegral;
+    private int productQuantity;
+    private int productInstock;
+    private String storeId;
+    private String storeName;
+    private String buySouce;
+
+    private String productActivityType;
+    private String productRemarks;
+    private long productSku;
+    private String productSkuName;
+    private float productSkuPrice;
+    private int productSkuIntegral;
+    private String productNormalType;
+    private String productDisplay;
+}

+ 30 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickGroup.java

@@ -0,0 +1,30 @@
+package cn.poyee.datapersist.dto;
+
+import lombok.Getter;
+
+@Getter
+public class ClickGroup implements Event {
+
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String groupSport;
+    private String groupSource;
+    private String groupPrice;
+    private String groupState;
+    private String groupPlay;
+    private String groupProgress;
+    private String groupYear;
+    private String groupManufacturer;
+    private String groupSets;
+    private String groupSpecifications;
+    private String groupType;
+    private int groupQuantity;
+    private String storeId;
+    private String storeName;
+    private String recId;
+    private String payType;
+    private String paniniBaseId;
+    private String groupStartTime;
+    private String groupDisplay;
+}

+ 14 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupBuy.java

@@ -0,0 +1,14 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickGroupBuy implements Event {
+
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String groupType;
+    private String groupPrice;
+    private String storeId;
+    private String storeName;
+    private String payType;
+    private String groupDisplay;
+}

+ 11 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupBuy2.java

@@ -0,0 +1,11 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickGroupBuy2 implements Event {
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String groupType;
+    private String groupPrice;
+    private String storeId;
+    private String storeName;
+}

+ 20 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupRoom.java

@@ -0,0 +1,20 @@
+package cn.poyee.datapersist.dto;
+
+import lombok.Getter;
+
+@Getter
+public class ClickGroupRoom implements Event {
+
+    private String roomId;
+    private String roomName;
+    private String playerId;
+    private String playerName;
+    private String roomSource;
+    private Integer shopId;
+    private String shopName;
+    private String status;
+
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickGroupTab.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickGroupTab implements Event {
+
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickMall.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickMall implements Event {
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickOnTheTeamSearchBar.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickOnTheTeamSearchBar implements Event {
+    private String searchSource;
+}

+ 27 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickProduct.java

@@ -0,0 +1,27 @@
+package cn.poyee.datapersist.dto;
+
+import lombok.Getter;
+
+@Getter
+public class ClickProduct implements Event {
+    private String productId;
+    private String productCode;
+    private String productName;
+    private String productSource;
+    private float productPrice;
+    private int productIntegral;
+    private String productType;
+    private String productCategory;
+    private String productShoptype;
+    private String productRules;
+    private String productSku;
+    private String productSpu;
+    private String storeId;
+    private String storeName;
+
+    private String productActivityType;
+    private String productRemarks;
+    private String productState;
+    private String productNormalType;
+    private String productDisplay;
+}

+ 13 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickRoom.java

@@ -0,0 +1,13 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickRoom implements Event {
+
+    private String roomId;
+    private String roomName;
+    private String roomSource;
+    private String playerId;
+    private String playerName;
+    private Integer shopId;
+    private String shopName;
+    private String status;
+}

+ 10 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ClickRoomShoppingCart.java

@@ -0,0 +1,10 @@
+package cn.poyee.datapersist.dto;
+
+public class ClickRoomShoppingCart implements Event {
+    private String roomId;
+    private String roomName;
+    private String playerId;
+    private String playerName;
+    private String storeId;
+    private String storeName;
+}

+ 7 - 0
persist/src/main/java/cn/poyee/datapersist/dto/CollectProductClick.java

@@ -0,0 +1,7 @@
+package cn.poyee.datapersist.dto;
+
+public class CollectProductClick implements Event {
+    private String productId;
+    private String productName;
+    private String collectSouce;
+}

+ 10 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ConfirmExpressClick.java

@@ -0,0 +1,10 @@
+package cn.poyee.datapersist.dto;
+
+public class ConfirmExpressClick implements Event {
+
+    private String storeId;
+    private String storeName;
+    private String orderNo;
+    private String expressName;
+    private String expressNo;
+}

+ 12 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ConfirmShipmentClick.java

@@ -0,0 +1,12 @@
+package cn.poyee.datapersist.dto;
+
+public class ConfirmShipmentClick implements Event {
+
+    private String storeId;
+    private String storeName;
+    private String groupId;
+    private String groupCode;
+    private String groupName;
+    private String isSuccess;
+    private String failReason;
+}

+ 12 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentClick.java

@@ -0,0 +1,12 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentClick implements Event {
+    private String contentId;
+    private String contentTitle;
+    private String storeId;
+    private String storeName;
+    private String contentType;
+    private String contentMediaType;
+    private String contentStyleType;
+    private String contentSource;
+}

+ 13 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentDetail.java

@@ -0,0 +1,13 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentDetail implements Event {
+    private String contentId;
+    private String contentTitle;
+    private String storeId;
+    private String storeName;
+    private String contentDuration;
+    private String contentType;
+    private String contentMediaType;
+    private String contentStyleType;
+    private String contentSource;
+}

+ 5 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchClick.java

@@ -0,0 +1,5 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentSearchClick implements Event {
+    private String searchSource;
+}

+ 6 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchRequest.java

@@ -0,0 +1,6 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentSearchRequest implements Event {
+    private String keyWord;
+    private int resultNumber;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentSearchResultClick.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentSearchResultClick implements Event {
+    private String keyWord;
+    private int resultNumber;
+    private int positionNumber;
+    private String productId;
+    private String productName;
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentShare.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentShare implements Event {
+    private String contentId;
+    private String contentTitle;
+    private String storeId;
+    private String storeName;
+    private String shareType;
+}

+ 13 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ContentView.java

@@ -0,0 +1,13 @@
+package cn.poyee.datapersist.dto;
+
+public class ContentView implements Event {
+    private String contentId;
+    private String contentTitle;
+    private String storeId;
+    private String storeName;
+    private String contentDuration;
+    private String contentType;
+    private String contentMediaType;
+    private String contentStyleType;
+    private String contentSource;
+}

+ 4 - 0
persist/src/main/java/cn/poyee/datapersist/dto/Event.java

@@ -0,0 +1,4 @@
+package cn.poyee.datapersist.dto;
+
+public interface Event {
+}

+ 9 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ExchangeActionConfirmExClick.java

@@ -0,0 +1,9 @@
+package cn.poyee.datapersist.dto;
+
+public class ExchangeActionConfirmExClick implements Event {
+
+    private String activityId;
+    private String activityName;
+    private int activityExchangeNumber;
+    private String isExchangeSuccess;
+}

+ 8 - 0
persist/src/main/java/cn/poyee/datapersist/dto/ExchangeActionExProductClick.java

@@ -0,0 +1,8 @@
+package cn.poyee.datapersist.dto;
+
+public class ExchangeActionExProductClick implements Event {
+    private String activityId;
+    private String activityName;
+    private Float activityEachpoint;
+    private int activityNumber;
+}

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov