zhouyang před 2 roky
rodič
revize
bcc0087d99
38 změnil soubory, kde provedl 2701 přidání a 0 odebrání
  1. 45 0
      Marketing/marketing-api/pom.xml
  2. 12 0
      Marketing/marketing-api/src/main/java/com/mofang/travel/marketing/api/BikeIconServiceApi.java
  3. 172 0
      Marketing/marketing-base/pom.xml
  4. 17 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/Application.java
  5. 23 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/BikeIcon.java
  6. 107 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/RidingCardType.java
  7. 101 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/UserRidingCard.java
  8. 59 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/config/LogAspect.java
  9. 28 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/config/RestTemplateConfig.java
  10. 22 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/controller/admin/BikeIconController.java
  11. 22 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/controller/mini/mBikeIconController.java
  12. 35 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/enums/StatusEnum.java
  13. 49 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/handler/GlobalExceptionHandler.java
  14. 14 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/mapper/BikeIconMapper.java
  15. 19 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/mapper/UserRidingCardMapper.java
  16. 269 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/redis/RedisClient.java
  17. 13 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/BikeIconService.java
  18. 4 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/UserRidingCardService.java
  19. 33 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/impl/BikeIconServiceImpl.java
  20. 34 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/impl/UserRidingCardServiceImpl.java
  21. 159 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/CommonUtil.java
  22. 56 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/GenerateCodeUtil.java
  23. 34 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/JsonUtils.java
  24. 73 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/ListUtil.java
  25. 46 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/MD5Util.java
  26. 134 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/RandomUtils.java
  27. 669 0
      Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/RegexUtils.java
  28. 1 0
      Marketing/marketing-base/src/main/resources/META-INF/app.properties
  29. 79 0
      Marketing/marketing-base/src/main/resources/application.yaml
  30. 9 0
      Marketing/marketing-base/src/main/resources/config/mybatis.xml
  31. 18 0
      Marketing/marketing-base/src/main/resources/logback-dev.xml
  32. 72 0
      Marketing/marketing-base/src/main/resources/logback-prod.xml
  33. 17 0
      Marketing/marketing-base/src/main/resources/sqlmap/BikeIconMapper.xml
  34. 51 0
      Marketing/marketing-base/src/main/resources/sqlmap/UserRidingCardMapper.xml
  35. 67 0
      Marketing/marketing-domain/pom.xml
  36. 25 0
      Marketing/marketing-domain/src/main/java/com/mofang/travel/marketing/domain/entity/BikeIconVo.java
  37. 38 0
      Marketing/marketing-domain/src/main/java/com/mofang/travel/marketing/domain/enums/BikeStatusEnum.java
  38. 75 0
      Marketing/pom.xml

+ 45 - 0
Marketing/marketing-api/pom.xml

@@ -0,0 +1,45 @@
+<?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>com.mofang.travel.marketing</groupId>
+        <artifactId>marketing</artifactId>
+        <version>0.0.1</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.mofang.travel.marketing</groupId>
+    <artifactId>marketing-api</artifactId>
+    <version>${version}</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.mofang.travel.marketing</groupId>
+            <artifactId>marketing-domain</artifactId>
+            <version>${version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>marketing-api</finalName>
+        <plugins>
+            <!-- 要将源码放上去,需要加入这个插件 -->
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <attach>true</attach>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 12 - 0
Marketing/marketing-api/src/main/java/com/mofang/travel/marketing/api/BikeIconServiceApi.java

@@ -0,0 +1,12 @@
+package com.mofang.travel.marketing.api;
+
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.domain.entity.BikeIconVo;
+
+import java.util.List;
+
+public interface BikeIconServiceApi {
+
+    ResponseResult<List<BikeIconVo>> selectBikeIcon();
+
+}

+ 172 - 0
Marketing/marketing-base/pom.xml

@@ -0,0 +1,172 @@
+<?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>com.mofang.travel.marketing</groupId>
+        <artifactId>marketing</artifactId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.mofang.travel.marketing</groupId>
+    <artifactId>marketing-base</artifactId>
+    <version>${version}</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-redis</artifactId>
+            <version>1.4.7.RELEASE</version>
+        </dependency>
+        <!--MySQL 链接工具类-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!--Mybatis 相关工具类-->
+<!--        <dependency>-->
+<!--            <groupId>org.mybatis.spring.boot</groupId>-->
+<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
+<!--            <version>${mybatis-spring.version}</version>-->
+<!--        </dependency>-->
+
+        <!-- mybatis-plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.4.0</version>
+        </dependency>
+
+        <!-- commons -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${apache-commons-lang3.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.20</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+            <version>2.1.6.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${google.guava.version}</version>
+        </dependency>
+
+        <!--阿里数据库连接池-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.1.20</version>
+        </dependency>
+
+        <!-- dubbo start -->
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-spring-boot-starter</artifactId>
+            <version>2.7.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo</artifactId>
+            <version>${dubbo.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-recipes</artifactId>
+            <version>2.13.0</version>
+        </dependency>
+        <!--  dubbo end-->
+
+        <dependency>
+            <groupId>com.mofangchuxing.lib</groupId>
+            <artifactId>common-lib-core</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.mofang.travel.marketing</groupId>
+            <artifactId>marketing-api</artifactId>
+            <version>${version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>marketing-base</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.mybatis.generator</groupId>
+                <artifactId>mybatis-generator-maven-plugin</artifactId>
+                <version>1.3.6</version>
+
+                <configuration>
+                    <verbose>true</verbose>
+                    <overwrite>true</overwrite>
+                </configuration>
+            </plugin>
+            <!--排除deploy-->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>2.8.2</version>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 17 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/Application.java

@@ -0,0 +1,17 @@
+package com.mofang.travel.marketing.base;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableDubbo
+@MapperScan("com.mofang.travel.marketing.base.mapper")
+public class Application {
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class);
+        System.out.println("================ marketing启动完毕 ===============");
+    }
+
+}

+ 23 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/BikeIcon.java

@@ -0,0 +1,23 @@
+package com.mofang.travel.marketing.base.bean.po;
+
+import lombok.Data;
+
+/**
+ * 车辆车标
+ */
+@Data
+public class BikeIcon {
+
+    private Long id;
+
+    /**
+     * 名称
+     */
+    private String iconName;
+
+    /**
+     * 图片地址
+     */
+    private String iconUrl;
+
+}

+ 107 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/RidingCardType.java

@@ -0,0 +1,107 @@
+package com.mofang.travel.marketing.base.bean.po;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 骑行卡类型
+ *
+ * @Date 10:41 2022/9/20
+ * @Author zy
+ **/
+@Data
+public class RidingCardType {
+
+    private Long id;
+
+    /**
+     * 骑行卡产品id
+     */
+    private Long productId;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+    /**
+     * 手机号
+     */
+    private String mobile;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * app渠道
+     */
+    private Integer appFrom;
+    /**
+     * 产品类型
+     */
+    private Integer productType;
+    /**
+     * 购买用户id
+     */
+    private Integer buyerId;
+    /**
+     * 购买用户手机号
+     */
+    private String buyerMobile;
+    /**
+     * 开始时间
+     */
+    private Date startTime;
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+    /**
+     * 初始数量(天,元,次)
+     */
+    private BigDecimal originalNumber;
+    /**
+     * 剩余数量(天,元,次)
+     */
+    private BigDecimal leftNumber;
+    /**
+     *
+     */
+    private Integer ridingFreqLimit;
+    /**
+     *
+     */
+    private Integer ridingTimeLimit;
+    /**
+     *
+     */
+    private Double ridingMileageLimit;
+    /**
+     *
+     */
+    private BigDecimal eachFreeAmount;
+    /**
+     *
+     */
+    private Integer autoRenewFlag;
+    /**
+     * 支付方式1微信,2支付宝
+     */
+    private Integer payMethod;
+    /**
+     * 0 不生效 1 生效
+     */
+    private Integer status;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date modifyTime;
+}

+ 101 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/bean/po/UserRidingCard.java

@@ -0,0 +1,101 @@
+package com.mofang.travel.marketing.base.bean.po;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class UserRidingCard {
+
+    private Long id;
+
+    /**
+     * 骑行卡产品id
+     */
+    private Long productId;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+    /**
+     * 手机号
+     */
+    private String mobile;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * app渠道
+     */
+    private Integer appFrom;
+    /**
+     * 产品类型
+     */
+    private Integer productType;
+    /**
+     * 购买用户id
+     */
+    private Integer buyerId;
+    /**
+     * 购买用户手机号
+     */
+    private String buyerMobile;
+    /**
+     * 开始时间
+     */
+    private Date startTime;
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+    /**
+     * 初始数量(天,元,次)
+     */
+    private BigDecimal originalNumber;
+    /**
+     * 剩余数量(天,元,次)
+     */
+    private BigDecimal leftNumber;
+    /**
+     *
+     */
+    private Integer ridingFreqLimit;
+    /**
+     *
+     */
+    private Integer ridingTimeLimit;
+    /**
+     *
+     */
+    private Double ridingMileageLimit;
+    /**
+     *
+     */
+    private BigDecimal eachFreeAmount;
+    /**
+     *
+     */
+    private Integer autoRenewFlag;
+    /**
+     * 支付方式1微信,2支付宝
+     */
+    private Integer payMethod;
+    /**
+     * 0 不生效 1 生效
+     */
+    private Integer status;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date modifyTime;
+}

+ 59 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/config/LogAspect.java

@@ -0,0 +1,59 @@
+package com.mofang.travel.marketing.base.config;
+
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+/**
+ * 请求日志
+ *
+ * @Author zy
+ **/
+@Slf4j
+@Aspect
+@Component
+public class LogAspect {
+
+    @Pointcut("execution(* *..*Controller.*(..))")
+    public void pointCut() {
+    }
+
+    @Around("pointCut()")
+    public Object around(ProceedingJoinPoint pjp) throws Throwable {
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        long start = System.currentTimeMillis();
+        Object obj = null;
+        try {
+            obj = pjp.proceed();
+        } catch (Throwable throwable) {
+            throw throwable;
+        } finally {
+            long costTime = System.currentTimeMillis() - start;
+
+            Enumeration<String> enu = request.getParameterNames();
+            HashMap<String, String> params = new HashMap<>();
+            while (enu.hasMoreElements()) {
+                String paraName = enu.nextElement();
+                params.put(paraName, request.getParameter(paraName));
+            }
+
+            if (log.isInfoEnabled()) {
+                String responseJson = JSONUtil.toJsonStr(obj);
+                log.info("调用 [ " + request.getRequestURL() + " ] , request= " + JSONUtil.toJsonStr(params) + ", response= " + responseJson + ", 耗时= " + costTime + " ms");
+            }
+
+        }
+        return obj;
+    }
+
+}

+ 28 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/config/RestTemplateConfig.java

@@ -0,0 +1,28 @@
+//package com.kaola.travel.user.config;
+//
+//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.http.client.ClientHttpRequestFactory;
+//import org.springframework.http.client.SimpleClientHttpRequestFactory;
+//import org.springframework.web.client.RestOperations;
+//import org.springframework.web.client.RestTemplate;
+//
+//@Configuration
+//public class RestTemplateConfig {
+//    @Bean
+//    @ConditionalOnMissingBean({RestOperations.class, RestTemplate.class})
+//    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
+//        RestTemplate restTemplate = new RestTemplate(factory);
+//        return restTemplate;
+//    }
+//
+//    @Bean
+//    @ConditionalOnMissingBean({ClientHttpRequestFactory.class})
+//    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
+//        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+//        factory.setReadTimeout(3000);// ms
+//        factory.setConnectTimeout(3000);// ms
+//        return factory;
+//    }
+//}

+ 22 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/controller/admin/BikeIconController.java

@@ -0,0 +1,22 @@
+package com.mofang.travel.marketing.base.controller.admin;
+
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.base.service.BikeIconService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/admin/bikeIcon")
+public class BikeIconController {
+    @Resource
+    private BikeIconService bikeIconService;
+
+    @GetMapping("/check")
+    public ResponseResult selectBikeIcon() {
+        return bikeIconService.selectBikeIcon();
+    }
+
+}

+ 22 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/controller/mini/mBikeIconController.java

@@ -0,0 +1,22 @@
+package com.mofang.travel.marketing.base.controller.mini;
+
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.base.service.BikeIconService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/bikeIcon")
+public class mBikeIconController {
+    @Resource
+    private BikeIconService bikeIconService;
+
+    @GetMapping("/check")
+    public ResponseResult selectBikeIcon() {
+        return bikeIconService.selectBikeIcon();
+    }
+
+}

+ 35 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/enums/StatusEnum.java

@@ -0,0 +1,35 @@
+package com.mofang.travel.marketing.base.enums;
+
+/**
+ * 返回数据枚举 demo
+ */
+public enum StatusEnum {
+
+    OK(200, "操作成功"),
+    FALSE(-1, "未知异常错误");
+
+    private int code;
+    private String message;
+
+    StatusEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public static StatusEnum getEnum(Integer code) {
+        for (StatusEnum scene : StatusEnum.values()) {
+            if (scene.getCode() == code.intValue()) {
+                return scene;
+            }
+        }
+        return null;
+    }
+}

+ 49 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/handler/GlobalExceptionHandler.java

@@ -0,0 +1,49 @@
+package com.mofang.travel.marketing.base.handler;
+
+import com.alibaba.druid.support.json.JSONUtils;
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.commons.enums.ResultEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+
+@ControllerAdvice
+@RestController
+public class GlobalExceptionHandler {
+    public static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    @ResponseStatus(HttpStatus.OK)
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResponseResult handleValidException(HttpServletRequest request, Exception e) {
+        LOGGER.error("Request Url:{}, message:{}, params:{}", request.getRequestURI(), e.getMessage(), getParams(request));
+        return ResponseResult.error(ResultEnum.UNKNOWN_ERROR);
+    }
+
+    //    @ResponseStatus(HttpStatus.OK)
+    @ExceptionHandler(Exception.class)
+    public ResponseResult handleBaseException(HttpServletRequest request, Exception e) {
+        LOGGER.error("Request Url:{}, params:{}, Exception:{}", request.getRequestURI(), getParams(request), e);
+        return ResponseResult.error(ResultEnum.UNKNOWN_ERROR);
+    }
+
+    private String getParams(HttpServletRequest request) {
+        Map<String, String> map = new HashMap<>();
+        Enumeration enu = request.getParameterNames();
+        while (enu.hasMoreElements()) {
+            String paraName = (String) enu.nextElement();
+            map.put(paraName, request.getParameter(paraName));
+        }
+        return JSONUtils.toJSONString(map);
+    }
+}

+ 14 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/mapper/BikeIconMapper.java

@@ -0,0 +1,14 @@
+package com.mofang.travel.marketing.base.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.mofang.travel.marketing.base.bean.po.BikeIcon;
+import com.mofang.travel.marketing.domain.entity.BikeIconVo;
+
+import java.util.List;
+
+public interface BikeIconMapper extends BaseMapper<BikeIcon> {
+
+    List<BikeIconVo> selectByBikeIcon();
+
+}

+ 19 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/mapper/UserRidingCardMapper.java

@@ -0,0 +1,19 @@
+package com.mofang.travel.marketing.base.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.mofang.travel.marketing.base.bean.po.UserRidingCard;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface UserRidingCardMapper extends BaseMapper<UserRidingCard> {
+
+    /**
+     * 根据用户id和开始查询时间查询骑行卡列表
+     *
+     * @param userId
+     * @param startTime
+     * @return
+     */
+    List<UserRidingCard> selectByUserIdAndStartTime(@Param("userId") Long userId, @Param("startTime") String startTime);
+}

+ 269 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/redis/RedisClient.java

@@ -0,0 +1,269 @@
+package com.mofang.travel.marketing.base.redis;
+
+import cn.hutool.json.JSONUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.core.ZSetOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisClient {
+
+    private final static Logger logger = LoggerFactory.getLogger(RedisClient.class);
+
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    public void set(String key, String value) {
+        try {
+            stringRedisTemplate.opsForValue().set(key, value);
+        } catch (Exception e) {
+            logger.error("redis新增操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+    }
+
+    public void set(String key, int seconds, String value) {
+        try {
+            stringRedisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            logger.error("redis新增操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+    }
+
+    public void set(String key, int seconds, Object value) {
+        try {
+            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), seconds, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            logger.error("redis新增操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+    }
+
+    public void set(String key, long seconds, Object value) {
+        try {
+            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), seconds, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            logger.error("redis新增操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+    }
+
+    public void set(String key, String value, long time, TimeUnit timeUnit) {
+        if (time <= 0) {
+            return;
+        }
+        try {
+            stringRedisTemplate.opsForValue().set(key, value, time, timeUnit);
+        } catch (Exception e) {
+            logger.error("redis新增操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+
+    }
+
+    public List<String> multiGet(Collection<String> keys) {
+        return stringRedisTemplate.opsForValue().multiGet(keys);
+    }
+
+    public <T> T getBean(String key, Class<T> clazz) {
+        try {
+            String value = stringRedisTemplate.opsForValue().get(key);
+            if (StringUtils.isNotBlank(value)) {
+                return JSONUtil.toBean(value, clazz);
+            }
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    public String get(String key) {
+        try {
+            return stringRedisTemplate.opsForValue().get(key);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    public List<String> get(Collection<String> keys) {
+        try {
+            return stringRedisTemplate.opsForValue().multiGet(keys);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key={}", JSONUtil.toJsonStr(keys), e);
+        }
+        return null;
+    }
+
+    public Boolean del(String key) {
+        try {
+            return stringRedisTemplate.delete(key);
+        } catch (Exception e) {
+            logger.error("redis删除操作失败,key=" + new String(key) + ", " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 批量清除key
+     *
+     * @param keys
+     */
+    public void delete(Collection<String> keys) {
+        stringRedisTemplate.delete(keys);
+    }
+
+    public Object hget(String key, String field) {
+        try {
+            return redisTemplate.opsForHash().get(key, field);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    public void hmset(String key, Map<Object, Object> map) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+    }
+
+    public Long setSize(String key) {
+        return redisTemplate.opsForSet().size(key);
+    }
+
+    public Boolean setIsMember(String key, Object o) {
+        return redisTemplate.opsForSet().isMember(key, o);
+    }
+
+    public Set<String> setMembers(String key) {
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    public void setAdd(String key, String v) {
+        try {
+            redisTemplate.opsForSet().add(key, v);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+    }
+
+    public void setRemove(String key, String v) {
+        try {
+            redisTemplate.opsForSet().remove(key, v);
+        } catch (Exception e) {
+            logger.error("redis查询操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+    }
+
+    public Boolean getBit(String key, Long offset, boolean defaultValue) {
+        try {
+            return redisTemplate.opsForValue().getBit(key, offset);
+        } catch (Exception e) {
+            logger.error("redis getBit操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+        return defaultValue;
+    }
+
+    public void setBit(String key, Long offset, boolean value) {
+        try {
+            redisTemplate.opsForValue().setBit(key, offset, value);
+        } catch (Exception e) {
+            logger.error("redis getBit操作失败,key=" + key + ", " + e.getMessage(), e);
+        }
+    }
+
+    public boolean zadd(String key, Object value, Object score) {
+        try {
+            return redisTemplate.opsForZSet().add(key, String.valueOf(value), Double.parseDouble(String.valueOf(score)));
+        } catch (Exception e) {
+            logger.error("redis zadd 失败,key={},value={},score={} ", key, value, score, e);
+        }
+        return false;
+    }
+
+    public Double score(String key, Object value) {
+        return redisTemplate.opsForZSet().score(key, value);
+    }
+
+    public double zsetRemove(String key, Object value) {
+        return redisTemplate.opsForZSet().remove(key, value);
+    }
+
+    public Set<ZSetOperations.TypedTuple<String>> reverseRangeWithScores(String key, long offset, long count) {
+        return redisTemplate.opsForZSet().reverseRangeWithScores(key, offset, count);
+    }
+
+    public Set<ZSetOperations.TypedTuple<String>> zRangeWithScores(String key, Long startIndex, Long endIndex) {
+        try {
+            return redisTemplate.opsForZSet().rangeWithScores(key, startIndex, endIndex);
+        } catch (Exception e) {
+            logger.error(String.format("RedisClient#zRangeWithScores(key,startIndex,endIndex) field,key={%s},startIndex={%d},endIndex={%d}", key, startIndex, endIndex), e);
+        }
+        return Collections.emptySet();
+    }
+
+    public Set<ZSetOperations.TypedTuple<String>> zReverseRangeWithScores(String key, Long startIndex, Long endIndex) {
+        try {
+            return redisTemplate.opsForZSet().reverseRangeWithScores(key, startIndex, endIndex);
+        } catch (Exception e) {
+            logger.error(String.format("RedisClient#zRangeWithScores(key,startIndex,endIndex) field,key={%s},startIndex={%d},endIndex={%d}", key, startIndex, endIndex), e);
+        }
+        return Collections.emptySet();
+    }
+
+    public void zRemRangeByScore(String key, Long start, Long end) {
+        try {
+            redisTemplate.opsForZSet().removeRangeByScore(key, start, end);
+        } catch (Exception e) {
+            logger.error("redis zRemRangeByScore 失败,key={},start={},end={} ", key, start, end, e);
+        }
+    }
+
+    public void expire(String key, long timeout) {
+        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    public void zRem(String key, Object... value) {
+        try {
+            redisTemplate.opsForZSet().remove(key, value);
+        } catch (Exception e) {
+            logger.error("redis zRemRangeByScore 失败,key={}", key, e);
+        }
+    }
+
+    public String incrementValue(String key) {
+        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
+        try {
+            valueOperations.increment(key, 1);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return valueOperations.get(key);
+    }
+
+
+    public void putValueExpireTimes(String key, String value, Long timeout) {
+        redisTemplate.opsForValue().set(key, value);
+        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    public boolean setIfAbsent(String key, String value, long time, TimeUnit timeUnit) {
+        return redisTemplate.opsForValue().setIfAbsent(key, value);
+    }
+}

+ 13 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/BikeIconService.java

@@ -0,0 +1,13 @@
+package com.mofang.travel.marketing.base.service;
+
+
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.domain.entity.BikeIconVo;
+
+import java.util.List;
+
+public interface BikeIconService {
+
+    ResponseResult<List<BikeIconVo>> selectBikeIcon();
+
+}

+ 4 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/UserRidingCardService.java

@@ -0,0 +1,4 @@
+package com.mofang.travel.marketing.base.service;
+
+public interface UserRidingCardService {
+}

+ 33 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/impl/BikeIconServiceImpl.java

@@ -0,0 +1,33 @@
+package com.mofang.travel.marketing.base.service.impl;
+
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.api.BikeIconServiceApi;
+import com.mofang.travel.marketing.base.mapper.BikeIconMapper;
+import com.mofang.travel.marketing.base.service.BikeIconService;
+import com.mofang.travel.marketing.domain.entity.BikeIconVo;
+import org.apache.dubbo.config.annotation.Service;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * dubbo
+ *
+ * @Date 18:30 2022/9/19
+ * @Author zy
+ **/
+// 这里需要注意 implements 的接口 只会注册第一个实现到dubbo
+@Component
+@Service
+public class BikeIconServiceImpl implements BikeIconServiceApi, BikeIconService {
+
+    @Resource
+    private BikeIconMapper bikeIconMapper;
+
+    @Override
+    public ResponseResult<List<BikeIconVo>> selectBikeIcon() {
+        return ResponseResult.ok(bikeIconMapper.selectByBikeIcon());
+    }
+
+}

+ 34 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/service/impl/UserRidingCardServiceImpl.java

@@ -0,0 +1,34 @@
+package com.mofang.travel.marketing.base.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.mofang.travel.commons.bean.ResponseResult;
+import com.mofang.travel.marketing.base.bean.po.UserRidingCard;
+import com.mofang.travel.marketing.base.mapper.UserRidingCardMapper;
+import com.mofang.travel.marketing.base.redis.RedisClient;
+import com.mofang.travel.marketing.base.service.UserRidingCardService;
+import org.apache.dubbo.config.annotation.Service;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+@Service
+public class UserRidingCardServiceImpl implements UserRidingCardService {
+
+    @Resource
+    private RedisClient redisClient;
+
+    @Resource
+    private UserRidingCardMapper userRidingCardMapper;
+
+    /**
+     * 列表查询
+     *
+     * @return
+     */
+    public ResponseResult selectAll(String mobile, Long companyId) {
+        QueryWrapper<UserRidingCard> queryWrapper = new QueryWrapper<>();
+        return ResponseResult.ok(userRidingCardMapper.selectList(queryWrapper));
+    }
+
+}

+ 159 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/CommonUtil.java

@@ -0,0 +1,159 @@
+package com.mofang.travel.marketing.base.utils;
+
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.regex.Pattern;
+
+public class CommonUtil {
+
+    public static String getIpAddress(HttpServletRequest request) {
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_CLIENT_IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        return ip;
+    }
+
+    public static boolean isInteger(String str) {
+        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
+        return pattern.matcher(str).matches();
+    }
+
+    public static String replaceDeposit(Integer appFrom, Long operateAreaId, String origin, String target) {
+        if (appFrom == null || operateAreaId == null || target == null) {
+            return origin;
+        }
+        if (1546L == operateAreaId && (appFrom.intValue() == 14 || appFrom.intValue() == 15)) {
+            return origin.replace("押金", target);
+        }
+        return origin;
+    }
+
+    /**
+     * 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0
+     *
+     * @param version1
+     * @param version2
+     * @return
+     */
+    public static int compareVersion(String version1, String version2) {
+        if (version1 == null || version2 == null) {
+            return 0;
+        }
+        // 注意此处为正则匹配,不能用".";
+        String[] versionArray1 = version1.split("\\.");
+        String[] versionArray2 = version2.split("\\.");
+        int idx = 0;
+        // 取最小长度值
+        int minLength = Math.min(versionArray1.length, versionArray2.length);
+        int diff = 0;
+        while (idx < minLength
+                && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0
+                && (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {
+            ++idx;
+        }
+        //如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
+        diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
+        return diff;
+    }
+
+    public static SimpleClientHttpRequestFactory getRequestTimeOut() {
+        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
+        requestFactory.setConnectTimeout(3000);// 设置超时
+        requestFactory.setReadTimeout(5000);
+        return requestFactory;
+    }
+
+    /**
+     * 获取当前进程的调用者,
+     * 及方法名称,行数。
+     *
+     * @return
+     */
+    public static String getCaller() {
+        StackTraceElement stack[] = (new Throwable()).getStackTrace();
+        StringBuffer result = new StringBuffer();
+        for (int i = 1; i < stack.length; i++) {
+            StackTraceElement s = stack[i];
+            result.append("\n");
+            result.append("\tat ");
+            result.append(s.getClassName());
+            result.append(".");
+            result.append(s.getMethodName());
+            result.append("(");
+            result.append(s.getFileName());
+            result.append(":");
+            result.append(s.getLineNumber());
+            result.append(")");
+        }
+        return result.toString();
+    }
+
+    public static int str2Ip(String ip) throws UnknownHostException {
+        InetAddress address = InetAddress.getByName(ip);
+        byte[] bytes = address.getAddress();
+        int a, b, c, d;
+        a = byte2int(bytes[0]);
+        b = byte2int(bytes[1]);
+        c = byte2int(bytes[2]);
+        d = byte2int(bytes[3]);
+        int result = (a << 24) | (b << 16) | (c << 8) | d;
+        return result;
+    }
+
+    public static int byte2int(byte b) {
+        int l = b & 0x07f;
+        if (b < 0) {
+            l |= 0x80;
+        }
+        return l;
+    }
+
+
+    public static long ip2long(String ip) throws UnknownHostException {
+        int ipNum = str2Ip(ip);
+        return int2long(ipNum);
+    }
+
+    public static long int2long(int i) {
+        long l = i & 0x7fffffffL;
+        if (i < 0) {
+            l |= 0x080000000L;
+        }
+        return l;
+    }
+
+    public static String long2ip(long ip) {
+        int[] b = new int[4];
+        b[0] = (int) ((ip >> 24) & 0xff);
+        b[1] = (int) ((ip >> 16) & 0xff);
+        b[2] = (int) ((ip >> 8) & 0xff);
+        b[3] = (int) (ip & 0xff);
+        String x;
+        Integer p;
+        p = new Integer(0);
+        x = Integer.toString(b[0]) + "." + Integer.toString(b[1]) + "." + Integer.toString(b[2]) + "." + Integer.toString(b[3]);
+
+        return x;
+    }
+
+    public static void main(String[] args) {
+
+    }
+
+}

+ 56 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/GenerateCodeUtil.java

@@ -0,0 +1,56 @@
+package com.mofang.travel.marketing.base.utils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class GenerateCodeUtil {
+    private static AtomicInteger count = new AtomicInteger(0);
+    private static String ip;
+
+    /**
+     * 获取当前时间戳
+     *
+     * @return
+     */
+    public static Integer getTimeStamp() {
+        return (int) (System.currentTimeMillis() / 1000);
+    }
+
+    /**
+     * 根据用户id生成订单编号
+     * 时间戳 + 自增序列  + ip最后两位 + 用户id最后一位
+     *
+     * @return
+     */
+    public static String getOrderNo(Long userId) {
+        int ipLast = 0;
+        if (ip == null) {
+            InetAddress addr = null;
+            try {
+                addr = InetAddress.getLocalHost();
+                ip = addr.getHostAddress().split("\\.")[3];
+                ipLast = Integer.valueOf(ip);
+            } catch (UnknownHostException e) {
+                ipLast = 0;
+            }
+        }
+        long start = System.currentTimeMillis() % 100000000000L;
+        int andIncrement = count.getAndIncrement();
+        if (count.get() >= 1000) {
+            count = new AtomicInteger(0);
+
+        }
+        String orderNo = start + String.format("%03d", andIncrement) + String.format("%03d", ipLast);
+        Long lastUserId = userId % 10;
+        orderNo = orderNo + lastUserId.toString();
+        return orderNo;
+    }
+
+    public static String getFiveNumber() {
+        Random random = new Random();
+        int end = random.nextInt(100000);
+        return String.format("%05d", end);
+    }
+}

+ 34 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/JsonUtils.java

@@ -0,0 +1,34 @@
+package com.mofang.travel.marketing.base.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Map;
+
+public class JsonUtils {
+
+    /**
+     * 校验json
+     *
+     * @param jsonStr
+     * @return
+     */
+    public static boolean isJson(String jsonStr) {
+        try {
+            JSONObject.parseObject(jsonStr);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * jsonStr to Map
+     *
+     * @param jsonStr
+     * @return
+     */
+    public static Map<String, String> jsonToMap(String jsonStr) {
+        Map map = JSONObject.parseObject(jsonStr, Map.class);
+        return map;
+    }
+}

+ 73 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/ListUtil.java

@@ -0,0 +1,73 @@
+package com.mofang.travel.marketing.base.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 处理List工具类
+ *
+ * @author 刘美丽
+ * @date 2022-03-25 10:14
+ */
+public class ListUtil {
+    /**
+     * 将传入的list中的指定字段根据 splitChar 分割成列表 (多字段)
+     *
+     * @param map       key-指定分割后的列表名称 value-字段 lambda写法 Class::getColumn
+     * @param list      传入列表
+     * @param splitChar 指定分割字符,将根据此字符进行分割
+     * @return {@link Map<String,List<String>>} key-列表名称 value-分割后的列表
+     * @author 刘美丽
+     * @date 2022/03/25 10:27
+     */
+    public static <T> Map<String, List<String>> splitListByColumn(Map<String, Function<? super T, ? extends String>> map, List<T> list, String splitChar) {
+        Map<String, List<String>> result = new HashMap<>();
+        map.forEach((k, v) -> {
+            result.put(k, list.stream().map(v).flatMap(str -> Arrays.stream(str.split(splitChar))).collect(Collectors.toList()));
+        });
+        return result;
+    }
+
+    /**
+     * 将传入的list中的指定字段根据 splitChar 分割成列表 (单字段)
+     *
+     * @param function  字段
+     * @param list      列表
+     * @param splitChar 分割字符
+     * @return {@link List<String>}
+     * @author 刘美丽
+     * @date 2022/03/25 10:36
+     */
+    public static <T> List<String> splitListByColumn(Function<? super T, ? extends String> function, List<T> list, String splitChar) {
+        return list.stream()
+                .map(function)
+                .filter(StringUtils::isNotBlank)
+                .flatMap(str -> Arrays.stream(str.split(splitChar)))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 统计列表中同一对象出现次数
+     *
+     * @param list 列表
+     * @return {@link Map<T,Integer>} key-对象 value-出现次数
+     * @author 刘美丽
+     * @date 2022/03/25 10:37
+     */
+    public static <T> Map<T, Integer> getListCount(List<T> list) {
+        Map<T, Integer> result = new HashMap<>();
+        for (T t : list) {
+            if (!result.containsKey(t)) {
+                result.put(t, 0);
+            }
+            result.put(t, result.get(t) + 1);
+        }
+        return result;
+    }
+}

+ 46 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/MD5Util.java

@@ -0,0 +1,46 @@
+package com.mofang.travel.marketing.base.utils;
+
+import java.security.MessageDigest;
+
+public class MD5Util {
+
+    private static String byteArrayToHexString(byte b[]) {
+        StringBuffer resultSb = new StringBuffer();
+        for (int i = 0; i < b.length; i++) {
+            resultSb.append(byteToHexString(b[i]));
+        }
+
+        return resultSb.toString();
+    }
+
+    private static String byteToHexString(byte b) {
+        int n = b;
+        if (n < 0) {
+            n += 256;
+        }
+        int d1 = n / 16;
+        int d2 = n % 16;
+        return hexDigits[d1] + hexDigits[d2];
+    }
+
+    public static String MD5Encode(String origin, String charsetname) {
+        String resultString = null;
+        try {
+            resultString = new String(origin);
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            if (charsetname == null || "".equals(charsetname)) {
+                resultString = byteArrayToHexString(md.digest(resultString
+                        .getBytes()));
+            } else {
+                resultString = byteArrayToHexString(md.digest(resultString
+                        .getBytes(charsetname)));
+            }
+        } catch (Exception exception) {
+        }
+        return resultString;
+    }
+
+    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
+            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
+
+}

+ 134 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/RandomUtils.java

@@ -0,0 +1,134 @@
+package com.mofang.travel.marketing.base.utils;
+
+import java.util.Random;
+
+/**
+ * 随机字符串生成工具类
+ */
+public class RandomUtils {
+
+    /**
+     * 定义所有的字符组成的串
+     */
+    public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    /**
+     * 定义所有的小写字符组成的串(不包括数字)
+     */
+    public static final String letterChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    /**
+     * 定义所有的数字字符组成的串
+     */
+    public static final String numberChar = "0123456789";
+
+    /**
+     * 产生长度为length的随机字符串(包括字母和数字)
+     *
+     * @param length
+     * @return
+     */
+    public static String generateString(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < length; i++) {
+            sb.append(allChar.charAt(random.nextInt(allChar.length())));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 产生长度为length的随机字符串(包括字母,不包括数字)
+     *
+     * @param length
+     * @return
+     */
+    public static String generateMixString(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < length; i++) {
+            sb.append(letterChar.charAt(random.nextInt(letterChar.length())));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 产生长度为length的随机小写字符串(包括字母,不包括数字)
+     *
+     * @param length
+     * @return
+     */
+    public static String generateLowerString(int length) {
+        return generateMixString(length).toLowerCase();
+    }
+
+    /**
+     * 产生长度为length的随机大写字符串(包括字母,不包括数字)
+     *
+     * @param length
+     * @return
+     */
+    public static String generateUpperString(int length) {
+        return generateMixString(length).toUpperCase();
+    }
+
+    /**
+     * 产生长度为length的'0'串
+     *
+     * @param length
+     * @return
+     */
+    public static String generateZeroString(int length) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            sb.append('0');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 将输入的long整数值补全成为fixedlength长度的字符串
+     *
+     * @param num
+     * @return
+     */
+    public static String toFixdLengthString(long num, int fixdlenth) {
+        StringBuffer sb = new StringBuffer();
+        String strNum = String.valueOf(num);
+        if (fixdlenth - strNum.length() >= 0) {
+            sb.append(generateZeroString(fixdlenth - strNum.length()));
+        } else {
+            throw new RuntimeException("将数字" + num + "转化为长度为" + fixdlenth + "的字符串发生异常!");
+        }
+        sb.append(strNum);
+        return sb.toString();
+    }
+
+    /**
+     * 将输入的int整数值补全成为fixedlength长度的字符串
+     *
+     * @param num
+     * @return
+     */
+    public static String toFixdLengthString(int num, int fixdlenth) {
+        StringBuffer sb = new StringBuffer();
+        String strNum = String.valueOf(num);
+        if (fixdlenth - strNum.length() >= 0) {
+            sb.append(generateZeroString(fixdlenth - strNum.length()));
+        } else {
+            throw new RuntimeException("将数字" + num + "转化为长度为" + fixdlenth + "的字符串发生异常!");
+        }
+        sb.append(strNum);
+        return sb.toString();
+    }
+
+    public static String getRandom(int length) {
+        String val = "";
+        Random random = new Random();
+        for (int i = 0; i < length; i++) {
+            val += String.valueOf(random.nextInt(10));
+        }
+        return val;
+    }
+
+    public static void main(String[] args) {
+    }
+}

+ 669 - 0
Marketing/marketing-base/src/main/java/com/mofang/travel/marketing/base/utils/RegexUtils.java

@@ -0,0 +1,669 @@
+package com.mofang.travel.marketing.base.utils;
+
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 正则工具类 提供验证邮箱、手机号、电话号码、身份证号码、数字等方法
+ */
+public final class RegexUtils {
+
+    /**
+     * 整数
+     */
+    private static final String V_INTEGER = "^-?[1-9]\\d*$";
+
+    /**
+     * 正整数
+     */
+    private static final String V_Z_INDEX = "^[1-9]\\d*$";
+
+    /**
+     * 负整数
+     */
+    private static final String V_NEGATIVE_INTEGER = "^-[1-9]\\d*$";
+
+    /**
+     * 数字
+     */
+    private static final String V_NUMBER = "^([+-]?)\\d*\\.?\\d+$";
+
+    /**
+     * 正数
+     */
+    private static final String V_POSITIVE_NUMBER = "^[1-9]\\d*|0$";
+
+    /**
+     * 负数
+     */
+    private static final String V_NEGATINE_NUMBER = "^-[1-9]\\d*|0$";
+
+    /**
+     * 浮点数
+     */
+    private static final String V_FLOAT = "^([+-]?)\\d*\\.\\d+$";
+
+    /**
+     * 正浮点数
+     */
+    private static final String V_POSTTIVE_FLOAT = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$";
+
+    /**
+     * 负浮点数
+     */
+    private static final String V_NEGATIVE_FLOAT = "^-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*)$";
+
+    /**
+     * 非负浮点数(正浮点数 + 0)
+     */
+    private static final String V_UNPOSITIVE_FLOAT = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0$";
+
+    /**
+     * 非正浮点数(负浮点数 + 0)
+     */
+    private static final String V_UN_NEGATIVE_FLOAT = "^(-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*))|0?.0+|0$";
+
+    /**
+     * 邮件
+     */
+    private static final String V_EMAIL = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
+
+    /**
+     * 颜色
+     */
+    private static final String V_COLOR = "^[a-fA-F0-9]{6}$";
+
+    /**
+     * url
+     */
+    private static final String V_URL = "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$";
+
+    /**
+     * 仅中文
+     */
+    private static final String V_CHINESE = "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$";
+
+    /**
+     * 仅ACSII字符
+     */
+    private static final String V_ASCII = "^[\\x00-\\xFF]+$";
+
+    /**
+     * 邮编
+     */
+    private static final String V_ZIPCODE = "^\\d{6}$";
+
+    /**
+     * 手机
+     */
+    private static final String V_MOBILE = "^(13|15)[0-9]{9}$";
+
+    /**
+     * ip地址
+     */
+    private static final String V_IP4 = "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$";
+
+    /**
+     * 非空
+     */
+    private static final String V_NOTEMPTY = "^\\S+$";
+
+    /**
+     * 图片
+     */
+    private static final String V_PICTURE = "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$";
+
+    /**
+     * 压缩文件
+     */
+    private static final String V_RAR = "(.*)\\.(rar|zip|7zip|tgz)$";
+
+    /**
+     * 日期
+     */
+    private static final String V_DATE = "^((((1[6-9]|[2-9]\\d)\\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-0?2-(0?[1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\\d):[0-5]?\\d:[0-5]?\\d$";
+
+    /**
+     * QQ号码
+     */
+    private static final String V_QQ_NUMBER = "^[1-9]*[1-9][0-9]*$";
+
+    /**
+     * 电话号码的函数(包括验证国内区号,国际区号,分机号)
+     */
+    private static final String V_TEL = "^(([0\\+]\\d{2,3}-)?(0\\d{2,3})-)?(\\d{7,8})(-(\\d{3,}))?$";
+
+    /**
+     * 用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
+     */
+    private static final String V_USERNAME = "^\\w+$";
+
+
+    /**
+     * 包含非单词字符:[^\W]
+     */
+    private static final String V_INC_NOT_WORD = "^.*([\\W_])+.*$";
+
+    /**
+     * 包含字母:"^.*([a-zA-Z])+.*$";
+     */
+    private static final String V_INC_WORD = "^.*([a-zA-Z])+.*$";
+
+    /**
+     * 包含数字: "^.*([0-9])+.*$";
+     */
+    private static final String V_INC_NUM = "^.*([0-9])+.*$";
+
+
+    /**
+     * 字母
+     */
+    private static final String V_LETTER = "^[A-Za-z]+$";
+
+    /**
+     * 大写字母
+     */
+    private static final String V_LETTER_U = "^[A-Z]+$";
+
+    /**
+     * 小写字母
+     */
+    private static final String V_LETTER_I = "^[a-z]+$";
+
+    /**
+     * 身份证
+     */
+    private static final String V_IDCARD = "^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$";
+
+    /**
+     * 验证密码(数字和英文同时存在)
+     */
+    private static final String V_PASSWORD_REG = "[A-Za-z]+[0-9]";
+
+    /**
+     * 验证密码长度(8-20位)
+     */
+    private static final String V_PASSWORD_LENGTH = "^\\d{8,20}$";
+
+
+    /**
+     * 验证两位数
+     */
+    private static final String V_TWO_POINT = "^[0-9]+(.[0-9]{2})?$";
+
+    /**
+     * 验证一个月的31天
+     */
+    private static final String V_31DAYS = "^((0?[1-9])|((1|2)[0-9])|30|31)$";
+
+    /**
+     * 验证是不是整数
+     *
+     * @param value 要验证的字符串 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Integer(String value) {
+        return match(V_INTEGER, value);
+    }
+
+    /**
+     * 验证是不是正整数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Z_index(String value) {
+        return match(V_Z_INDEX, value);
+    }
+
+    /**
+     * 验证是不是负整数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Negative_integer(String value) {
+        return match(V_NEGATIVE_INTEGER, value);
+    }
+
+    /**
+     * 验证是不是数字
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Number(String value) {
+        return match(V_NUMBER, value);
+    }
+
+    /**
+     * 验证是不是正数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean PositiveNumber(String value) {
+        return match(V_POSITIVE_NUMBER, value);
+    }
+
+    /**
+     * 验证是不是负数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean NegatineNumber(String value) {
+        return match(V_NEGATINE_NUMBER, value);
+    }
+
+    /**
+     * 验证一个月的31天
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Is31Days(String value) {
+        return match(V_31DAYS, value);
+    }
+
+    /**
+     * 验证是不是ASCII
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean ASCII(String value) {
+        return match(V_ASCII, value);
+    }
+
+    /**
+     * 验证是不是中文
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Chinese(String value) {
+        return match(V_CHINESE, value);
+    }
+
+    /**
+     * 验证是不是颜色
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Color(String value) {
+        return match(V_COLOR, value);
+    }
+
+    /**
+     * 验证是不是日期
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Date(String value) {
+        return match(V_DATE, value);
+    }
+
+    /**
+     * 验证是不是邮箱地址
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Email(String value) {
+        return match(V_EMAIL, value);
+    }
+
+    /**
+     * 验证是不是浮点数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Float(String value) {
+        return match(V_FLOAT, value);
+    }
+
+    /**
+     * 验证是不是正确的身份证号码
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean IDcard(String value) {
+        return match(V_IDCARD, value);
+    }
+
+    /**
+     * 验证是不是正确的IP地址
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean IP4(String value) {
+        return match(V_IP4, value);
+    }
+
+    /**
+     * 验证是不是字母
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Letter(String value) {
+        return match(V_LETTER, value);
+    }
+
+    /**
+     * 验证是不是小写字母
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Letter_i(String value) {
+        return match(V_LETTER_I, value);
+    }
+
+    /**
+     * 验证是不是大写字母
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Letter_u(String value) {
+        return match(V_LETTER_U, value);
+    }
+
+    /**
+     * 验证是不是手机号码
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Mobile(String value) {
+        return match(V_MOBILE, value);
+    }
+
+    /**
+     * 最新手机号验证
+     *
+     * @param phone
+     * @return
+     */
+    public static boolean isPhone(String phone) {
+        String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
+        if (phone.length() != 11) {
+            return false;
+        } else {
+            Pattern p = Pattern.compile(regex);
+            Matcher m = p.matcher(phone);
+            boolean isMatch = m.matches();
+            if (!isMatch) {
+            }
+            return isMatch;
+        }
+    }
+
+    /**
+     * 验证是不是负浮点数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Negative_float(String value) {
+        return match(V_NEGATIVE_FLOAT, value);
+    }
+
+    /**
+     * 验证非空
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Notempty(String value) {
+        return match(V_NOTEMPTY, value);
+    }
+
+    /**
+     * 验证密码的长度(8~20位)
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Number_length(String value) {
+        return match(V_PASSWORD_LENGTH, value);
+    }
+
+    /**
+     * 验证密码(数字和英文同时存在)
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Password_reg(String value) {
+        return match(V_PASSWORD_REG, value);
+    }
+
+    /**
+     * 验证图片
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Picture(String value) {
+        return match(V_PICTURE, value);
+    }
+
+    /**
+     * 验证正浮点数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Posttive_float(String value) {
+        return match(V_POSTTIVE_FLOAT, value);
+    }
+
+    /**
+     * 验证QQ号码
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean QQnumber(String value) {
+        return match(V_QQ_NUMBER, value);
+    }
+
+    /**
+     * 验证压缩文件
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Rar(String value) {
+        return match(V_RAR, value);
+    }
+
+    /**
+     * 验证电话
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Tel(String value) {
+        return match(V_TEL, value);
+    }
+
+    /**
+     * 验证两位小数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Two_point(String value) {
+        return match(V_TWO_POINT, value);
+    }
+
+    /**
+     * 验证非正浮点数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Un_negative_float(String value) {
+        return match(V_UN_NEGATIVE_FLOAT, value);
+    }
+
+    /**
+     * 验证非负浮点数
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Unpositive_float(String value) {
+        return match(V_UNPOSITIVE_FLOAT, value);
+    }
+
+    /**
+     * 验证URL
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Url(String value) {
+        return match(V_URL, value);
+    }
+
+    /**
+     * 验证用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean UserName(String value) {
+        return match(V_USERNAME, value);
+    }
+
+    /**
+     * 验证邮编
+     *
+     * @param value 要验证的字符串
+     * @return 如果是符合格式的字符串, 返回 <b>true </b>,否则为 <b>false </b>
+     */
+    public static boolean Zipcode(String value) {
+        return match(V_ZIPCODE, value);
+    }
+
+    /**
+     * @param regex 正则表达式字符串
+     * @param str   要匹配的字符串
+     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
+     */
+    private static boolean match(String regex, String str) {
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(str);
+        return matcher.matches();
+    }
+
+
+    /**
+     * 密码强度
+     *
+     * @param passwordStr
+     * @return
+     * @author lijinghui
+     */
+    public static String checkPassword(String passwordStr) {
+        // 8-10位纯数字  密码弱
+        String num8_10 = "^[0-9]{8,10}$";
+        // 由字母组成  8-10 弱
+        String str8_10 = "^[a-zA-Z]{8,10}$";
+        // 11-20位纯数字  密码中
+        String num11_20 = "^[0-9]{11,20}$";
+        // 由纯字母组成  11-20 中
+        String str11_20 = "^[a-zA-Z]{11,20}$";
+        // 由字母、数字组成,8-10位 中
+        String strNum8_10 = "^[0-9|a-z|A-Z]{8,10}$";
+        // 由字母、数字组成,11-20位 强
+        String strNum11_20 = "^[0-9|a-z|A-Z]{11,20}$";
+        if (passwordStr.length() < 8) {
+            return "passWord_to_short";
+        }
+        if (passwordStr.length() > 20) {
+            return "passWord_to_long";
+        }
+        // 纯数字  8-10 弱11-20 中
+        if (match(num8_10, passwordStr) || match(str8_10, passwordStr)) {
+            return "passWord_weak";
+        }
+        // 数字+字母 8-10中 11-20强
+        if (match(num11_20, passwordStr) || match(strNum8_10, passwordStr) || match(str11_20, passwordStr)) {
+            return "passWord_middleStrong";
+        }
+        if (match(strNum11_20, passwordStr)) {
+            return "passWord_strong";
+        }
+        return "";
+    }
+
+    /**
+     * 密码强度
+     *
+     * @param passwordStr
+     * @return
+     */
+    public static String passWordLevel(String passwordStr) {
+
+        passwordStr = StringUtils.trimToNull(passwordStr);
+        if (passwordStr == null) {
+            return null;
+        }
+        int strength = 0;
+
+        if (passwordStr.length() < 8) {
+            // 密码太短
+            return "passWord_to_short";
+        }
+
+        if (passwordStr.length() > 20) {
+            // 密码太长
+            return "passWord_to_long";
+        }
+
+        if (passwordStr.length() > 10) {
+            strength++;
+        }
+        if (match(V_INC_NOT_WORD, passwordStr)) {
+            strength++;
+        }
+        if (match(V_INC_WORD, passwordStr)) {
+            strength++;
+        }
+
+        if (match(V_INC_NUM, passwordStr)) {
+            strength++;
+        }
+
+        if (strength <= 1) {
+            return "passWord_weak";
+        }
+        if (strength == 2) {
+            // 密码强度中
+            return "passWord_middleStrong";
+        }
+        if (strength >= 3) {
+            // 密码强
+            return "passWord_strong";
+        }
+        return "";
+    }
+
+    public static void main(String[] args) {
+
+    }
+}

+ 1 - 0
Marketing/marketing-base/src/main/resources/META-INF/app.properties

@@ -0,0 +1 @@
+app.name=marketing

+ 79 - 0
Marketing/marketing-base/src/main/resources/application.yaml

@@ -0,0 +1,79 @@
+server:
+  port: 8089
+spring:
+  datasource:
+    druid:
+      name: master
+      url: jdbc:mysql://127.0.0.1:3307/bike?&zeroDateTimeBehavior=convertToNull&useSSL=false
+      username: root
+      password: server@188.24
+      driver-class-name: com.mysql.jdbc.Driver
+      type: com.alibaba.druid.pool.DruidDataSource
+      druid:
+        # 下面为连接池的补充设置,应用到上面所有数据源中
+        # 初始化大小,最小,最大
+        initial-size: 5
+        min-idle: 5
+        max-active: 20
+        # 配置获取连接等待超时的时间
+        max-wait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        time-between-eviction-runs-millis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        min-evictable-idle-time-millis: 300000
+        validation-query: SELECT 1 FROM DUAL
+        test-while-idle: true
+        test-on-borrow: false
+        test-on-return: false
+        # 打开PSCache,并且指定每个连接上PSCache的大小
+        pool-prepared-statements: true
+        #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+        max-pool-prepared-statement-per-connection-size: 20
+        filters: stat,wall
+        use-global-data-source-stat: true
+        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+        connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+  redis:
+    open: true  # 是否开启redis缓存  true开启   false关闭
+    database: 0
+    host: 127.0.0.1  # 测试环境redis
+    port: 6379
+    password: 3DACB724449FABEA1183729254046DFA      # 密码(默认为空)
+    jedis:
+      pool:
+        max-wait: -1      # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-idle: 10      # 连接池中的最大空闲连接
+        min-idle: 5
+        max-active: 1000       # 连接池中的最小空闲连接
+logging:
+  config: classpath:logback-dev.xml
+
+mybatis:
+  config-location: classpath:config/mybatis.xml
+  mapper-locations: classpath:sqlmap/*.xml
+
+dubbo:
+  application:
+    id: marketing
+    name: marketing
+    qosEnable: true
+    qosPort: 33333
+    qosAcceptForeignIp: false
+  registry:
+    address: zookeeper://localhost:2181
+  protocol:
+    name: dubbo
+    port: 20881
+  scan:
+    basePackages: com.mofang.travel
+  consumer:
+    timeout: 10000
+    check: false
+    retries: 0
+  provider:
+    retries: 0
+
+spring.kafka.bootstrap-servers: 127.0.0.1:9092
+spring.kafka.consumer.group-id: marketing
+spring.kafka.consumer.auto-offset-reset: latest
+

+ 9 - 0
Marketing/marketing-base/src/main/resources/config/mybatis.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE configuration
+        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <settings>
+        <setting name="logImpl" value="SLF4J"/>
+    </settings>
+</configuration>

+ 18 - 0
Marketing/marketing-base/src/main/resources/logback-dev.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder charset="UTF-8">
+            <pattern>%date [%thread] %-5level %logger [%L] - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <!--<appender name="CatAppender" class="com.kaola.travel.user.config.CatLogbackAppender"></appender>-->
+    <logger name="org.apache.ibatis" level="info" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <!--<appender-ref ref="CatAppender" />-->
+    </logger>
+    <!--调试模式下可以改为debug-->
+    <root level="INFO">
+        <!--<appender-ref ref="CatAppender" />-->
+        <appender-ref ref="CONSOLE"/>
+    </root>
+</configuration>

+ 72 - 0
Marketing/marketing-base/src/main/resources/logback-prod.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <springProperty scope="context" name="LOG_HOME" source="logback.file"/>
+    <!--info日志-->
+    <appender name="APP_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!--活动日志输出路径示例-->
+        <file>${LOG_HOME}/info.log</file>
+        <append>true</append>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>DENY</onMatch>
+            <onMismatch>ACCEPT</onMismatch>
+        </filter>
+        <!--存档日志示例-->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/info-${HOSTNAME}.%i.log.gz</fileNamePattern>
+            <!--日志大小可自定义-->
+            <maxFileSize>50MB</maxFileSize>
+            <!--存档天数可自定义-->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <!--统一日志输出格式-->
+        <encoder charset="UTF-8">
+            <pattern>%date [%thread] %-5level %logger [%L] - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <!--ERROR日志-->
+    <appender name="APP_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_HOME}/error.log</file>
+        <append>true</append>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/error-${HOSTNAME}.%i.log.gz</fileNamePattern>
+            <!--日志大小可自定义-->
+            <maxFileSize>50MB</maxFileSize>
+            <!--存档天数可自定义-->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+
+        <encoder charset="UTF-8">
+            <pattern>%date [%thread] %-5level %logger [%L] - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <!--<appender name="CatAppender" class="com.kaola.travel.user.config.CatLogbackAppender"></appender>-->
+
+    <logger name="org.apache.ibatis" level="info" additivity="false">
+        <appender-ref ref="APP_INFO"/>
+        <appender-ref ref="APP_ERROR"/>
+        <!--<appender-ref ref="CatAppender" />-->
+    </logger>
+
+    <logger name="com.kaola.travel" level="INFO" additivity="false">
+        <appender-ref ref="APP_INFO"/>
+        <appender-ref ref="APP_ERROR"/>
+        <!--<appender-ref ref="CatAppender" />-->
+    </logger>
+    <logger name="com.alibaba.dubbo" level="INFO" additivity="false">
+        <appender-ref ref="APP_INFO"/>
+        <appender-ref ref="APP_ERROR"/>
+        <!--<appender-ref ref="CatAppender" />-->
+    </logger>
+
+    <root level="INFO">
+        <!--<appender-ref ref="CatAppender" />-->
+        <appender-ref ref="APP_INFO"/>
+        <appender-ref ref="APP_ERROR"/>
+    </root>
+</configuration>

+ 17 - 0
Marketing/marketing-base/src/main/resources/sqlmap/BikeIconMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.mofang.travel.marketing.base.mapper.BikeIconMapper">
+    <resultMap id="BaseResultMap" type="com.mofang.travel.marketing.base.bean.po.BikeIcon">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="icon_name" jdbcType="VARCHAR" property="iconName"/>
+        <result column="icon_url" jdbcType="VARCHAR" property="iconUrl"/>
+    </resultMap>
+    <sql id="Base_Column_List">
+        id, icon_name, icon_url
+    </sql>
+    <select id="selectByBikeIcon" resultType="com.mofang.travel.marketing.domain.entity.BikeIconVo">
+        select bi.id, bi.icon_name, bi.icon_url
+        from bike_icon bi
+    </select>
+
+</mapper>

+ 51 - 0
Marketing/marketing-base/src/main/resources/sqlmap/UserRidingCardMapper.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.mofang.travel.marketing.base.mapper.UserRidingCardMapper">
+    <resultMap id="BaseResultMap" type="com.mofang.travel.marketing.base.bean.po.UserRidingCard">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="product_id" jdbcType="BIGINT" property="productId"/>
+        <result column="user_id" jdbcType="BIGINT" property="userId"/>
+        <result column="mobile" jdbcType="VARCHAR" property="mobile"/>
+        <result column="order_no" jdbcType="VARCHAR" property="orderNo"/>
+        <result column="app_from" jdbcType="VARCHAR" property="appFrom"/>
+        <result column="product_type" jdbcType="INTEGER" property="productType"/>
+        <result column="buyer_id" jdbcType="BIGINT" property="buyerId"/>
+        <result column="buyer_mobile" jdbcType="VARCHAR" property="buyerMobile"/>
+        <result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
+        <result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
+        <result column="original_number" jdbcType="TIMESTAMP" property="originalNumber"/>
+        <result column="left_number" jdbcType="TIMESTAMP" property="leftNumber"/>
+        <result column="riding_freq_limit" property="ridingFreqLimit" jdbcType="INTEGER"/>
+        <result column="riding_time_limit" property="ridingTimeLimit" jdbcType="INTEGER"/>
+        <result column="riding_mileage_limit" property="ridingMileageLimit" jdbcType="INTEGER"/>
+        <result column="each_free_amount" property="eachFreeAmount" jdbcType="DOUBLE"/>
+        <result column="auto_renew_flag" jdbcType="INTEGER" property="autoRenewFlag"/>
+        <result column="pay_method" jdbcType="INTEGER" property="payMethod"/>
+        <result column="status" jdbcType="INTEGER" property="status"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+        <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/>
+
+    </resultMap>
+    <sql id="Base_Column_List">
+        id, product_id, user_id, mobile, order_no,app_from, product_type,buyer_id,buyer_mobile,start_time,end_time,original_number,left_number,
+    riding_freq_limit,riding_time_limit,riding_mileage_limit,each_free_amount, create_time, modify_time, auto_renew_flag,pay_method,status
+    </sql>
+
+    <select id="selectByUserIdAndStartTime" resultType="com.mofang.travel.marketing.base.bean.po.UserRidingCard">
+        select u.id                as id,
+               u.product_id        as productId,
+               u.product_type      as productType,
+               u.start_time        as startTime,
+               u.end_time          as endTime,
+               u.auto_renew_flag   as autoRenewFlag,
+               u.left_number       as leftNumber,
+               r.product_title     as productTitle,
+               r.riding_freq_limit as ridingFreqLimit
+        from user_riding_card u
+                 left join riding_card_product r
+                           on u.product_id = r.id
+        where u.status = 1
+          AND u.user_id = #{userId,jdbcType=BIGINT}
+          and (end_time is null or end_time > #{startTime})
+    </select>
+</mapper>

+ 67 - 0
Marketing/marketing-domain/pom.xml

@@ -0,0 +1,67 @@
+<?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>com.mofang.travel.marketing</groupId>
+        <artifactId>marketing</artifactId>
+        <version>0.0.1</version>
+    </parent>
+
+    <groupId>com.mofang.travel.marketing</groupId>
+    <artifactId>marketing-domain</artifactId>
+    <version>${version}</version>
+    <modelVersion>4.0.0</modelVersion>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.16.10</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+            <version>2.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.4.1</version>
+        </dependency>
+        <!--FastJson1-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.mofang.travel.commons</groupId>
+            <artifactId>mofang-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <finalName>marketing-domain</finalName>
+        <plugins>
+            <!-- 要将源码放上去,需要加入这个插件 -->
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <attach>true</attach>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 25 - 0
Marketing/marketing-domain/src/main/java/com/mofang/travel/marketing/domain/entity/BikeIconVo.java

@@ -0,0 +1,25 @@
+package com.mofang.travel.marketing.domain.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 车辆车标
+ */
+@Data
+public class BikeIconVo implements Serializable {
+
+    private Long id;
+
+    /**
+     * 名称
+     */
+    private String iconName;
+
+    /**
+     * 图片地址
+     */
+    private String iconUrl;
+
+}

+ 38 - 0
Marketing/marketing-domain/src/main/java/com/mofang/travel/marketing/domain/enums/BikeStatusEnum.java

@@ -0,0 +1,38 @@
+package com.mofang.travel.marketing.domain.enums;
+
+/**
+ * 10-工厂检验中 20-运输中 30-库管中 40-待出租 50-已预约 60-出租中 70-特殊下架
+ * 80-被扣押 90-已丢失 100-维修中 110-馈电停租 130-已报废 140-换电中 150-调度中
+ * 160-待回库 170-回库中 175-待确认回库 180-待检修 190-检修中 195-待寻车 200-寻车中 210-越界停租
+ */
+public enum BikeStatusEnum {
+    WAIT_SELL(40, "待租中"),
+    WAIT_REPAIR(180, "待检修"),
+    APPOINTMENT(50, "已预约"),
+    LEASE(60, "出租中");
+
+    BikeStatusEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    private Integer code;
+    private String desc;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static BikeStatusEnum getEnum(Integer code) {
+        for (BikeStatusEnum scene : BikeStatusEnum.values()) {
+            if (scene.getCode() == code.intValue()) {
+                return scene;
+            }
+        }
+        return null;
+    }
+}

+ 75 - 0
Marketing/pom.xml

@@ -0,0 +1,75 @@
+<?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>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.0.2.RELEASE</version>
+    </parent>
+
+    <groupId>com.mofang.travel.marketing</groupId>
+    <artifactId>marketing</artifactId>
+    <packaging>pom</packaging>
+    <version>0.0.1</version>
+
+    <modules>
+        <module>marketing-domain</module>
+        <module>marketing-api</module>
+        <module>marketing-base</module>
+    </modules>
+
+
+    <properties>
+        <!--Spring-->
+        <spring.boot.version>2.0.2.RELEASE</spring.boot.version>
+        <!--Mybatis-->
+        <mybatis-spring.version>1.1.1</mybatis-spring.version>
+        <!--<pagehelper.version>4.1.6</pagehelper.version>-->
+        <cat.version>3.0.0</cat.version>
+        <!--基础工具包-->
+        <fastjson.version>1.2.46</fastjson.version>
+        <google.guava.version>20.0</google.guava.version>
+        <dubbo.version>2.7.2</dubbo.version>
+        <!-- apache commons补充包 -->
+        <apache-commons-lang3.version>3.4</apache-commons-lang3.version>
+        <!--编译选项-->
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <version>0.0.1</version>
+    </properties>
+
+    <build>
+        <finalName>marketing</finalName>
+        <plugins>
+            <!-- 要将源码放上去,需要加入这个插件 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <attach>true</attach>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>