فهرست منبع

feat: 先提交

bianzhenhua123 1 ماه پیش
کامیت
9e830f934b
91فایلهای تغییر یافته به همراه9301 افزوده شده و 0 حذف شده
  1. 54 0
      .gitignore
  2. 1 0
      README.md
  3. 65 0
      micro-common/pom.xml
  4. 12 0
      micro-common/src/main/java/com/poyee/common/annotation/ValueAspect.java
  5. 38 0
      micro-common/src/main/java/com/poyee/common/config/BaseConfig.java
  6. 33 0
      micro-common/src/main/java/com/poyee/common/config/CommonConfig.java
  7. 32 0
      micro-common/src/main/java/com/poyee/common/config/DynamicRedisConfig.java
  8. 47 0
      micro-common/src/main/java/com/poyee/common/config/Knife4jConfig.java
  9. 29 0
      micro-common/src/main/java/com/poyee/common/config/LimitRule.java
  10. 18 0
      micro-common/src/main/java/com/poyee/common/config/MetricsConfig.java
  11. 123 0
      micro-common/src/main/java/com/poyee/common/config/RedisConfig.java
  12. 88 0
      micro-common/src/main/java/com/poyee/common/config/ServerModel.java
  13. 21 0
      micro-common/src/main/java/com/poyee/common/constant/BusConstants.java
  14. 954 0
      micro-common/src/main/java/com/poyee/common/constant/Constants.java
  15. 11 0
      micro-common/src/main/java/com/poyee/common/constant/DictConstants.java
  16. 17 0
      micro-common/src/main/java/com/poyee/common/constant/RedisKeyConstants.java
  17. 33 0
      micro-common/src/main/java/com/poyee/common/constant/RetConstants.java
  18. 175 0
      micro-common/src/main/java/com/poyee/common/domain/BaseEntity.java
  19. 88 0
      micro-common/src/main/java/com/poyee/common/domain/CharsetKit.java
  20. 1001 0
      micro-common/src/main/java/com/poyee/common/domain/Convert.java
  21. 92 0
      micro-common/src/main/java/com/poyee/common/domain/StrFormatter.java
  22. 59 0
      micro-common/src/main/java/com/poyee/common/domain/entity/ActCountParam.java
  23. 136 0
      micro-common/src/main/java/com/poyee/common/domain/entity/AppActConfig.java
  24. 64 0
      micro-common/src/main/java/com/poyee/common/domain/entity/AppCarouselPicture.java
  25. 21 0
      micro-common/src/main/java/com/poyee/common/domain/entity/AppVersionParam.java
  26. 19 0
      micro-common/src/main/java/com/poyee/common/domain/entity/ApplicationInfo.java
  27. 69 0
      micro-common/src/main/java/com/poyee/common/domain/entity/SysDictData.java
  28. 13 0
      micro-common/src/main/java/com/poyee/common/domain/entity/TzyCardTaskRemind.java
  29. 56 0
      micro-common/src/main/java/com/poyee/common/domain/vo/AppActAdVO.java
  30. 122 0
      micro-common/src/main/java/com/poyee/common/domain/vo/AppActManageVO.java
  31. 32 0
      micro-common/src/main/java/com/poyee/common/domain/vo/AppCarouselPictureVO.java
  32. 179 0
      micro-common/src/main/java/com/poyee/common/dto/AppUserInfoDto.java
  33. 46 0
      micro-common/src/main/java/com/poyee/common/dto/DictPropDTO.java
  34. 166 0
      micro-common/src/main/java/com/poyee/common/dto/InDto.java
  35. 184 0
      micro-common/src/main/java/com/poyee/common/dto/OutDTO.java
  36. 32 0
      micro-common/src/main/java/com/poyee/common/dto/UserInfo.java
  37. 19 0
      micro-common/src/main/java/com/poyee/common/dto/qiniu/AntispamDTO.java
  38. 22 0
      micro-common/src/main/java/com/poyee/common/dto/qiniu/CensorDTO.java
  39. 18 0
      micro-common/src/main/java/com/poyee/common/dto/qiniu/CensorResult.java
  40. 18 0
      micro-common/src/main/java/com/poyee/common/dto/qiniu/SceneDetailDTO.java
  41. 17 0
      micro-common/src/main/java/com/poyee/common/dto/qiniu/scenesDTO.java
  42. 55 0
      micro-common/src/main/java/com/poyee/common/exception/ServiceException.java
  43. 65 0
      micro-common/src/main/java/com/poyee/common/utils/Base64Util.java
  44. 595 0
      micro-common/src/main/java/com/poyee/common/utils/DateUtils.java
  45. 12 0
      micro-common/src/main/java/com/poyee/common/utils/HostPropertyDefiner.java
  46. 209 0
      micro-common/src/main/java/com/poyee/common/utils/IpUtils.java
  47. 181 0
      micro-common/src/main/java/com/poyee/common/utils/ServletUtils.java
  48. 500 0
      micro-common/src/main/java/com/poyee/common/utils/StringUtils.java
  49. 129 0
      micro-common/src/main/java/com/poyee/common/utils/UserUtils.java
  50. 67 0
      micro-common/src/main/java/com/poyee/common/utils/bean/DozerUtils.java
  51. 36 0
      micro-common/src/main/java/com/poyee/common/utils/bean/JSONTools.java
  52. 35 0
      micro-dao/pom.xml
  53. 13 0
      micro-dao/src/main/java/com/poyee/dao/mapper/AppActPrizeRecordMapper.java
  54. 24 0
      micro-dao/src/main/java/com/poyee/dao/mapper/AppCarouselPictureMapper.java
  55. 14 0
      micro-dao/src/main/java/com/poyee/dao/mapper/AppCategoryPaymentMapper.java
  56. 21 0
      micro-dao/src/main/java/com/poyee/dao/mapper/BaseApiMapper.java
  57. 5 0
      micro-dao/src/main/java/com/poyee/dao/mapper/GroupApiMapper.java
  58. 23 0
      micro-dao/src/main/java/com/poyee/dao/mapper/SysDictDataMapper.java
  59. 13 0
      micro-dao/src/main/java/com/poyee/dao/mapper/TzyCardTaskRemindMapper.java
  60. 27 0
      micro-dao/src/main/resources/mapper/AppActPrizeRecordMapper.xml
  61. 42 0
      micro-dao/src/main/resources/mapper/AppCarouselPictureMapper.xml
  62. 12 0
      micro-dao/src/main/resources/mapper/AppCategoryPaymentMapper.xml
  63. 115 0
      micro-dao/src/main/resources/mapper/BaseApiMapper.xml
  64. 12 0
      micro-dao/src/main/resources/mapper/GroupApiMapper.xml
  65. 42 0
      micro-dao/src/main/resources/mapper/SysDictDataMapper.xml
  66. 27 0
      micro-dao/src/main/resources/mapper/TzyCardTaskInfoMapper.xml
  67. 42 0
      micro-manager/pom.xml
  68. 19 0
      micro-manager/src/main/java/com/poyee/manager/CacheRedisManager.java
  69. 47 0
      micro-manager/src/main/java/com/poyee/manager/CacheSqlManager.java
  70. 8 0
      micro-manager/src/main/java/com/poyee/manager/QiNiuManager.java
  71. 106 0
      micro-manager/src/main/java/com/poyee/manager/RedisManager.java
  72. 44 0
      micro-manager/src/main/java/com/poyee/manager/aspect/ValueAspectHandler.java
  73. 63 0
      micro-manager/src/main/java/com/poyee/manager/impl/CacheRedisManagerImpl.java
  74. 100 0
      micro-manager/src/main/java/com/poyee/manager/impl/CacheSqlManagerImpl.java
  75. 19 0
      micro-manager/src/main/java/com/poyee/manager/impl/QiNiuManagerImpl.java
  76. 970 0
      micro-manager/src/main/java/com/poyee/manager/impl/RedisManagerImpl.java
  77. 30 0
      micro-service/pom.xml
  78. 71 0
      micro-service/src/main/java/com/poyee/service/BusService.java
  79. 24 0
      micro-service/src/main/java/com/poyee/service/DictService.java
  80. 346 0
      micro-service/src/main/java/com/poyee/service/impl/BusServiceImpl.java
  81. 80 0
      micro-service/src/main/java/com/poyee/service/impl/DictServiceImpl.java
  82. 215 0
      pom.xml
  83. 66 0
      web-controller/pom.xml
  84. 20 0
      web-controller/src/main/java/com/poyee/SvrApplication.java
  85. 174 0
      web-controller/src/main/java/com/poyee/controller/AppCommonController.java
  86. 16 0
      web-controller/src/main/java/com/poyee/controller/DeploymentController.java
  87. 75 0
      web-controller/src/main/resources/application-prod.yml
  88. 111 0
      web-controller/src/main/resources/application.yml
  89. 11 0
      web-controller/src/main/resources/dozer/dozer-mapping.xml
  90. 21 0
      web-controller/src/main/resources/logback-fluentd.xml
  91. 125 0
      web-controller/src/main/resources/logback.xml

+ 54 - 0
.gitignore

@@ -0,0 +1,54 @@
+
+.idea
+# IDE
+.vscode/
+.settings/
+.project
+.classpath
+.factorypath
+
+# Build tool
+.mvn/
+mvnw
+mvnw.cmd
+
+# OS generated files
+Thumbs.db
+.DS_Store
+desktop.ini
+
+# Editor backup files
+*~
+*.swp
+*.bak
+
+# Temporary files
+tmp/
+temp/
+*.tmp
+
+# Logs
+logs/
+*.log.*
+
+# Maven
+.dependency-info/
+
+# Java
+*.jar
+*.war
+*.ear
+target/
+
+# Environment files
+.env
+*.env.*
+!.env.example
+
+# IDE specific files
+*.iws
+*.ipr
+.out/
+
+# Application specific
+.DS_Store

+ 1 - 0
README.md

@@ -0,0 +1 @@
+拍卖服务micro

+ 65 - 0
micro-common/pom.xml

@@ -0,0 +1,65 @@
+<?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>com.poyee</groupId>
+        <artifactId>poyee-micro</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>micro-common</artifactId>
+    <version>1.0.0</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.github.dozermapper</groupId>
+            <artifactId>dozer-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 12 - 0
micro-common/src/main/java/com/poyee/common/annotation/ValueAspect.java

@@ -0,0 +1,12 @@
+package com.poyee.common.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ ElementType.METHOD, ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ValueAspect {
+    String value();
+
+    String defaultValue() default "";
+}

+ 38 - 0
micro-common/src/main/java/com/poyee/common/config/BaseConfig.java

@@ -0,0 +1,38 @@
+package com.poyee.common.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@Data
+public class BaseConfig {
+	@Value("${tzy.app-version:dev}")
+	private String env;
+
+    // 核心线程池大小
+    private int corePoolSize = 100;
+    // 最大可创建的线程数
+    private int maxPoolSize = 300;
+    // 队列最大长度
+    private int queueCapacity = 600;
+    // 线程池维护线程所允许的空闲时间
+    private int keepAliveSeconds = 120;
+
+    @Bean
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setCorePoolSize(corePoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveSeconds);
+        // 线程池对拒绝任务(无线程可用)的处理策略
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.setThreadNamePrefix("micro-pool-");
+        return executor;
+    }
+}

+ 33 - 0
micro-common/src/main/java/com/poyee/common/config/CommonConfig.java

@@ -0,0 +1,33 @@
+package com.poyee.common.config;
+
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+
+/**
+ * @author by po'yi
+ * @Classname CommonConfig
+ * @Description TODO
+ * @Date 2021/12/16 14:05
+ */
+@Configuration
+public class CommonConfig {
+	public static BaseConfig baseconfig;
+	public static final String ENV_PRO = "prod";
+	public static final String ENV_TEST = "test";
+	public static final String ENV_DEV = "dev";
+
+
+	@Resource
+	public  void setBaseConfig(BaseConfig baseconfig) {
+		CommonConfig.baseconfig = baseconfig;
+	}
+
+	public static boolean isProdEnv(){
+		return ENV_PRO.equals(baseconfig.getEnv());
+	}
+
+	public static boolean isDevEnv(){
+		return ENV_DEV.equals(baseconfig.getEnv());
+	}
+}

+ 32 - 0
micro-common/src/main/java/com/poyee/common/config/DynamicRedisConfig.java

@@ -0,0 +1,32 @@
+package com.poyee.common.config;
+
+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.lang.NonNull;
+
+import java.time.Duration;
+
+public class DynamicRedisConfig extends RedisCacheManager {
+
+    public DynamicRedisConfig(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
+        super(cacheWriter, defaultCacheConfiguration);
+    }
+
+    @Override
+    @NonNull
+    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
+        String cacheName = name;
+        // 解析缓存名称中的 TTL 配置
+        if (name.contains("#")) {
+            String[] parts = name.split("#");
+            cacheName = parts[0];
+            long ttlSeconds = Long.parseLong(parts[1]);
+
+            // 创建带有特定 TTL 的配置
+            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttlSeconds));
+        }
+        return super.createRedisCache(cacheName, cacheConfig);
+    }
+}

+ 47 - 0
micro-common/src/main/java/com/poyee/common/config/Knife4jConfig.java

@@ -0,0 +1,47 @@
+package com.poyee.common.config;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
+
+@Configuration
+@EnableSwagger2WebMvc
+@RequiredArgsConstructor
+public class Knife4jConfig implements WebMvcConfigurer {
+
+    private static final String API_BASE_PACKAGE = "com.poyee";
+    private static final String API_TITLE = "poyee-micro";
+    private static final String API_DESCRIPTION = "poyee-micro";
+    private static final String API_CONTACT_NAME = "com/poyee";
+    private static final String API_VERSION = "1.0.0";
+    private static final String API_TERMS_OF_SERVICE = "";
+    private static final String API_LICENSE_URL = "";
+
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
+                                                      .select()
+                                                      .apis(RequestHandlerSelectors.basePackage(API_BASE_PACKAGE))
+                                                      .paths(PathSelectors.any())
+                                                      .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder().title(API_TITLE)
+                                   .description(API_DESCRIPTION)
+                                   .contact(new Contact(API_CONTACT_NAME, API_TERMS_OF_SERVICE, API_LICENSE_URL))
+                                   .version(API_VERSION)
+                                   .build();
+    }
+
+
+}

+ 29 - 0
micro-common/src/main/java/com/poyee/common/config/LimitRule.java

@@ -0,0 +1,29 @@
+package com.poyee.common.config;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class LimitRule {
+    public static final String COMMON="common";
+    public static final String USER="user";
+    public static final String ACT="act";
+    /**需要token*/
+    public static final String ACT_TOKEN="act_token";
+
+    /**几秒内限制*/
+    private int seconds;
+    /**可访问次数*/
+    private int limitCount;
+    /**锁定次数,limitCount相比取更大*/
+    private int lockCount;
+    /**锁定时间*/
+    private int lockTime;
+
+    public boolean enableLimitLock() {
+        return this.getLockTime() > 0 && this.getLockCount() > 0;
+    }
+}

+ 18 - 0
micro-common/src/main/java/com/poyee/common/config/MetricsConfig.java

@@ -0,0 +1,18 @@
+package com.poyee.common.config;
+
+import io.micrometer.prometheus.PrometheusConfig;
+import io.micrometer.prometheus.PrometheusMeterRegistry;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class MetricsConfig {
+
+    @Bean
+    public PrometheusMeterRegistry prometheusMeterRegistry() {
+        PrometheusMeterRegistry prometheusMeterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
+        prometheusMeterRegistry.config().commonTags("application", "poyee-micro");
+        return prometheusMeterRegistry;
+    }
+}

+ 123 - 0
micro-common/src/main/java/com/poyee/common/config/RedisConfig.java

@@ -0,0 +1,123 @@
+package com.poyee.common.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.SingleServerConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.io.IOException;
+import java.time.Duration;
+
+/**
+ * Redis配置
+ *
+ * @author zheng
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig {
+    @Value("${spring.redis.host:127.0.0.1}")
+    private String host;
+    @Value("${spring.redis.port:6379}")
+    private String port;
+    @Value("${spring.redis.password}")
+    private String password;
+
+	@Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory)
+    {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
+        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
+        // 开启事务
+        //redisTemplate.setEnableTransactionSupport(true);
+        redisTemplate.setConnectionFactory(factory);
+        return redisTemplate;
+
+    }
+    @Bean
+    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate)
+    {
+        return redisTemplate.opsForHash();
+    }
+
+    @Bean
+    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate)
+    {
+        return redisTemplate.opsForValue();
+    }
+
+    @Bean
+    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate)
+    {
+        return redisTemplate.opsForList();
+    }
+
+    @Bean
+    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate)
+    {
+        return redisTemplate.opsForSet();
+    }
+
+    @Bean
+    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate)
+    {
+        return redisTemplate.opsForZSet();
+    }
+
+    @Bean(name = "redissonClient")
+    public RedissonClient redissonClientSingle() throws IOException {
+        Config config = new Config();
+
+        SingleServerConfig singleServer = config.useSingleServer();
+        singleServer.setAddress("redis://" + host + ":" + port);
+        if (!StringUtils.isEmpty(password)) {
+            singleServer.setPassword(password);
+        }
+
+        return Redisson.create(config);
+    }
+
+    @Bean
+    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
+        ObjectMapper om = new ObjectMapper();
+        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        // 解决查询缓存转换异常的问题
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(om);
+        // 配置序列化(解决乱码的问题)
+        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
+                .entryTtl(Duration.ofMillis(-1))
+                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
+                .disableCachingNullValues();
+        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
+
+        /**
+         * 一般缓存不需要特别设置
+         * 限制 name#600 注解缓存时间
+         */
+        return new DynamicRedisConfig(cacheWriter, config);
+    }
+}

+ 88 - 0
micro-common/src/main/java/com/poyee/common/config/ServerModel.java

@@ -0,0 +1,88 @@
+package com.poyee.common.config;
+
+import lombok.Data;
+import lombok.ToString;
+
+@Data
+@ToString
+public class ServerModel {
+    private String custNo; //公司编号
+    private String custName; //公司名称
+    private String systemType;
+    private String dbType;
+    private String serverName;//服务器地址
+    private String dbName; //数据库名称
+    private String dbUser;
+    private String dbPassword;
+    private String dbDriver;
+    private String dbPort;
+    private String status;
+	public String getCustNo() {
+		return custNo;
+	}
+	public void setCustNo(String custNo) {
+		this.custNo = custNo;
+	}
+	public String getCustName() {
+		return custName;
+	}
+	public void setCustName(String custName) {
+		this.custName = custName;
+	}
+	public String getSystemType() {
+		return systemType;
+	}
+	public void setSystemType(String systemType) {
+		this.systemType = systemType;
+	}
+	public String getDbType() {
+		return dbType;
+	}
+	public void setDbType(String dbType) {
+		this.dbType = dbType;
+	}
+	public String getServerName() {
+		return serverName;
+	}
+	public void setServerName(String serverName) {
+		this.serverName = serverName;
+	}
+	public String getDbName() {
+		return dbName;
+	}
+	public void setDbName(String dbName) {
+		this.dbName = dbName;
+	}
+	public String getDbUser() {
+		return dbUser;
+	}
+	public void setDbUser(String dbUser) {
+		this.dbUser = dbUser;
+	}
+	public String getDbPassword() {
+		return dbPassword;
+	}
+	public void setDbPassword(String dbPassword) {
+		this.dbPassword = dbPassword;
+	}
+	public String getDbDriver() {
+		return dbDriver;
+	}
+	public void setDbDriver(String dbDriver) {
+		this.dbDriver = dbDriver;
+	}
+	public String getDbPort() {
+		return dbPort;
+	}
+	public void setDbPort(String dbPort) {
+		this.dbPort = dbPort;
+	}
+	public String getStatus() {
+		return status;
+	}
+	public void setStatus(String status) {
+		this.status = status;
+	}
+
+
+}

+ 21 - 0
micro-common/src/main/java/com/poyee/common/constant/BusConstants.java

@@ -0,0 +1,21 @@
+package com.poyee.common.constant;
+
+/**
+ * 业务相关敞亮
+ * @author: zhenhua.bian
+ * @date: 2025/10/24
+ */
+public class BusConstants {
+    /**
+     * 七牛云token
+     */
+    public static String QI_NIU_TOKEN = "qiniu_token";
+    public static final long QI_NIU_TOKEN_EXPIRE_TIME = 1800;
+    public static final String bucketName = "tzy-admin-public";
+    public static final String accessKey = "RYT6zfQA5Yf4IKgbaDBPMjEgQmzKdcfN48M8VIvI";
+    public static final String secretKey = "4P9slQYFTQeomzEMRj3Vq8n_WSv3IvbUvTSmwMwa";
+
+    /**
+     * 其他
+     */
+}

+ 954 - 0
micro-common/src/main/java/com/poyee/common/constant/Constants.java

@@ -0,0 +1,954 @@
+package com.poyee.common.constant;
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 通用常量信息
+ * 
+ * @author zheng
+ */
+public class Constants {
+	/**
+	 * UTF-8 字符集
+	 */
+	public static final String UTF8 = "UTF-8";
+
+	/**
+	 * GBK 字符集
+	 */
+	public static final String GBK = "GBK";
+
+	/**
+	 * 通用成功标识
+	 */
+	public static final String SUCCESS = "0";
+
+	/**
+	 * 通用失败标识
+	 */
+	public static final String FAIL = "1";
+
+	/**
+	 * 登录成功
+	 */
+	public static final String LOGIN_SUCCESS = "Success";
+
+	/**
+	 * 注销
+	 */
+	public static final String LOGOUT = "Logout";
+
+	/**
+	 * 注册
+	 */
+	public static final String REGISTER = "Register";
+
+	/**
+	 * 登录失败
+	 */
+	public static final String LOGIN_FAIL = "Error";
+
+	/**
+	 * 当前记录起始索引
+	 */
+	public static final String PAGE_NUM = "pageNum";
+
+	/**
+	 * 每页显示记录数
+	 */
+	public static final String PAGE_SIZE = "pageSize";
+
+	/**
+	 * 排序列
+	 */
+	public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+	/**
+	 * 排序的方向 "desc" 或者 "asc".
+	 */
+	public static final String IS_ASC = "isAsc";
+
+	/**
+	 * 参数管理 cache name
+	 */
+	public static final String SYS_CONFIG_CACHE = "sys-config";
+
+	/**
+	 * 参数管理 cache key
+	 */
+	public static final String SYS_CONFIG_KEY = "sys_config:";
+
+	/**
+	 * 字典管理 cache name
+	 */
+	public static final String SYS_DICT_CACHE = "sys-dict";
+
+	/**
+	 * 字典管理 cache key
+	 */
+	public static final String SYS_DICT_KEY = "sys_dict:";
+
+	/**
+	 * 资源映射路径 前缀
+	 */
+	public static final String RESOURCE_PREFIX = "/profile";
+	public static final String STOCK_GROUP_INFO = "STOCK_GROUP_INFO_";
+	public static final String AUTHENTICATION_TOKEN = "REDIS_AUTHENTICATION_TOKEN_";
+	public static final String AUTHORIZATION = "token";
+	public static final String ORDER_BY = "order by ";
+	public static final String STATUS_OK = "1";
+	public static final String ONE = "1";
+	public static final String ZERO = "0";
+	public static final String TWO = "2";
+	public static final String FINANCE_TYPE_ADD = "支付";
+	public static final String FINANCE_TYPE_RETURN = "退款";
+	public static final String PAY_CALLBACK_LOCK_KEY = "pay_callback_lock_key";
+	public static final String ORDER_CALLBACK_LOCK_KEY = "order_callback_lock_key";
+	public static final String TRADE_SUCCESS = "支付成功";
+	public static final String TRADE_SUCCESS_EN = "SUCCESS";
+	public static final String ALIPAY_TRADE_SUCCESS = "TRADE_SUCCESS";
+	public static final String ALIPAY_REFUND_SUCCESS = "REFUND_SUCCESS";
+	public static final String REDIRECT_PATH = "/pageB/productDetail/productDetail?id=";
+	public static final String TYPE_BANNER_DETAIL = "banner_detail";
+	public static final String QINIU_HOST = "https://static.public.hobbystock.cn";
+	public static final String MERCHANT_INFO_TYPE_SALE = "sale";
+	public static final String MERCHANT_INFO_TYPE_HISTORY = "history";
+	public static final String KEY_WORD = "keyword";
+	public static final String BANK_STR = " ";
+	public static final String EMPTY_STR = "";
+	public static final String AND_STR = "&";
+	public static final String USER_FACE_VERIFY = "USER_FACE_VERIFY_ID";
+	public static final String RY_TOKEN = "RY_TOKEN";
+	//商家拉黑类型
+	public static final @NotNull String DICT_TYPE_MER_PULL_BACK = "mer_pull_back";
+	public static long timesDay = 60 * 60 * 24 * 7;
+	public static long times = 1000 * timesDay;
+	public static final String OPTIONS = "OPTIONS";
+	public static final String ORDER_BUY_ALL_MARK = "ORDER_BUY_ALL_MARK";
+	public static final String CARD_INFO_MARK = "CARD_INFO_MARK_";
+	public static final String CARD_GOODS_ACT_SIGN = "CARD_GOODS_ACT_SIGN";
+	public static final String CARD_INFO_ACT_SIGN = "CARD_INFO_ACT_SIGN";
+	public static Map<String, Object> JSON_HEADS = new HashMap<String, Object>() {{
+		put("Content-Type", "application/json");
+	}};
+	public static final String JPUSH_TYPE_TAG = "tags";
+	public static final String JPUSH_TYPE_ID = "registrationIds";
+	public static final String ORDER_BUY_ALL_RETURN_TITLE = "亲爱的用户您好,感谢您对HOBBY STOCKS的支持,请理性参与购买,祝您玩卡愉快,得到好卡!";
+	public static final String CODE_TYPE_INCR = "CODE_TYPE_INCR_";
+	public static final String USER_CODE_TYPE_INCR = "USER_CODE_TYPE_INCR";
+	public static final String PRICE_FOR_NEW = "price_for_new";
+	public static String PUSH_TYPE_JPUSH = "jpush";
+	public static String PUSH_TYPE_SYSTEM = "system";
+	public static String PUSH_ACCEPT_TYPE_ALL = "all";
+	public static String PUSH_ACCEPT_TYPE_SETS = "sets";
+	public static String PUSH_ACCEPT_TYPE_GROUP = "group";
+	public static String PUSH_ACCEPT_TYPE_USER = "user";
+	public static String APP_VERSION_PROD = "prod";
+	public static String APP_VERSION_DEV = "dev";
+	/**
+	 * 买队玩法
+	 */
+	public static String INFO_TYPE_BUY_TEAM = "买队玩法";
+	/**
+	 * 选队随机
+	 */
+	public static String INFO_TYPE_SELECT_TEAM = "选队随机";
+	/**
+	 * 支持 转 剩余随机的玩法
+	 * ||买队,选队随机
+	 */
+	public static List<String> CAN_CHANGE_RATE = Arrays.asList(INFO_TYPE_BUY_TEAM, INFO_TYPE_SELECT_TEAM);
+	/**
+	 * 自选卡种
+	 */
+	public static String INFO_TYPE_SELECT_SETS = "自选卡种";
+	/**
+	 * 随机球队
+	 */
+	public static String INFO_TYPE_TEAM = "随机球队";
+	/**
+	 * 随机球员
+	 */
+	public static String INFO_TYPE_PLAYER = "随机球员";
+	/**
+	 * 随机卡种(区分编号)
+	 */
+	public static String INFO_TYPE_SETS = "随机卡种(区分编号)";
+	/**
+	 * 随机卡种(不区分编号)
+	 */
+	public static String INFO_TYPE_SETS_NUM = "随机卡种(不区分编号)";
+	/**
+	 * 选队随机 子分类:区域随机
+	 */
+	public static String INFO_SUB_TYPE_AREA_RANDOM = "区域随机";
+	public static String CACHE_GOODS_SETS = "APP_CACHE_GOODS_SETS_";
+	public static String CACHE_GOODS_TEAM = "APP_CACHE_GOODS_TEAM_";
+	public static String GROUP_INFO_MIX_MAX_PRICE = "GROUP_INFO_MIX_MAX_PRICE";
+	public static String GROUP_INFO_CLICK_COUNT = "GROUP_INFO_CLICK_COUNT";
+	public static String MERCHANT_APP_USER_LINK = "MERCHANT_APP_USER_LINK";
+	public static String INFO_SORT_RATE_TYPE = "info_sort_rate_type";
+	public static String SORT_RATE_TYPE_CLICK = "sort_rate_type_click";
+	public static String SORT_RATE_TYPE_SOLD_AMOUNT = "sort_rate_type_sold_amount";
+	public static String SORT_AMOUNT_RATE = "sort_amount_rate";
+	public static String SORT_AMOUNT_RATE_NEW = "sort_amount_rate_new";
+	public static String CARD_INFO_MARK_USER = "CARD_INFO_MARK_USER";
+	public static String CODE_USER_LINK = "CODE_USER_LINK";
+	public static String REFUND_TYPE = "REFUND_TYPE";
+	public static String REFUND_TYPE_CODE = "code";
+	public static String ORDER_MARK_USER_POINT = "ORDER_MARK_USER_POINT";
+	public static final String ORDER_MARK_INFO_MSG = "亲爱的卡迷用户,为了更好的营造平台用户购物体验,您购买的本组订单未支付(含订单支付超时)次数即将达到单日上限,若未及时支付,您将于24小时内无法购买本组商品。感谢您的配合,祝您玩卡愉快,获得心仪卡片!";
+	public static final String ORDER_MARK_INFO_MSG_END = "亲爱的卡迷用户,为了更好的营造平台用户购物体验,您购买的本组订单未支付(含订单支付超时)次数已达到单日上限,您将于24小时内无法购买本组商品。感谢您的配合,祝您玩卡愉快,获得心仪卡片!";
+	public static final String ORDER_MARK_APP_MSG = "亲爱的卡迷用户,为了更好的营造平台用户购物体验,您当日订单未支付(含订单支付超时)次数即将达到单日上限,若未及时支付,您将于24小时内无法购买本平台商品。感谢您的配合,祝您玩卡愉快,获得心仪卡片!";
+	public static final String ORDER_MARK_APP_MSG_END = "亲爱的卡迷用户,为了更好的营造平台用户购物体验,您当日订单未支付(含订单支付超时)次数已达到单日上限,您将于24小时内无法购买本平台商品。感谢您的配合,祝您玩卡愉快,获得心仪卡片!";
+	public static final String PHONE_CHECK = "PHONE_CHECK";
+	public static final String LIMIT_RULE = "LIMIT_RULE";
+	public static final String comma = ",";
+	public static final String dot = ".";
+	public static final String pound_key = "#";
+	public static final String comma2 = ",,";
+	public static final String comma3 = ",,,";
+	public static final String bank = " ";
+	public static final String sub = "-";
+	public static final String seq_ZN = "编";
+	public static final String NO = "No.";
+	public static final String WORK_WX_LIVE_OPEN = "work_wx_live_open";
+	public static final String XML_BACK_SUCCESS = " xmlBack = \"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>\";";
+	public static String GROUP_PLAYBACKPATH = "GROUP_PLAYBACKPATH_";
+	public static String ORDER_CANCEL_PREFIX = "ORDERCANCELPREFIX_";
+	public static String ORDER_CANCEL_LOCK = "ORDER_CANCEL_LOCK_";
+	public static final String All = "all";
+	public static final String TRUE_STR = "T";
+	public static final String LIVE_TYPE_APPLET = "applet";
+	public static final String LIVE_TYPE_WORK_WX = "work_wx";
+	public static final String LIVE_TYPE_RONG_CLOUD = "rongcloud";
+	//腾讯直播
+	public static final String LIVE_TYPE_TENCENT_CLOUD = "tencent_cloud";
+	//火山直播
+	public static final String LIVE_TYPE_VOLC = "volc";
+	public static String EDIT_TYPE_PAY_PSD = "pay_psd";
+	public static String EDIT_TYPE_LOGIN_PSD = "login_psd";
+	public static String MSG_PAGE = "MSG_PAGE";
+	public static String HOT_TYPE = "HOT_TYPE";
+	public static String USER_PSD_COUNT = "USER_PSD_COUNT";
+	public static String USER_PAY_REMIND = "USER_PAY_REMIND";
+	public static final String UPDATE_GROUP_QUERY = "UPDATE_GROUP_QUERY_";
+	/**
+	 * 优惠劵类型:组团
+	 */
+	public static final String COUPON_TYPE_CARD = "card";
+	/**
+	 * 优惠劵类型:商品
+	 */
+	public static final String COUPON_TYPE_GOODS = "goods";
+	/**
+	 * 活动商品类型:虚拟商品,和sku无关了
+	 */
+	public static final String SKU_TYPE_VIRTUAL_GOODS = "virtual_goods";
+	/**
+	 * 订单类型:组团
+	 */
+	public static final String ORDER_TYPE_GROUP = "group";
+	/**
+	 * 订单类型:商城
+	 */
+	public static final String ORDER_TYPE_SHOP = "shop";
+	/**
+	 * 商品类型:积分
+	 */
+	public static final String SKU_TYPE_POINT = "point";
+	/**
+	 * 商城商品
+	 */
+	public static final String SKU_TYPE_GOODS = COUPON_TYPE_GOODS;
+	/**
+	 * 商品类型:纯金额
+	 */
+	public static final String SKU_TYPE_AMOUNT = "amount";
+	/**
+	 * 商品类型:混合
+	 */
+	public static final String SKU_TYPE_MIX = "mix";
+	/**
+	 * 商品活动类型:优惠劵
+	 */
+	public static final String SKU_ACT_TYPE_COUPON = "coupon";
+	/**
+	 * 人脸识别不提醒白名单
+	 */
+	public static String WHITELIST_FAVE_VERIFY_USER = "WHITELIST_FAVE_VERIFY_USER";
+	/**
+	 * spu库存锁key
+	 */
+	public static String SPU_SOLD_STOCK_LOCK = "SPU_SOLD_STOCK_LOCK";
+	public static String MALL_ORDER_DETAIL_URL = "/pageC/shoppingUser/myOrderDetials?id=";
+
+	public static final List<Integer> refundOrderStatus = Arrays.asList(101, 102, 103, 104, 105, 106, 301, 302);
+	/**
+	 * 商户积分
+	 */
+	public static final String POINT_TYPE_MERCHANT = "merchant";
+	public static final String POINT_NAME_MERCHANT = "商家活动积分";
+	/**
+	 * 商家活动前缀
+	 */
+	public static final String POINT_TYPE_MERCHANT_ACT_PRE = "mer_act";
+	/**
+	 * 平台活动前缀
+	 */
+	public static final String POINT_TYPE_HB_ACT_PRE = "hb_act";
+	public static final String POINT_NAME_HB_ACT = "HS活动积分";
+	/**
+	 * 平台活动前缀,需要订单完结
+	 */
+	public static final String POINT_TYPE_HB_ACT_OVER_PRE = "hb_act_over";
+	/**
+	 * 平台积分
+	 */
+	public static final String POINT_TYPE_COMMON = "common";
+	public static final String POINT_NAME_COMMON = "平台积分";
+	/**
+	 * 商城购物积分
+	 */
+	public static final String POINT_TYPE_GOODS = "goods";
+	public static final String POINT_NAME_GOODS = "商城积分";
+	/**
+	 * 积分消耗
+	 */
+	public static final String POINT_TYPE_COMMON_SUB = "common_sub";
+	/**
+	 * 积分活动
+	 */
+	public static final String POINT_TYPE_COMMON_ACT = "common_act";
+	public static final String POINT_TYPE_COMMON_ACT_SUB = "common_act_sub";
+	/**
+	 * 积分返回
+	 */
+	public static final String POINT_TYPE_COMMON_RETURN = "common_return";
+	/**
+	 * 活动积分-SP
+	 */
+	public static final String POINT_TYPE_ACT_SP = "SP";
+	public static final String POINT_NAME_ACT_SP = "SP积分";
+	/**
+	 * 商城,仅添加记录
+	 */
+	public static final String POINT_TYPE_ADD_RECORD = "record";
+	public static final String POINT_TYPE_ADD_RECORD_NEW = "common_record";
+	/**
+	 * 竞价积分-通用积分
+	 */
+	public static final String AUCTION_ORDER_COMMON_POINT = "auction_common_point";
+	public static final String AUCTION_ORDER_COMMON_AMOUNT = "auction_common_amount";
+	/**
+	 * 鸿运系列积分-lucky_point
+	 */
+	public static final String POINT_TYPE_ACT_LUCKY = "lucky_point";
+	/**
+	 * 用户成长值
+	 */
+	public static final String POINT_TYPE_USER_GROWTH = "user_growth";
+	public static final String POINT_NAME_USER_GROWTH = "会员成长值";
+	/**
+	 * 精美卡片积分类型前缀,后面拼上card_id
+	 */
+	public static final String POINT_TYPE_GIFT_CARD_PRE = "gift_card_";
+	public static final String POINT_NAME_GIFT_CARD = "精美卡片";
+	public static final String INFO_TEAM_PRICE = "info_team_price";
+	public static final String OTHER_STR = "OTHER";
+	public static final String TEAM_SIMPLE_NAME = "team_simple_name";
+	public static final String TEAM_SIMPLE_NAME_NEW = "team_simple_name_new";
+	public static final String INFO_SELECT_TEAM_CACHE = "INFO_SELECT_TEAM_CACHE";
+	public static final String INFO_ONLY_TEAM_CACHE = "INFO_ONLY_TEAM_CACHE_";
+	public static final String POINT_CHANGE_RMB = "point_rmb_rate";
+	//verify_user_act  实名用户活动
+	public static final String POINT_TYPE_VERIFY_USER_ACT = "verify_user_act";
+	//complete_order_act 消费达标活动
+	public static final String POINT_TYPE_COMPLETE_ORDER_ACT = "complete_order_act";
+	//act_task_labubu labubu抽奖活动
+	public static final String POINT_TYPE_ACT_LABUBU = "act_task_";
+
+	/**
+	 * 用户支付类型配置
+	 */
+	public static final String USER_PAY_TYPE_CONFIG = "user_pay_type_config";
+	/**
+	 * 订单随机支付类型配置
+	 */
+	public static final String PAY_TYPE_RANDOM_CONFIG = "pay_type_random_config";
+	/**
+	 * 每日支付金额统计
+	 */
+	public static final String PAY_AMOUNT_DAY_KEY = "pay_amount_day_";
+	/**
+	 * 每日支付次数统计
+	 */
+	public static final String PAY_COUNT_DAY_KEY = "pay_count_day_";
+	public static final String PAY_FAIL_COUNT = "pay_fail_count";
+	public static final String ENFORCE_FAVE_VERIFY_USER = "enforce_fave_verify_user_fail";
+	public static final String ENFORCE_FACE_VERIFY_REMIND = "enforce_face_verify_remind";
+	public static final BigDecimal RMB_ONE_CENT = new BigDecimal("0.01");
+	/**
+	 * 选队转随机
+	 */
+	public static final String INFO_TYPE_TEAM_TO_RANDOM = "team_to_random";
+	public static final String INFO_REAL_SOLD_COUNT = "info_real_sold_count_";
+	public static final String ALIPAY_MAIN_BF = "alipay-main-bf";
+	public static final String WXPAY_MAIN_BF = "wxpay-main-bf";
+
+	public static final String INFO_TEAM_TO_RANDOM_CACHE = "info_team_to_random_cache_";
+	public static final String CHINA = "china";
+	public static final String IP_CACHE = "app_ip_address_cache";
+	public static final String TEAM_CHANGE_RATE = "team_change_rate";
+	public static final String BUY_TEAM_CHANGE_RATE = "buy_team_change_rate";
+	public static final String DEFAULT_PAY_TYPE = "alipay";
+	public static final String ADD = "add";
+	public static final String SUB = "sub";
+	public static final String EVALUATION_LEVEL_MIDDLE = "middle";
+	public static final String EVALUATION_LEVEL_BAD = "bad";
+	public static final String EVALUATION_LEVEL_GOOD = "good";
+	public static final String GUESS_GOODS_CACHE = "guess_goods_cache_";
+	public static final String URL_LIMIT_COUNT = "url_limit_count";
+	//关注
+	public static final String FANS_TYPE_USER_LIKE = "user_like";
+	//用户拉黑
+	public static final String FANS_TYPE_USER_DISLIKE = "user_dislike";
+	//商家拉黑
+	public static final String FANS_TYPE_MERCHANT_DISLIKE = "merchant_dislike";
+	/**
+	 * 拉黑缓存key
+	 */
+	public static final String MERCHANT_DISLIKE_USER = "merchant_dislike_user";
+	public static final String USER_DISLIKE_MERCHANT = "user_dislike_merchant";
+	/**
+	 * 卡种字典表记录id
+	 */
+	public static final String INFO_SETS_RECORD_ID = "info_sets_record_id";
+	/**
+	 * 用户下单分布式key,同一时间仅能提交一种订单
+	 */
+	public static final String GROUP_ORDER_LOCK = "group_order_lock_";
+	/**
+	 * AES秘钥
+	 */
+	public static final String AES_TOKEN_PASSWORD = "C19CF02FC6A2040FC9A16BA5161F2D17";
+	public static final String AES_USER_PASSWORD = "E1C7AE96EFE6CD2CD84861C029C2E80D";
+	/**
+	 * 抢购token
+	 */
+	public static final String AES_TOKEN_CACHE = "AES_TOKEN_CACHE";
+	public static final String ACT_USER_TOKEN_CACHE = "ACT_USER_TOKEN_CACHE";
+	/**
+	 * 卡单用户限制
+	 */
+	public static final String ORDER_LIMIT_USER = "order_limit_user";
+	/**
+	 * 免验证手机号
+	 */
+	public static final List<String> NO_CHECK_PHONE = Arrays.asList("17317287633", "13071005103", "15618709098", "15679535223");
+	/**
+	 * 订单子类型,赠送订单接收
+	 */
+	public static final String ORDER_SUB_TYPE_RECEIVE = "receive";
+	/**
+	 * 订单子类型,奖品订单
+	 */
+	public static final String ORDER_SUB_TYPE_PRIZE = "prize_ship";
+	/**
+	 * 订单子类型,赠送订单:赠送
+	 */
+	public static final String ORDER_SUB_TYPE_GIVE_AWAY = "give_away";
+	public static final String SKU_COUPON_ID_CACHE = "sku_coupon_id_cache";
+	/**
+	 * 秒级别-半小时
+	 */
+	public static final int HALF_AN_HOUR = 1800;
+	/**
+	 * 秒级别-1小时
+	 */
+	public static final int ONE_HOUR = 3600;
+	/**
+	 * 优惠劵使用域
+	 */
+	public static final String COUPON_SCOPE_CONFIG = "coupon_scope_config";
+	public static final String COUPON_SCOPE_CONFIG_CACHE = "coupon_scope_config_cache";
+	/**
+	 * 支付类型
+	 */
+	public static final String PAYMENT_TYPE = "payment_type";
+
+	public static final String DAY = "day";
+	public static final String HOUR = "hour";
+
+	public static final String ACT_PRIZE_CACHE = "act_prize";
+	public static final String ACT_PRIZE_INFO_CACHE = "act_prize_info";
+	public static final String ACT_PRIZE_POOL_CACHE = "act_prize_pool";
+	public static final String ACT_TASK_SHARE_CACHE = "act_task_share_cache:";
+	public static final String DEFAULT_STR = "default";
+	/**
+	 * 发票类型,个人
+	 */
+	public static final String INVOICE_TYPE_PERSON = "person";
+	/**
+	 * 发票类型,企业
+	 */
+	public static final String INVOICE_TYPE_COMPANY = "company";
+	public static final BigDecimal HUNDRED = new BigDecimal("100");
+
+	public static final BigDecimal ONE_THOUSAND = new BigDecimal("1000");
+	/**
+	 * sku库存key
+	 */
+	public static final String SKU_STOCK_PRE = "sku_stock_";
+	public static final String NUM_REG = "^[0-9]+$";
+	/**
+	 * 开屏广告活动key
+	 */
+	public static final String APP_ACT_CACHE = "app_act_cache";
+	/**
+	 * 活动参与类型:积分
+	 */
+	public static final String ACT_SUB_TYPE_POINT = "point";
+	/**
+	 * 活动参与类型:次数
+	 */
+	public static final String ACT_SUB_TYPE_TIMES = "times";
+
+	public static final String COUPON_ACT_MERCHANT = "coupon_act_merchant";
+	/**
+	 * 卡密活动类型:商品
+	 */
+	public static final String GOODS_ACT_TYPE_GOODS = COUPON_TYPE_GOODS;
+	/**
+	 * 卡密活动类型:优惠劵
+	 */
+	public static final String GOODS_ACT_TYPE_COUPON = "coupon";
+	/**卡密活动类型:大转盘*/
+	/**
+	 * 卡密活动类型:大转盘
+	 */
+	public static final String GOODS_ACT_TYPE_TURNTABLE = "turntable";
+
+	public static final String CACHE_CALENDAR_LIST_SEARCH = "cache_calendar_list_search";
+	public static final String EVALUATION_TYPE_LIST_CALENDAR = "checklist_calendar";
+	/**
+	 * 完结组团状态
+	 */
+	public static final List<Integer> GROUP_FULL_STATUS = Arrays.asList(203, 204, 205, 2051, 206, 301);
+
+	/**
+	 * 随买随机分配卡密
+	 */
+	public static final String GROUP_RANDOM_ALL = "random_all";
+	/**
+	 * 选队随机
+	 */
+	public static final String GROUP_RANDOM_SELECT_TEAM = "random_select_team";
+	/**
+	 * 选队,区域随机
+	 */
+	public static final String GROUP_RANDOM_SELECT_CONFERENCE = "random_select_conference";
+	/**
+	 * 选队/区域转随机
+	 */
+	public static final String GROUP_RANDOM_SELECT_TO_RANDOM = "select_to_random";
+	/**
+	 * 买队,无随机
+	 */
+	public static final String GROUP_RANDOM_BUY_TEAM = "random_buy_team";
+	/**
+	 * 组满随机,暂不存在
+	 */
+	public static final String GROUP_RANDOM_FULL_ALL = "random_full_all";
+	/**
+	 * 买队转随机,暂不存在
+	 */
+	public static final String GROUP_RANDOM_BUY_TEAM_ALL = "random_buy_team_all";
+
+	public static final String RESTRICT_USER = "restrict_user"; // 黑名单用户字典type
+	public static final String RESTRICT_USER_CACHE = "restrict_user_cache"; // 黑名单用户信息key
+	public static final String RESTRICT_USER_ADDRESS = "restrict_user_address"; // 黑名单用户地址key
+	/**
+	 * 卡密来源-组队卡密
+	 */
+	public static final String GOODS_REF_TYPE_GROUP = "group";
+	public static final String CODE_TYPE_PRIZE = "prize";
+	/**
+	 * 公布抽奖结果回调url
+	 */
+	public static final String CODE_PUBLIC_CALL_BACK_URL = "http://poyee-app/api/local/public";
+	//不属于金额支付的支付类型
+	public static final List<String> payment_type = Arrays.asList("point", "积分抽奖", "活动赠送");
+
+	public static final String ES_CACHE_CARD_GROUP_INFO = "es_cache_card_group_info";
+
+	public static final String INDEX_NAME = "app_es_group";
+	//顺丰快递
+	public static final String SF_TOKEN = "sf_token";
+	public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
+	public static final String CONTENT_TYPE_JSON = "application/json";
+	public static final String express_level_type = "express_level";
+
+	public static final String stop_courier_mer = "stop_courier_mer";
+	/**
+	 * 一天的秒
+	 */
+	public static final Long dayForSecond = 86400L;
+	/**
+	 * 一周的毫秒
+	 */
+	public static final Long WEEK_OF_TIMESTAMP = 86400L * 7000;
+	/**
+	 * 仓管费
+	 */
+	public static final Integer warehouseFee = 0;
+	/**
+	 * 预售开卡订单key
+	 */
+	public static final String ALLOCATE_USER_GOODS_ORDER = "allocate_user_goods_order_";
+	/**
+	 * 会员初始化
+	 */
+	public static final String MEMBER_INIT_KEY = "app_user_member_init";
+
+	public static final String PAY_BOFOO = "bof";
+	public static final String PAY_ADAPAY = "adapay";
+
+	/**
+	 * 组队组齐后发放
+	 */
+	public static final String MERCHANT_ACT_GROUP_FULL = "merchant_act_group_full";
+	/**
+	 * 公示卡密后发放
+	 */
+	public static final String MERCHANT_ACT_PUBLIC_GOODS = "merchant_act_public_goods";
+	/**
+	 * 订单购买后分配
+	 */
+	public static final String MERCHANT_ACT_AFT_ORDER = "merchant_act_aft_order";
+	/**
+	 * 随机:订单购买后分配
+	 */
+	public static final String MERCHANT_ACT_RANDOM_AFT_ORDER = "merchant_act_random_aft_order";
+	/**
+	 * 随机:订单购买后分配
+	 */
+	public static final String MERCHANT_ACT_RANDOM_GROUP_FULL = "merchant_act_random_group_full";
+
+	public static final String payment_type_agreement = "agreement";
+
+	public static final String payment_type_bank = "bank";
+	public static final String payment_type_uac = "uac";
+	public static final String payment_type_alipay = "alipay";
+	/**
+	 * 正常订单
+	 */
+	public static final String order_type_normal = "normal";
+	/**
+	 * 需要退款订单
+	 */
+	public static final String order_type_refund = "refund";
+
+	public static final String lucky_point_2023_618 = "lucky_point_2023_618";
+	/**
+	 * 鸿运系列积分 618 -lucky_point
+	 */
+	public static final String POINT_TYPE_ACT_LUCKY_618 = "lucky_point_2023_618";
+	/**
+	 * hotType时间缓存
+	 */
+	public static final String APP_HOT_TYPE_TIMES_CACHE = "app_hot_type_times_cache";
+	/**
+	 * 昵称黑名单
+	 */
+	public static final String APP_NAME_BACK_LIST_CACHE = "app_name_back_list_cache";
+	/**
+	 * 用户标签:高频
+	 */
+	public static final String APP_USER_CAT_HIGH_FREQUENCY = "high_frequency";
+	public static final String APP_USER_CAT_TYPE_USER_PAY = "user_pay";
+
+	public static final String PHONE_TYPE_IOS = "IOS";
+
+	public static final String LIST_ACT_TYPE_SET = "list_act_all_set";
+	public static final String LIST_ACT_ALL_TEAM = "list_act_all_team";
+	public static final String LIST_ACT_ALL_PLAYER = "list_act_all_player";
+	public static final String LIST_ACT_SELECT_PLAYER = "list_act_select_player";
+	public static final String LIST_ACT_SELECT_TEAM = "list_act_select_team";
+	public static final String LIST_ACT_SELECT_SET = "list_act_select_set";
+	public static final String LIST_ACT_SELECT_NUM = "list_act_select_num";
+	/**
+	 * 球员球队list的key
+	 */
+	public static final String LIST_ACT_OF_PLAYER_TEAM = "list_act_of_set_player_team";
+	/**
+	 * 卡密收集活动类型
+	 */
+	public static final List<String> listActTypes = Arrays.asList("list_act_all_set", "list_act_all_team", "list_act_all_player",
+			"list_act_select_player", "list_act_select_team", "list_act_select_set", "list_act_select_num");
+
+	public static final String MEMBER_BENEFITS = "member_benefits";
+
+	public static final String BRAND_MEMBER_BENEFITS = "brand_member_benefits";
+	/**
+	 * 支付限流
+	 */
+	public static final String PAYMENT_TYPE_LIMIT_KEY = "payment_type_limit_key_";
+
+	public static final String USER_PAY_REMIND_DAY = "app_user_pay_remind_day";
+
+	public static final String USER_PAY_REMIND_MONTH = "app_user_pay_remind_month";
+	/**
+	 * 买退
+	 */
+	public static final String ALLOW_REFUND_SALE = "买退";
+	// 偏远地区
+	public static final String REMOTE_SHIPPING_FEE = "remote_shipping_fee";
+	/**
+	 * 消息类型
+	 */
+	public static final String APP_NOTIFY_TYPE_CONFIG = "app_notify_type_config";
+	/**
+	 * 消息显示大类型
+	 */
+	public static final String APP_NOTIFY_SHOW_CONFIG = "app_notify_show_config";
+	/**
+	 * 消息初始化类型
+	 */
+	public static final String APP_NOTIFY_INIT_CONFIG = "app_notify_init_config";
+
+	public static final String APP_CACHE_USER_NOTIFY_CONFIG = "app_cache_user_notify_config_";
+	/**
+	 * 物流订单号对应支付单号
+	 */
+	public static final String SHIPPING_TRADE_NO_TO_ORDER = "shipping_trade_no_to_order";
+
+	public static final String LIVE_EFFECTS = "live_effects";
+	/**
+	 * 支付编号对应订单
+	 */
+	public static final String PAY_TRADE_NO_TO_ORDER = "pay_trade_no_to_order";
+	/**
+	 * 组队卡密活动:选中卡密
+	 */
+	public static final String GROUP_ACT_TYPE_SELECT = "select";
+	/**
+	 * 组队卡密活动:随机卡密
+	 */
+	public static final String GROUP_ACT_TYPE_RANDOM = "random";
+	/**
+	 * 消费达标活动
+	 */
+	public static final String ACT_TYPE_CONSUME_LEVEL = "consume_level";
+	/**
+	 * 抽卡机活动
+	 */
+	public static final String ACT_TYPE_DRAW_CARD_GAME = "draw_card_game";
+	public static final String ACT_NAME_DRAW_CARD_GAME = "抽卡机活动币";
+	/**
+	 * 抽卡活动类型
+	 */
+	public static final String USER_DRAW_CARD_ACT = "user_draw_card_act";
+
+	public static final String ACT_BASE_SHIPPING_COST_KEY = "act_base_shipping_cost";
+
+	public static final BigDecimal ACT_BASE_SHIPPING_COST = new BigDecimal("9.9");
+
+
+	public static final String ACT_GOODS_TYPE_SET = "set";
+	public static final String ACT_GOODS_TYPE_TEAM = "team";
+	public static final String ACT_GOODS_TYPE_PLAYER = "player";
+	public static final String PART_COUPON = "part_coupon";
+	public static final String COLLECT_PANINI_ACT = "collect_panini_act";
+	//精美卡片key
+	public static final String GROUP_GIFT_CARD = "group_gift_card";
+	//精美卡片订单
+	public static final String ORDER_TYPE_GIFT_CARD = "gift_card";
+
+	public static final String ORDER_TYPE_DRAW = "draw";
+	;
+	//评级保证金
+	public static final String GRADE_EARNEST_AMOUNT = "grade_earnest_amount";
+
+	public static final String GRADE_INSURE_AMOUNT = "grade_insure_amount";
+
+	/**
+	 * 物流订单号对应支付单号
+	 */
+	public static final String GRADE_TRADE_NO_TO_ORDER = "grade_trade_no_to_order";
+	/**
+	 * 支付编号对应支付记录
+	 */
+	public static final String TRADE_NO_TO_PAY_RECORD = "trade_no_to_pay_record";
+	public static final String ANONYMOUS_NAME = "匿名用户";
+	public static final String ANONYMOUS_AVATAR = "https://static.public.hobbystock.cn/MC143302022060920611/avatar/1666182630730.jpg";
+
+	public static final String MERCHANT_POINT_SHOW = "merchant_point_show";
+	public static final String USER_SUB_POINT_LOCK = "user_sub_point_lock";
+	/**
+	 * 拼团赠送红包大转盘key
+	 */
+	public static final String INFO_GIVE_DRAW = "info_give_draw";
+	/**
+	 * 拼团618砍一刀
+	 */
+	public static final String ACT_GROUP_DECR_AMOUNT = "group_decr_amount";
+	public static String GROUP_USER_SHARE_24_618 = "group_user_share_24_618";
+	public static String ACT_CARD_REMOVAL = "act_card_removal";
+	public static String SEND_LIKE_ACT_PRIZE_ORDERS = "send_like_act_prize_orders";
+	public static String ACT_LIMIT_NUM_618 = "act_limit_num_618";
+	public static String email_notice_hzt = "hzt1212520@126.com";
+	/**
+	 * 私域显示
+	 */
+	public static String PRIVATE_SHOW_TYPE = "private_show_type";
+	/**
+	 * 商家赠礼活动
+	 */
+	public static final String MERCHANT_ACT_GIFT = "merchant_act_send_gift";
+
+	public static final String TYPE_SHOP_POINT = "shop_order_point";
+	/**
+	 * 即将售罄查询每个商家个数-key
+	 */
+	public static final String ALMOST_FINISHED_NUM = "almost_finished_num";
+	/**
+	 * 好卡点赞
+	 */
+	public static final String FOLLOW_TOP_CARD_LIKE = "top_card_like";
+	/**
+	 * 首页红包列表
+	 */
+	public static final String FIRST_PAGE_DRAW_ACT = "first_page_draw_act";
+	//用户高频支付限制数量key
+	public static final String USER_PAY_LIMIT = "user_pay_limit";
+	/**
+	 * 用户消费限额提示key
+	 */
+	public static final String USER_LIMIT_PAY_NOTICE_KEY = "user_limit_pay_notice_%s_%s";
+	/**
+	 * 用户消费限额配置
+	 */
+	public static final String USER_LIMIT_PAY_CONFIG = "user_limit_pay_config";
+	/**
+	 * 用户提额问卷
+	 */
+	public static final String TYPE_USER_INCR_AMOUNT = "user_incr_amount";
+	/**
+	 * 用户月度提醒
+	 */
+	public static final String REFUSE_CARD_NOTICE = "refuse_card_notice:";
+	/**
+	 * 商家集团活动积分前缀
+	 */
+	public static final String POINT_TYPE_MERCHANT_GROUP_ACT_PRE = "mer_group_act";
+	/**
+	 * 商品购买资格
+	 */
+	public static final String PRIZE_REDUCTION_BUY_NUM = "reduction_buy_num";
+	public static final String USER_BUY_GROUP_INFO_KEY = "user_buy_group_info_%s_%s";
+	public static final String USER_CONTAINS_CAT_KEY_PRE = "user_cat_key_%s_%s_%s";
+	public static final String APP_CAT_SEARCH_ORDER = "user_search_order";
+	/**
+	 * 拼团活动积分倍率
+	 */
+	public static final String GROUP_ACT_RATE_PRE = "group_act_rate_";
+	/**
+	 * 拼团消费达标积分活动
+	 */
+	public static final String CONSUME_GROUP_ACT_POINT = "consume_group_act_point";
+	/**
+	 * 拼团组齐次数达标
+	 */
+	public static final String CONSUME_GROUP_FULL_COUNT = "consume_group_full_count";
+	/**
+	 * 新版退款模式,异步mq消费
+	 */
+	public static final String ASYNC_REFUND_TYPE = "amount_async";
+	/**
+	 * 退款模式2,仅退款,不更新订单状态
+	 */
+	public static final String REFUND_TYPE_AMOUNT_ONLY = "amount_only";
+	public static final String REFUND_SUB_TYPE_AMOUNT = "amount";
+	public static final String REFUND_SUB_TYPE_POINT = "point";
+	public static final String ACT_GOODS_COMMON_SORT = "act_goods_common_sort";
+
+
+	public static final String LUCK_BAG_ONLINE_REDIS_KEY = "luck_bag_online_redis_key_";
+	public static final String LUCK_BAG_JOIN_REDIS_KEY = "luck_bag_join_redis_key_";
+	public static final String GROUP_FULL_COUNT = "group_full_count";
+	public static final String GROUP_ACT_RATE = "group_act_rate";
+
+	/**
+	 * 生态购商家id
+	 */
+	public static final List<Long> GROUP_SALE_MERCHANT_IDS = Arrays.asList(31L, 1430L);
+	//拼团详情关注类型
+	public static final String GROUP_DETAIL_FOLLOW = "group_detail_follow";
+	//app商家指定权限
+	public static final String APP_MER_PERMISSIONS = "app_mer_permissions";
+	//直播间用户key
+	public static final String LIVING_ROOM_USER_KEY="living_room_user_key:";
+	//商家名下用户订单数量
+	public static final String MERCHANT_USER_ORDER_NUM="merchant_user_order_num:";
+	//用户变动
+	public static final String LIVING_USER_CHANGE_RECORD="living_user_change_record:";
+	/**拼团退款申请*/
+	public static final String REFUND_TYPE_GROUP = "group_refund";
+	/**拼团下架退款申请*/
+	public static final String REFUND_SUB_TYPE_OFF = "refund_off";
+	//订单退款状态
+	public static final List<Integer> REFUND_STATUS_LIST=Arrays.asList(204,205,206);
+	//直播间点赞key
+	public static final String LIVING_ROOM_LIKE_KEY="living_room_like_key:";
+	//直播间点赞人和点赞数key
+	public static final String LIVING_ROOM_LIKE_USER_KEY="living_room_like_user_key:";
+	//直播间点赞通知延时key
+	public static final String LIVING_ROOM_LIKE_DELAY_KEY="living_room_like_delay_key:";
+	//直播间点赞DB延时队列
+	public static final String LIVING_ROOM_LIKE_DB_DELAY_KEY="living_room_like_db_delay_key:";
+	/** 品牌会员积分前缀 **/
+	public static final String BRAND_POINT_TYPE_PRE = "diy_brand_point_";
+	/** 品牌会员成长值前缀 **/
+	public static final String BRAND_GROWTH_TYPE_PRE = "diy_brand_growth_";
+	/** 品牌会员初始化key **/
+	public static final String BRAND_MEMBER_INIT_KEY = "brand_member_init";
+	//精美卡片订单运费记录key
+	public static final String COST_ORDER_RECORD = "cost_order_record";
+	/** 商城首单券 **/
+	public static final String FIRST_ORDER_MERCHANT = "first_order_merchant";
+
+	public static final String APP_SEARCH_CACHE_KEY = "search_api_cache:app_search_cache_key_";
+
+	/** 签到 */
+	public static final String APP_ACT_TASK_TYPE_SIGNIN = "signIn";
+	/** 拼团支付 */
+	public static final String APP_ACT_TASK_TYPE_GROUPPAYMENT = "groupPayment";
+	/** 全平台支付 */
+	public static final String APP_ACT_TASK_TYPE_PAYMENT = "payment";
+	/** 商城商品支付 */
+	public static final String APP_ACT_TASK_TYPE_GOODSPAYMENT = "goodsPayment";
+	/** 拼团完成 */
+	public static final String APP_ACT_TASK_TYPE_GROUPCOMPLETEPAYMENT = "groupCompletePayment";
+	/** 支付完成 */
+	public static final String APP_ACT_TASK_TYPE_PAYCOMPLETEPAYMENT = "payCompletePayment";
+	/** 邀请 */
+	public static final String APP_ACT_TASK_TYPE_INVTATION = "invitation";
+
+
+	//商家邀请码配置的优惠券
+	public static final String DICT_TYPE_INVITE_CODE = "merchant_invite_code";
+
+
+	/**
+	 * 商家发货锁单
+	 */
+	public static final String REDIS_KEY_MERCHANT_DELIVERY_LOCK = "merchant_delivery_lock:";
+
+
+}

+ 11 - 0
micro-common/src/main/java/com/poyee/common/constant/DictConstants.java

@@ -0,0 +1,11 @@
+package com.poyee.common.constant;
+
+/**
+ * 字典类常量
+ */
+public class DictConstants {
+    public static final String STOP_UPDATE_VERSION = "stop_update_version";
+    public static final String APP_ONLINE_VERSION = "app_online_version";
+    public static final String APP_ONLINE_VERSION_IOS = "app_online_version_ios";
+    public static final String APP_ONLINE_VERSION_ANDROID = "app_online_version_android";
+}

+ 17 - 0
micro-common/src/main/java/com/poyee/common/constant/RedisKeyConstants.java

@@ -0,0 +1,17 @@
+package com.poyee.common.constant;
+
+public class RedisKeyConstants {
+    /**
+     * 提醒任务
+     */
+    public static final String REMINDER_TASK = "reminderTask_";
+    public static final Long REMINDER_TASK_TIMEOUT = 300L;
+    public static final String ACT_REMIND_CACHE_USERID = "act_remind_cache_%s_userid_%s";
+
+    /**
+     * app活动配置
+     */
+    public static final String APP_ACT_CONFIG = "appActConfig";
+
+    public static final Long COMMON_DAY_TIMEOUT = 86400L;
+}

+ 33 - 0
micro-common/src/main/java/com/poyee/common/constant/RetConstants.java

@@ -0,0 +1,33 @@
+package com.poyee.common.constant;
+
+/**
+ * 返回值常量
+ */
+public enum RetConstants {
+    SUCCESS(0, "成功"),
+    ERROR(1, "失败"),
+    ERROR_PARAM(2, "参数错误"),
+    ERROR_NOT_LOGIN(500, ""),
+    ERROR_NOT_AUTH(4, "无权限"),
+    ERROR_NOT_EXIST(5, "不存在"),
+    ERROR_NOT_FOUND(501, "获取七牛token失败!"),
+    ERROR_NOT_SUPPORT(7, "不支持"),
+    ERROR_NOT_ALLOW(8, "不允许"),
+    ERROR_NOT_SUPPORT_OPERATION(9, "不支持的操作");
+
+    private final int code;
+    private final String message;
+
+    RetConstants(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}

+ 175 - 0
micro-common/src/main/java/com/poyee/common/domain/BaseEntity.java

@@ -0,0 +1,175 @@
+package com.poyee.common.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.poyee.common.utils.StringUtils;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Entity基类
+ * 
+ * @author zheng
+ */
+public class BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 搜索值 */
+    @JsonIgnore
+    private String searchValue;
+    
+    /**
+     * 字段查询
+     */
+    @JsonIgnore
+    private String columnsearch;
+	/** 创建者 */
+    @JsonIgnore
+    private String createBy;
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    /** 更新者 */
+    @JsonIgnore
+    private String updateBy;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 备注 */
+    private String remark;
+
+    /** 请求参数 */
+    @JsonIgnore
+    private Map<String, Object> params;
+    //分页
+    @JsonIgnore
+    private Integer page;
+    @JsonIgnore
+    private Integer rows;
+    //排序
+    @JsonIgnore
+    private String sidx;
+    @JsonIgnore
+    private String sord;
+    @JsonIgnore
+    public static List<String> types = Arrays.asList(new String[]{ "columnsearch","searchValue","params","page","rows","sidx","sord"});
+
+
+    public Integer getPage() {
+        return page;
+    }
+
+    public void setPage(Integer page) {
+        this.page = page;
+    }
+
+    public Integer getRows() {
+        return rows;
+    }
+
+    public void setRows(Integer rows) {
+        this.rows = rows;
+    }
+
+    public String getSidx() {
+        return sidx;
+    }
+
+    public void setSidx(String sidx) {
+        this.sidx = sidx;
+    }
+
+    public String getSord() {
+        return sord;
+    }
+
+    public void setSord(String sord) {
+        this.sord = sord;
+    }
+
+    public String getSearchValue()
+    {
+        return searchValue;
+    }
+
+    public void setSearchValue(String searchValue)
+    {
+        this.searchValue = searchValue;
+    }
+
+    public String getColumnsearch() {
+        if(StringUtils.isNotEmpty(columnsearch))return this.columnsearch.replaceAll("☻", "%");
+		return columnsearch;
+	}
+
+	public void setColumnsearch(String columnsearch) {
+		this.columnsearch = columnsearch;
+	}
+	
+    public String getCreateBy()
+    {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy)
+    {
+        this.createBy = createBy;
+    }
+
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy()
+    {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy)
+    {
+        this.updateBy = updateBy;
+    }
+
+    public Date getUpdateTime()
+    {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime)
+    {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+
+    public Map<String, Object> getParams()
+    {
+        if (params == null)
+        {
+            params = new HashMap<>();
+        }
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params)
+    {
+        this.params = params;
+    }
+}

+ 88 - 0
micro-common/src/main/java/com/poyee/common/domain/CharsetKit.java

@@ -0,0 +1,88 @@
+package com.poyee.common.domain;
+
+
+import com.poyee.common.utils.StringUtils;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ * 
+ * @author zheng
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 转换为Charset对象
+     * 
+     * @param charset 字符集,为空则返回默认字符集
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            srcCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 系统字符集编码
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}

+ 1001 - 0
micro-common/src/main/java/com/poyee/common/domain/Convert.java

@@ -0,0 +1,1001 @@
+package com.poyee.common.domain;
+
+
+import com.poyee.common.utils.StringUtils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+
+/**
+ * 类型转换器
+ * 
+ * @author zheng
+ */
+public class Convert
+{
+    /**
+     * 转换为字符串<br>
+     * 如果给定的值为null,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static String toStr(Object value, String defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof String)
+        {
+            return (String) value;
+        }
+        return value.toString();
+    }
+
+    /**
+     * 转换为字符串<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static String toStr(Object value)
+    {
+        return toStr(value, null);
+    }
+
+    /**
+     * 转换为字符<br>
+     * 如果给定的值为null,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Character toChar(Object value, Character defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Character)
+        {
+            return (Character) value;
+        }
+
+        final String valueStr = toStr(value, null);
+        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+    }
+
+    /**
+     * 转换为字符<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Character toChar(Object value)
+    {
+        return toChar(value, null);
+    }
+
+    /**
+     * 转换为byte<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Byte toByte(Object value, Byte defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Byte)
+        {
+            return (Byte) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).byteValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Byte.parseByte(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为byte<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Byte toByte(Object value)
+    {
+        return toByte(value, null);
+    }
+
+    /**
+     * 转换为Short<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Short toShort(Object value, Short defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Short)
+        {
+            return (Short) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).shortValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Short.parseShort(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Short<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Short toShort(Object value)
+    {
+        return toShort(value, null);
+    }
+
+    /**
+     * 转换为Number<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Number toNumber(Object value, Number defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return NumberFormat.getInstance().parse(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Number<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Number toNumber(Object value)
+    {
+        return toNumber(value, null);
+    }
+
+    /**
+     * 转换为int<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Integer toInt(Object value, Integer defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Integer)
+        {
+            return (Integer) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).intValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Integer.parseInt(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为int<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Integer toInt(Object value)
+    {
+        return toInt(value, null);
+    }
+
+    /**
+     * 转换为Integer数组<br>
+     * 
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Integer[] toIntArray(String str)
+    {
+        return toIntArray(",", str);
+    }
+
+    /**
+     * 转换为Long数组<br>
+     * 
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Long[] toLongArray(String str)
+    {
+        return toLongArray(",", str);
+    }
+
+    /**
+     * 转换为Integer数组<br>
+     * 
+     * @param split 分隔符
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static Integer[] toIntArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Integer[] {};
+        }
+        String[] arr = str.split(split);
+        final Integer[] ints = new Integer[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Integer v = toInt(arr[i], 0);
+            ints[i] = v;
+        }
+        return ints;
+    }
+
+    /**
+     * 转换为Long数组<br>
+     * 
+     * @param split 分隔符
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Long[] toLongArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Long[] {};
+        }
+        String[] arr = str.split(split);
+        final Long[] longs = new Long[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Long v = toLong(arr[i], null);
+            longs[i] = v;
+        }
+        return longs;
+    }
+
+    /**
+     * 转换为String数组<br>
+     * 
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String str)
+    {
+        return toStrArray(",", str);
+    }
+
+    /**
+     * 转换为String数组<br>
+     * 
+     * @param split 分隔符
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String split, String str)
+    {
+        return str.split(split);
+    }
+
+    /**
+     * 转换为long<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Long toLong(Object value, Long defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Long)
+        {
+            return (Long) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).longValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 支持科学计数法
+            return new BigDecimal(valueStr.trim()).longValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为long<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Long toLong(Object value)
+    {
+        return toLong(value, null);
+    }
+
+    /**
+     * 转换为double<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Double toDouble(Object value, Double defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Double)
+        {
+            return (Double) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).doubleValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 支持科学计数法
+            return new BigDecimal(valueStr.trim()).doubleValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为double<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Double toDouble(Object value)
+    {
+        return toDouble(value, null);
+    }
+
+    /**
+     * 转换为Float<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Float toFloat(Object value, Float defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Float)
+        {
+            return (Float) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).floatValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Float.parseFloat(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Float<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Float toFloat(Object value)
+    {
+        return toFloat(value, null);
+    }
+
+    /**
+     * 转换为boolean<br>
+     * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Boolean toBool(Object value, Boolean defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Boolean)
+        {
+            return (Boolean) value;
+        }
+        String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        valueStr = valueStr.trim().toLowerCase();
+        switch (valueStr)
+        {
+            case "true":
+                return true;
+            case "false":
+                return false;
+            case "yes":
+                return true;
+            case "ok":
+                return true;
+            case "no":
+                return false;
+            case "1":
+                return true;
+            case "0":
+                return false;
+            default:
+                return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为boolean<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Boolean toBool(Object value)
+    {
+        return toBool(value, null);
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 
+     * @param clazz Enum的Class
+     * @param value 值
+     * @param defaultValue 默认值
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (clazz.isAssignableFrom(value.getClass()))
+        {
+            @SuppressWarnings("unchecked")
+            E myE = (E) value;
+            return myE;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Enum.valueOf(clazz, valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 
+     * @param clazz Enum的Class
+     * @param value 值
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+    {
+        return toEnum(clazz, value, null);
+    }
+
+    /**
+     * 转换为BigInteger<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigInteger)
+        {
+            return (BigInteger) value;
+        }
+        if (value instanceof Long)
+        {
+            return BigInteger.valueOf((Long) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigInteger(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为BigInteger<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigInteger toBigInteger(Object value)
+    {
+        return toBigInteger(value, null);
+    }
+
+    /**
+     * 转换为BigDecimal<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigDecimal)
+        {
+            return (BigDecimal) value;
+        }
+        if (value instanceof Long)
+        {
+            return new BigDecimal((Long) value);
+        }
+        if (value instanceof Double)
+        {
+            return new BigDecimal((Double) value);
+        }
+        if (value instanceof Integer)
+        {
+            return new BigDecimal((Integer) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigDecimal(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为BigDecimal<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     * 
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigDecimal toBigDecimal(Object value)
+    {
+        return toBigDecimal(value, null);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     * 
+     * @param obj 对象
+     * @return 字符串
+     */
+    public static String utf8Str(Object obj)
+    {
+        return str(obj, CharsetKit.CHARSET_UTF_8);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     * 
+     * @param obj 对象
+     * @param charsetName 字符集
+     * @return 字符串
+     */
+    public static String str(Object obj, String charsetName)
+    {
+        return str(obj, Charset.forName(charsetName));
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     * 
+     * @param obj 对象
+     * @param charset 字符集
+     * @return 字符串
+     */
+    public static String str(Object obj, Charset charset)
+    {
+        if (null == obj)
+        {
+            return null;
+        }
+
+        if (obj instanceof String)
+        {
+            return (String) obj;
+        }
+        else if (obj instanceof byte[] || obj instanceof Byte[])
+        {
+            return str((Byte[]) obj, charset);
+        }
+        else if (obj instanceof ByteBuffer)
+        {
+            return str((ByteBuffer) obj, charset);
+        }
+        return obj.toString();
+    }
+
+    /**
+     * 将byte数组转为字符串
+     * 
+     * @param bytes byte数组
+     * @param charset 字符集
+     * @return 字符串
+     */
+    public static String str(byte[] bytes, String charset)
+    {
+        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * 解码字节码
+     * 
+     * @param data 字符串
+     * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+     * @return 解码后的字符串
+     */
+    public static String str(byte[] data, Charset charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        if (null == charset)
+        {
+            return new String(data);
+        }
+        return new String(data, charset);
+    }
+
+    /**
+     * 将编码的byteBuffer数据转换为字符串
+     * 
+     * @param data 数据
+     * @param charset 字符集,如果为空使用当前系统字符集
+     * @return 字符串
+     */
+    public static String str(ByteBuffer data, String charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        return str(data, Charset.forName(charset));
+    }
+
+    /**
+     * 将编码的byteBuffer数据转换为字符串
+     * 
+     * @param data 数据
+     * @param charset 字符集,如果为空使用当前系统字符集
+     * @return 字符串
+     */
+    public static String str(ByteBuffer data, Charset charset)
+    {
+        if (null == charset)
+        {
+            charset = Charset.defaultCharset();
+        }
+        return charset.decode(data).toString();
+    }
+
+    // ----------------------------------------------------------------------- 全角半角转换
+    /**
+     * 半角转全角
+     * 
+     * @param input String.
+     * @return 全角字符串.
+     */
+    public static String toSBC(String input)
+    {
+        return toSBC(input, null);
+    }
+
+    /**
+     * 半角转全角
+     * 
+     * @param input String
+     * @param notConvertSet 不替换的字符集合
+     * @return 全角字符串.
+     */
+    public static String toSBC(String input, Set<Character> notConvertSet)
+    {
+        char c[] = input.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 跳过不替换的字符
+                continue;
+            }
+
+            if (c[i] == ' ')
+            {
+                c[i] = '\u3000';
+            }
+            else if (c[i] < '\177')
+            {
+                c[i] = (char) (c[i] + 65248);
+
+            }
+        }
+        return new String(c);
+    }
+
+    /**
+     * 全角转半角
+     * 
+     * @param input String.
+     * @return 半角字符串
+     */
+    public static String toDBC(String input)
+    {
+        return toDBC(input, null);
+    }
+
+    /**
+     * 替换全角为半角
+     * 
+     * @param text 文本
+     * @param notConvertSet 不替换的字符集合
+     * @return 替换后的字符
+     */
+    public static String toDBC(String text, Set<Character> notConvertSet)
+    {
+        char c[] = text.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 跳过不替换的字符
+                continue;
+            }
+
+            if (c[i] == '\u3000')
+            {
+                c[i] = ' ';
+            }
+            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+            {
+                c[i] = (char) (c[i] - 65248);
+            }
+        }
+        String returnString = new String(c);
+
+        return returnString;
+    }
+
+    /**
+     * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+     * 
+     * @param n 数字
+     * @return 中文大写数字
+     */
+    public static String digitUppercase(double n)
+    {
+        String[] fraction = { "角", "分" };
+        String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
+        String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };
+
+        String head = n < 0 ? "负" : "";
+        n = Math.abs(n);
+
+        String s = "";
+        for (int i = 0; i < fraction.length; i++)
+        {
+            s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+        }
+        if (s.length() < 1)
+        {
+            s = "整";
+        }
+        int integerPart = (int) Math.floor(n);
+
+        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+        {
+            String p = "";
+            for (int j = 0; j < unit[1].length && n > 0; j++)
+            {
+                p = digit[integerPart % 10] + unit[1][j] + p;
+                integerPart = integerPart / 10;
+            }
+            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+        }
+        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+    }
+}

+ 92 - 0
micro-common/src/main/java/com/poyee/common/domain/StrFormatter.java

@@ -0,0 +1,92 @@
+package com.poyee.common.domain;
+
+import com.poyee.common.utils.StringUtils;
+
+/**
+ * 字符串格式化
+ * 
+ * @author zheng
+ */
+public class StrFormatter
+{
+    public static final String EMPTY_JSON = "{}";
+    public static final char C_BACKSLASH = '\\';
+    public static final char C_DELIM_START = '{';
+    public static final char C_DELIM_END = '}';
+
+    /**
+     * 格式化字符串<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param strPattern 字符串模板
+     * @param argArray 参数列表
+     * @return 结果
+     */
+    public static String format(final String strPattern, final Object... argArray)
+    {
+        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+        {
+            return strPattern;
+        }
+        final int strPatternLength = strPattern.length();
+
+        // 初始化定义好的长度以获得更好的性能
+        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+        int handledPosition = 0;
+        int delimIndex;// 占位符所在位置
+        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+        {
+            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+            if (delimIndex == -1)
+            {
+                if (handledPosition == 0)
+                {
+                    return strPattern;
+                }
+                else
+                { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+                    sbuf.append(strPattern, handledPosition, strPatternLength);
+                    return sbuf.toString();
+                }
+            }
+            else
+            {
+                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+                {
+                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+                    {
+                        // 转义符之前还有一个转义符,占位符依旧有效
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                        handledPosition = delimIndex + 2;
+                    }
+                    else
+                    {
+                        // 占位符被转义
+                        argIndex--;
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(C_DELIM_START);
+                        handledPosition = delimIndex + 1;
+                    }
+                }
+                else
+                {
+                    // 正常占位符
+                    sbuf.append(strPattern, handledPosition, delimIndex);
+                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                    handledPosition = delimIndex + 2;
+                }
+            }
+        }
+        // 加入最后一个占位符后所有的字符
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}

+ 59 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/ActCountParam.java

@@ -0,0 +1,59 @@
+package com.poyee.common.domain.entity;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Classname ActCountParam
+ * @Description 活动限流参数
+ * @Date 2024/3/5 15:52
+ * @Created by Administrator
+ */
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+public class ActCountParam implements Serializable {
+    /**活动id*/
+    private Integer actId;
+    /**是否仅查询当日*/
+    private boolean curDay;
+    /**开始时间范围,小时,0-23*/
+    private Integer startHour;
+    /**截止时间范围,小时,1-24*/
+    private Integer endHour;
+    /**关联来源id*/
+    private Integer refId;
+    private Integer userId;
+    private Integer shareUserId;
+    /**活动类型*/
+    private String actType;
+    //是否包含分享参与
+    private boolean excludeShare;
+    //仅查询分享
+    private boolean onlyShare;
+    //用户邀请和被邀请
+    private boolean userAndShare;
+
+    private String shareCode;
+
+    private String prizeImg;
+
+    private List<Long> actIds;
+    /**id*/
+    private Integer id;
+    /**拼团id*/
+    private Integer groupInfoId;
+    private Date startTime;
+    private Date endTime;
+    /**奖品类型*/
+    private String prizeType;
+    public ActCountParam(Integer actId, boolean curDay) {
+        this.actId = actId;
+        this.curDay = curDay;
+    }
+}

+ 136 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/AppActConfig.java

@@ -0,0 +1,136 @@
+package com.poyee.common.domain.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description  
+ * @Author  poyee
+ * @Date 2022-10-10 
+ */
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AppActConfig implements Serializable {
+
+	private static final long serialVersionUID =  8207660194957131175L;
+
+	private Long id;
+
+	/**
+	 * 活动类型:优惠劵:coupon;广告:ad
+	 */
+	private String type;
+
+	/**
+	 * 用户消费金额
+	 */
+	private Long userGrowth;
+
+	/**
+	 * 组团id
+	 */
+	private Long groupInfoId;
+
+	/**
+	 * 用户购买过的卡组
+	 */
+	private String set;
+
+	/**
+	 * 状态:1开启,0关闭
+	 */
+	private Integer status;
+
+	/**
+	 * 描述
+	 */
+	private String description;
+
+	private Date createTime;
+
+	/**
+	 * 活动名称
+	 */
+	private String actName;
+
+	/**
+	 * 开始时间
+	 */
+	private Date startTime;
+
+	/**
+	 * 结束时间
+	 */
+	private Date endTime;
+
+	/**
+	 * 优惠劵id集合,多个逗号拼接
+	 */
+	private String couponIds;
+
+	/**
+	 * 历史购买时间天数
+	 */
+	private Integer historyLimitDay;
+
+	/**
+	 * 当天开始时间,24小时制,0-24
+	 */
+	private Integer startHour;
+
+	/**
+	 * 当天结束时间,24小时制0-24
+	 */
+	private Integer endHour;
+
+	/**
+	 * 活动图片
+	 */
+	private String actImg;
+
+	/**
+	 * 图片:img,视频:video,动图:gif
+	 */
+	private String imgType;
+
+	/**
+	 * 跳转链接
+	 */
+	private String actUrl;
+
+	/**
+	 * 排序时间
+	 */
+	private Integer sortValue;
+
+	/**
+	 * 提醒时间间隔,单位小时,默认0,仅一次
+	 */
+	private Integer remindTime;
+
+	/**
+	 * 点击区域,默认0,任意点击,1区域点击
+	 */
+	private Integer clickType;
+
+	/**
+	 * 持续时间,默认5秒
+	 */
+	private Integer lastTime;
+
+	/**
+	 * 开屏广告:open_ad,首页推广:first_page
+	 */
+	private String subType;
+
+	/**
+	 * 条件1:and 0:or
+	 */
+	private Integer op;
+    /**关联标签id*/
+	private Long catId;
+}

+ 64 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/AppCarouselPicture.java

@@ -0,0 +1,64 @@
+package com.poyee.common.domain.entity;
+
+import com.poyee.common.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 轮播图对象 app_carousel_picture
+ * 
+ * @author tencheer
+ * @date 2021-07-09
+ */
+@Data
+public class AppCarouselPicture extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 所属程序 */
+    private String appid;
+
+    /** 排序 */
+    private Long sort;
+
+    /** 轮播图地址 */
+    private String path;
+
+    /** 描述 */
+    private String msg;
+
+    /** 跳转地址 */
+    private String redirectPath;
+    /**
+     * 类别
+     */
+    private String type;
+    /**
+     * 子类别
+     */
+    private String subType;
+    /** 状态 */
+    private Long status;
+
+    /** 部门id */
+    private Long departId;
+
+    private Date startTime;
+
+    private Date endTime;
+
+    /**
+     * 轮播图名称
+     */
+    private String name;
+
+    /**
+     * 轮播图描述
+     */
+    private String description;
+
+}

+ 21 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/AppVersionParam.java

@@ -0,0 +1,21 @@
+package com.poyee.common.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author by po'yi
+ * @Classname AppVersionParam
+ * @Description TODO
+ * @Date 2023/7/3 14:57
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AppVersionParam implements Serializable {
+	private String atVersion;
+	private String type;
+}

+ 19 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/ApplicationInfo.java

@@ -0,0 +1,19 @@
+package com.poyee.common.domain.entity;
+
+import lombok.Data;
+import lombok.ToString;
+
+/**
+ * 程序信息
+ */
+@Data
+@ToString
+public class ApplicationInfo {
+    private Integer  isUpdate;
+    private String  wgtUrl;
+    private Integer  autoUpdate ;
+    private Integer  autoRestart;
+    private String  tips;
+    private Integer  showLog;
+    private String  releaseType;
+}

+ 69 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/SysDictData.java

@@ -0,0 +1,69 @@
+package com.poyee.common.domain.entity;
+
+import com.alibaba.fastjson2.JSON;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.poyee.common.domain.BaseEntity;
+import com.poyee.common.dto.DictPropDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 字典数据表 sys_dict_data
+ * 
+ * @author zheng
+ */
+@EqualsAndHashCode(callSuper = true)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@Data
+public class SysDictData extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 字典编码 */
+    private Long dictCode;
+
+    /** 字典排序 */
+    private Long dictSort;
+
+    /** 字典标签 */
+    private String dictLabel;
+
+    /** 字典键值 */
+    private String dictValue;
+
+    /** 字典类型 */
+    private String dictType;
+
+    /** 样式属性(其他样式扩展) */
+    private String cssClass;
+
+    /** 表格字典样式 */
+    private String listClass;
+
+    /** 是否默认(Y是 N否) */
+    private String isDefault;
+
+    /** 状态(0正常 1停用) */
+    private String status;
+
+    private Integer abroadFlag;
+
+    /** 间隔时间,默认0,不限制,单位秒 */
+    private Integer limitTime;
+    /** 配置json */
+    private String propConfig;
+
+    private DictPropDTO dictProp;
+    //对公转账信息
+    private String paymentBankInfo;
+    //对公转账 验证码
+    private String tradeNo;
+
+    public DictPropDTO getDictProp() {
+        if(StringUtils.isNotEmpty(propConfig)){
+            return JSON.parseObject(propConfig, DictPropDTO.class);
+        }
+        return dictProp;
+    }
+}

+ 13 - 0
micro-common/src/main/java/com/poyee/common/domain/entity/TzyCardTaskRemind.java

@@ -0,0 +1,13 @@
+package com.poyee.common.domain.entity;
+
+
+import lombok.Data;
+
+@Data
+public class TzyCardTaskRemind {
+
+    private String imgUrl;
+    //优惠券提醒表id
+    private Long id;
+
+}

+ 56 - 0
micro-common/src/main/java/com/poyee/common/domain/vo/AppActAdVO.java

@@ -0,0 +1,56 @@
+package com.poyee.common.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @Description  
+ * @Author  poyee
+ * @Date 2022-10-10 
+ */
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AppActAdVO implements Serializable {
+
+	private static final long serialVersionUID =  8207660194957131175L;
+
+	private Long id;
+
+	/**
+	 * 优惠劵id集合,多个逗号拼接
+	 */
+	private String couponIds;
+
+	/**
+	 * 活动图片
+	 */
+	private String actImg;
+	/**
+	 * 图片:img,视频:video,动图:gif
+	 */
+	private String imgType;
+
+	/**
+	 * 跳转链接
+	 */
+	private String actUrl;
+
+	/**
+	 * 点击区域,默认0,任意点击,1区域点击
+	 */
+	private Integer clickType;
+
+	/**
+	 * 持续时间,默认5秒
+	 */
+	private Integer lastTime;
+
+	private String description;
+}

+ 122 - 0
micro-common/src/main/java/com/poyee/common/domain/vo/AppActManageVO.java

@@ -0,0 +1,122 @@
+package com.poyee.common.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jdk.nashorn.internal.ir.annotations.Ignore;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description  
+ * @Author  poyee
+ * @Date 2022-08-03 
+ */
+
+@Data
+public class AppActManageVO implements Serializable {
+
+	private static final long serialVersionUID =  4351720037552230067L;
+
+	private Long id;
+
+	/**
+	 * 活动类型
+	 */
+	private String type;
+
+	/**
+	 * 子类型,point,times
+	 */
+	private String subType;
+
+	/**
+	 * 活动名称
+	 */
+	private String name;
+
+	/**
+	 * 活动图片
+	 */
+	private String imgUrl;
+
+	/**
+	 * 描述
+	 */
+	private String description;
+
+	/**
+	 * 积分要求
+	 */
+	private Integer point;
+
+	private String limitTimeType;
+
+	private Integer limitTime;
+
+	private Integer limitTimeNum;
+	/**每日限购总数*/
+	private Integer dayLimitNum;
+	/**
+	 * 商家id
+	 */
+	private Long merchantId;
+
+	/**
+	 * 商家name
+	 */
+	private String merchantName;
+
+	/**
+	 * 状态:1开启,0关闭
+	 */
+	private Integer status;
+
+
+	/**
+	 * 开始时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date startTime;
+
+	/**
+	 * 结束时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date endTime;
+
+   	//@Ignore
+	//private List<AppActPrizeDTO> prizeList;
+
+	/**用户余次数*/
+	@Ignore
+	private Integer userTimes;
+	/**初始赠送次数*/
+	private Integer defaultTimes;
+	/**排行榜奖励描述*/
+	private String rankPrizeImg;
+	/**最终大奖描述*/
+	private String lastPrizeDesc;
+	/**消耗积分类型,默认common:通用积分*/
+	private String pointType;
+	/**规则json配置*/
+	private String ruleConfig;
+	@Ignore
+	private Long actStartTimestamp;
+	@Ignore
+	private Long actEndTimestamp;
+
+	public Long getActStartTimestamp() {
+		if (startTime != null) {
+			return startTime.getTime();
+		}
+		return actStartTimestamp;
+	}
+
+	public Long getActEndTimestamp() {
+		if (endTime != null) {
+			return endTime.getTime();
+		}
+		return actEndTimestamp;
+	}
+}

+ 32 - 0
micro-common/src/main/java/com/poyee/common/domain/vo/AppCarouselPictureVO.java

@@ -0,0 +1,32 @@
+package com.poyee.common.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class AppCarouselPictureVO implements Serializable {
+
+    /** id */
+    private Long id;
+    /** 轮播图地址 */
+    private String path;
+
+    /** 描述 */
+    private String msg;
+
+    /** 跳转地址 */
+    private String redirectPath;
+    /**
+     * 类别
+     */
+    private String type;
+    /**
+     * 子类别
+     */
+    private String subType;
+    /**
+     * 轮播图名称
+     */
+    private String name;
+}

+ 179 - 0
micro-common/src/main/java/com/poyee/common/dto/AppUserInfoDto.java

@@ -0,0 +1,179 @@
+package com.poyee.common.dto;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.poyee.common.utils.Base64Util;
+import lombok.Data;
+import lombok.ToString;
+import org.slf4j.MDC;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+@ToString
+public class AppUserInfoDto implements Serializable {
+	private static final long serializableUID = 1L;
+	//id
+	private Integer id;
+	//openid
+	private String openid;
+	//unionid
+	private String unionid;
+	//账号
+	private String account;
+	//真实姓名
+	private String realname;
+	//昵称
+	private String nickname;
+	private String username;
+	//头像
+	private String avatar;
+	//会员等级
+	private Integer level;
+	//积分
+	private Long point;
+	//手机号
+	private String phone;
+	//邮箱
+	private String email;
+	//角色id
+	private Integer roleId;
+	//角色编码
+	private String rolecode;
+	//注册时间
+	private Date registerTime;
+	//注册渠道(用户类型) WX_WEB = 公众号, WX_APPLET = 小程序 , THIRD = 第三方
+	private String registerChannel;
+	//会员成长值
+	private Long growthNum;
+	//会员码
+	private String code;
+	/**
+	 * 是否接受通知
+	 */
+	private Integer notifyFlag;
+	/**
+	 * 极光推送
+	 */
+	private String smsRegisterId;
+	private String notifyType;
+	private Integer faceVerify;
+	/**
+	 * 支付开关,1开启,0关闭
+	 */
+
+	private Integer openPsd;
+	/**
+	 * 支付密码
+	 */
+	@JsonIgnore
+	private String loginPsd;
+	/**
+	 * 登陆密码
+	 */
+	@JsonIgnore
+	private String payPsd;
+	private Boolean payPsdExist;
+	private Boolean loginPsdExist;
+	private Integer refusePickUp;
+	private Integer num;
+	/**
+	 * 限额额度,默认1万,prop1字段
+	 */
+	private String payAmountOfDay;
+	/**
+	 * 开启限额,prop2字段
+	 */
+	private String openPayAmount;
+	/**
+	 * 悬浮窗口开关
+	 */
+	private Integer windowOpen;
+	/**
+	 * 身份证
+	 */
+	private String certName;
+	/**
+	 * 阿里账户
+	 */
+	private String alipayAccount;
+	/**
+	 * 1删除
+	 */
+	private Integer delFlg;
+	/**
+	 * 1开票权限
+	 */
+	private Integer openInvoice;
+	/**
+	 * 用户状态,正常:0,锁定:1,限购:2
+	 */
+	private Integer accountStatus;
+	/**
+	 * 可用支付类型
+	 */
+	private Integer blacklist;
+	private String idCard;
+	/**
+	 * 会员等级
+	 */
+	private Integer memberLevel;
+	/**
+	 * 会员名称
+	 */
+	private String memberName;
+	/**
+	 * 当月已获取成长值
+	 */
+	private Integer currentMonthGrowth;
+	/**
+	 * 月初初始化标志,默认0:未开始,1:已初始化
+	 */
+	private Integer memberInitFlag;
+	/**
+	 * 当前会员保级所需成长值
+	 */
+	private Integer memberKeepGrowth;
+
+	private boolean payInfoFlag;
+	private BigDecimal memberDiscount; // 会员折扣
+	//用户身份信息
+	@JsonIgnore
+	private String userCertData;
+	// open_card_show
+	private Integer openCardShow;
+
+	private String effectsType;
+
+	private Integer dailyLimit;
+	private Integer weeklyLimit;
+	private Integer monthlyLimit;
+	// 国际区号
+	private String diallingCode;
+	//商家拉黑类型:
+	private String merBackType;
+
+	@JsonIgnore
+	private Map<String, Object> baseUserHeader;
+
+	public Map<String, Object> getBaseUserHeader() {
+		JSONObject data = new JSONObject();
+		data.put("id", this.id);
+		data.put("nickname", this.nickname);
+		data.put("avatar", this.avatar);
+		data.put("tenantId", 1);
+		try {
+			String userStr = Base64Util.Base64Encode(data.toJSONString()).replaceAll("\r|\n", "");
+			Map<String, Object> header = new HashMap<>();
+			header.put("X-USER-BASE64", userStr);
+			header.put("TRACE_ID", MDC.get("TRACE_ID"));
+			return header;
+		} catch (Exception e) {
+		}
+		return null;
+	}
+}

+ 46 - 0
micro-common/src/main/java/com/poyee/common/dto/DictPropDTO.java

@@ -0,0 +1,46 @@
+package com.poyee.common.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author by po'yi
+ * @Classname DictPropDTO
+ * @Date 2023/7/24 11:29
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DictPropDTO implements Serializable {
+
+	/**开启时间,0-24小时*/
+	private Integer startTime=0;
+	/**结束时间,0-24小时*/
+	private Integer endTime=24;
+	/**指定组队类型,多个用逗号隔开*/
+	private String infoType;
+
+	private List<String> infoTypeList;
+	/**排除指定组队类型,多个用逗号隔开*/
+	private String unlessType;
+
+	private List<String> unlessTypeList;
+
+	public List<String> getUnlessTypeList() {
+		if(StringUtils.isNotEmpty(unlessType)){
+			return Arrays.asList(unlessType.split(","));
+		}
+		return unlessTypeList;
+	}
+
+	public List<String> getInfoTypeList() {
+		if(StringUtils.isNotEmpty(infoType)){
+			return Arrays.asList(infoType.split(","));
+		}
+		return infoTypeList;
+	}
+}

+ 166 - 0
micro-common/src/main/java/com/poyee/common/dto/InDto.java

@@ -0,0 +1,166 @@
+package com.poyee.common.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.poyee.common.exception.ServiceException;
+import com.poyee.common.utils.bean.DozerUtils;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 接口入参
+ */
+@Data
+@Slf4j
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class InDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+    //appid
+    private String appid;
+    //openid
+    private String openid;
+    //unionid
+    private String unionid;
+    //用户类型: WX_WEB (微信公众号) WX_APPLET (微信小程序) THIRD (第三方) WX_AUTH(微信授权登陆)
+    private String userType;
+    //userid
+    private Integer userId;
+    //账号
+    private String username;
+    //每页数据条数
+    private Integer pageSize =10;
+    //页码数
+    private Integer pageNo=1;
+    //其他数据
+    private Map<String,Object> data;
+    //部门id
+    private Integer departId;
+
+    private Integer offset;
+
+    private long timestamp;
+
+    private String version;
+    // 极光id
+    private String smsRegisterId;
+    //签名
+    private String sign;
+
+    public Object get(String key){
+        if(null != data && !data.isEmpty()){
+            return this.data.get(key);
+        }
+        return null;
+    }
+    public Object getDefault(String key,Object value){
+        if(null != data && !data.isEmpty()){
+            try{
+                return null == this.data.get(key) ? value : this.data.get(key);
+            }catch (Exception e){
+            }
+        }
+        return value;
+    }
+    public String getString(String key){
+        if(null != data && !data.isEmpty()&&this.data.containsKey(key)){
+            return null != this.data.get(key) ? String.valueOf(this.data.get(key)) : null;
+        }
+        return null;
+    }
+
+    public Boolean existKeyString(String key){
+        if(null != data && !data.isEmpty()&&this.data.containsKey(key)){
+            return true;
+        }
+        return false;
+    }
+
+    public Integer getIntegerParam(String key) {
+        if (CollectionUtils.isEmpty(data)) {
+            return null;
+        }
+        return (Integer) this.data.get(key);
+    }
+
+    public boolean getBooleanParam(String key) {
+        if (CollectionUtils.isEmpty(data)) {
+            return false;
+        }
+        Boolean b = (Boolean) this.data.get(key);
+        return b != null && b;
+    }
+
+    public String getStringDefault(String key,String value){
+        if(null != data && !data.isEmpty()){
+            try {
+                String ret = String.valueOf(this.data.get(key));
+                return StringUtils.isEmpty(ret) ? value : ("null".equals(ret) ? value : ret);
+            }catch (Exception e){}
+        }
+        return value;
+    }
+    public Integer getIntegerDefault(String key,Integer value){
+        if(null != data && !data.isEmpty()){
+            try {
+                Integer ret = (Integer) this.data.get(key);
+                return StringUtils.isEmpty(ret) ? value :  ret;
+            }catch (Exception e){
+            }
+        }
+        return value;
+    }
+    public InDto put(String key ,Object value){
+        if(null == this.data) this.data = new HashMap<>();
+        this.data.put(key, value);
+        return this;
+    }
+    public InDto remove(String key){
+        if(null != this.data && !this.data.isEmpty()){
+            this.data.remove(key);
+        }
+        return this;
+    }
+
+    public Integer getPageSize() {
+        if(this.pageSize == null){
+            return pageSize;
+        }
+        return this.pageSize>0? this.pageSize:10;
+    }
+
+    public Integer getPageNo() {
+        if(this.pageNo == null){
+            return pageNo;
+        }
+        return this.pageNo>0? this.pageNo:1;
+    }
+
+    public Integer getOffset(){
+        if(this.pageNo==null||this.pageSize==null){
+            return 0;
+        }
+        return((pageNo) - 1 ) * pageSize;
+    }
+
+    /**
+     * 转换indto中data为指定参数
+     *
+     * @param param
+     * @param <T>
+     * @return
+     */
+    public <T> T buildParam( T param) {
+        try {
+            DozerUtils.copy(this.data,param);
+            return param;
+        } catch (Exception e) {
+            log.error("参数转换失败:", e);
+        }
+        throw new ServiceException(500, "参数获取失败!");
+    }
+}

+ 184 - 0
micro-common/src/main/java/com/poyee/common/dto/OutDTO.java

@@ -0,0 +1,184 @@
+package com.poyee.common.dto;
+
+import com.poyee.common.constant.RetConstants;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 输出参数
+ */
+@Data
+@ToString
+public class OutDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private boolean success = true;
+
+    private Integer code = 0;
+
+    private String msg = "成功";
+
+    private Map<String ,Object> data;
+    //时间戳
+    private long timestamp = System.currentTimeMillis();
+    //数据总量
+    private Integer total;
+    //每页条数
+    private Integer pageSize = 10;
+    //页码
+    private Integer pageNo = 1;
+    //总页数
+    private Integer pages;
+    //
+    private String roleCode;
+
+    public OutDTO(){}
+
+    public OutDTO(boolean success, Integer code, String msg){
+        this.success =success;
+        this.code = code;
+        this.msg = msg;
+    }
+
+    /**
+     *
+     * @param pageSize 每页条数
+     * @param pageNo 页码
+     * @param total 总量
+     * @return
+     */
+    public OutDTO setCount(Integer pageSize ,Integer pageNo ,Integer total){
+        this.total = total;
+        this.pageSize = pageSize;
+        this.pageNo = pageNo;
+        if(total % pageSize > 0){
+            this.pages = total / pageSize + 1;
+        }else{
+            this.pages = total / pageSize;
+        }
+        return this;
+    }
+
+    /**
+     * @param inDto
+     * @param total
+     * 设置分页
+     * @return
+     */
+    public OutDTO setCount(InDto inDto,Integer total){
+        this.total = total;
+        this.pageSize = inDto.getPageSize();
+        this.pageNo = inDto.getPageNo();
+        if(total % this.pageSize > 0){
+            this.pages = total / this.pageSize + 1;
+        }else{
+            this.pages = total / this.pageSize;
+        }
+        return this;
+    }
+
+    public OutDTO page(InDto inDto,Integer total , String key, List datas){
+        OutDTO outDTO = this.setCount(inDto, total);
+        if(null != datas && datas.size() > 0 ){
+            if(datas.size() >= inDto.getPageSize() * inDto.getPageNo()){
+                datas = datas.subList(inDto.getPageSize() *(inDto.getPageNo()-1),inDto.getPageSize() *inDto.getPageNo() );
+            }else{
+                datas = datas.subList(inDto.getPageSize() *(inDto.getPageNo()-1),datas.size());
+            }
+        }
+        outDTO.put(key,datas);
+        return outDTO;
+    }
+
+    public OutDTO buildPage(InDto inDto,Integer total , String key, List datas){
+        OutDTO outDTO = this.setCount(inDto, total);
+        outDTO.put(key,datas);
+        return outDTO;
+    }
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public OutDTO put(String key,Object value){
+        if(null == this.data) this.data = new HashMap<>();
+        this.data.put(key,value);
+        return this;
+    }
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public OutDTO putString(String key,String value){
+        if(null == this.data) this.data = new HashMap<>();
+        this.data.put(key,value);
+        return this;
+    }
+
+    /**
+     *
+     * @param key
+     * @return
+     */
+    public Object get(String key){
+        if(null != this.data) return this.data.get(key);
+        return null;
+    }
+
+    /**
+     * get String
+     * @param key
+     * @return
+     */
+    public String getString(String key){
+        if(null != this.data)  return (String) this.data.get(key);
+        return null;
+    }
+
+    public static OutDTO ok(){
+        OutDTO outDTO = new OutDTO();
+        outDTO.put("ok","");
+        return outDTO;
+    }
+
+    public static OutDTO ok(String msg) {
+        return new OutDTO(true,0,msg);
+    }
+
+    public static OutDTO ok(Integer code ,String msg){
+        return new OutDTO(true,code,msg);
+    }
+
+    /**
+     * 失败
+     * @param code
+     * @param msg
+     * @return
+     */
+    public static OutDTO error(Integer code,String msg){
+        return new OutDTO(false,code,msg);
+    }
+
+    /**
+     *
+     * @param message
+     * @return
+     */
+    public static OutDTO error500(String message) {
+        return new OutDTO(false,500,message);
+    }
+
+
+    public static OutDTO errorRet(RetConstants retConstants) {
+        return new OutDTO(false, retConstants.getCode(), retConstants.getMessage());
+    }
+}

+ 32 - 0
micro-common/src/main/java/com/poyee/common/dto/UserInfo.java

@@ -0,0 +1,32 @@
+package com.poyee.common.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.github.dozermapper.core.Mapping;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author by po'yi
+ * @Classname UserInfo
+ * @Description 用户信息
+ * @Date 2022/8/18 15:46
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class UserInfo implements Serializable {
+	private Integer id;
+	/**昵称*/
+	private String nickname;
+	/**头像*/
+	private String avatar;
+	/**角色code*/
+	@Mapping("code")
+	private String roleCode;
+	private Integer merchantId;
+	private String merchantName;
+	private String merchantAvatar;
+	/**权限*/
+	private List<String> permissionsList;
+}

+ 19 - 0
micro-common/src/main/java/com/poyee/common/dto/qiniu/AntispamDTO.java

@@ -0,0 +1,19 @@
+package com.poyee.common.dto.qiniu;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author by po'yi
+ * @Classname scenesDTO
+ * @Date 2024/1/4 14:25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AntispamDTO implements Serializable {
+	private String suggestion;
+	private List<SceneDetailDTO> details;
+}

+ 22 - 0
micro-common/src/main/java/com/poyee/common/dto/qiniu/CensorDTO.java

@@ -0,0 +1,22 @@
+package com.poyee.common.dto.qiniu;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author by po'yi
+ * @Classname CensorDTO
+ * @Date 2022/7/12 16:32
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CensorDTO implements Serializable {
+	private  Integer code;
+	private  String message;
+	private  String entry_id;
+	//suggestion - pass
+	//private Map<String, Object> result;
+	private CensorResult result;
+}

+ 18 - 0
micro-common/src/main/java/com/poyee/common/dto/qiniu/CensorResult.java

@@ -0,0 +1,18 @@
+package com.poyee.common.dto.qiniu;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author by po'yi
+ * @Classname CensorResult
+ * @Date 2024/1/4 14:25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CensorResult implements Serializable {
+	private String suggestion;
+	private scenesDTO scenes;
+}

+ 18 - 0
micro-common/src/main/java/com/poyee/common/dto/qiniu/SceneDetailDTO.java

@@ -0,0 +1,18 @@
+package com.poyee.common.dto.qiniu;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author by po'yi
+ * @Classname scenesDTO
+ * @Date 2024/1/4 14:25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SceneDetailDTO implements Serializable {
+	private String label;
+	private float score;
+}

+ 17 - 0
micro-common/src/main/java/com/poyee/common/dto/qiniu/scenesDTO.java

@@ -0,0 +1,17 @@
+package com.poyee.common.dto.qiniu;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author by po'yi
+ * @Classname scenesDTO
+ * @Date 2024/1/4 14:25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class scenesDTO implements Serializable {
+	private AntispamDTO antispam;
+}

+ 55 - 0
micro-common/src/main/java/com/poyee/common/exception/ServiceException.java

@@ -0,0 +1,55 @@
+package com.poyee.common.exception;
+
+import java.util.Map;
+
+/**
+ * 业务异常
+ * 
+ * @author zheng
+ */
+public class ServiceException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    protected final String message;
+    protected int code=0;
+    /**特殊异常,抛出需要返回到前端的数据*/
+    protected Map<String, Object> data;
+
+    public ServiceException(String message)
+    {
+        this.code = -1;
+        this.message = message;
+    }
+
+    public ServiceException(int code, String message) {
+        this.message = message;
+        this.code = code;
+    }
+
+    public ServiceException(int code, String message, Map<String, Object> data) {
+        this.message = message;
+        this.code = code;
+        this.data = data;
+    }
+
+    public ServiceException(String message, Throwable e)
+    {
+        super(message, e);
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public int getCode()
+    {
+        return this.code;
+    }
+
+    public Map<String, Object> getData() {
+        return data;
+    }
+}

+ 65 - 0
micro-common/src/main/java/com/poyee/common/utils/Base64Util.java

@@ -0,0 +1,65 @@
+package com.poyee.common.utils;
+
+import sun.misc.BASE64Encoder;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+
+public class Base64Util {
+
+    public static byte[] decode(String encodedText){
+    /** 解码  */
+        final Base64.Decoder decoder = Base64.getDecoder();
+        return decoder.decode(encodedText);
+    }
+    public static byte[] decodeMime(String encodedText){
+    /** 解码  */
+        final Base64.Decoder decoder = Base64.getMimeDecoder();
+        return decoder.decode(encodedText);
+    }
+    /** 编码 */
+    public static String encode(byte[] data){
+        final Base64.Encoder encoder = Base64.getEncoder();
+        return encoder.encodeToString(data);
+    }
+
+    public static String Base64Encode(String str) throws UnsupportedEncodingException {
+        return new BASE64Encoder().encode(str.getBytes("UTF-8"));
+    }
+
+    /**
+     * 根据给定的 Base64 编码字符串中的换行符和特殊字符的存在情况,
+     * 自动选择使用 {@link Base64#getDecoder()} 或 {@link Base64#getMimeDecoder()}
+     * 来解码数据。
+     *
+     * @param encodedData 待解码的 Base64 编码字符串
+     * @return 解码后的原始二进制数据
+     */
+    public static byte[] decodeV2(String encodedData){
+        if (containsMimeSpecialChars(encodedData) || containsLineBreaks(encodedData)) {
+            return Base64.getMimeDecoder().decode(encodedData);
+        } else {
+            return Base64.getDecoder().decode(encodedData);
+        }
+    }
+
+    /**
+     * 检查给定的 Base64 编码字符串是否包含 MIME Base64 特有的 `-` 或 `_` 字符。
+     *
+     * @param encodedData 待检查的 Base64 编码字符串
+     * @return 若字符串包含 MIME 特殊字符,则返回 true;否则返回 false
+     */
+    private static boolean containsMimeSpecialChars(String encodedData) {
+        return encodedData.contains("-") || encodedData.contains("_");
+    }
+
+    /**
+     * 检查给定的 Base64 编码字符串是否包含换行符 (`\r` 或 `\n`)。
+     *
+     * @param encodedData 待检查的 Base64 编码字符串
+     * @return 若字符串包含换行符,则返回 true;否则返回 false
+     */
+    private static boolean containsLineBreaks(String encodedData) {
+        return encodedData.contains("\r") || encodedData.contains("\n");
+    }
+}

+ 595 - 0
micro-common/src/main/java/com/poyee/common/utils/DateUtils.java

@@ -0,0 +1,595 @@
+package com.poyee.common.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.poyee.common.constant.Constants;
+import com.poyee.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+/**
+ * 时间工具类
+ *
+ * @author zheng
+ */
+@Slf4j
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
+
+	public static String add = "ADD";
+	public static String cut = "CUT";
+	public static String year = "year";
+	public static String month = "month";
+	public static String day = "day";
+	public static String hour = "hour";
+	public static String minute = "minute";
+	public static String second = "second";
+	//秒/天
+	public static Integer day2second = 24 * 60 * 60;
+	//秒/小时
+	public static Integer hour2second = 1 * 60 * 60;
+	//秒/分钟
+	public static Integer minute2second = 1 * 60;
+
+
+	public static String YYYY = "yyyy";
+
+	private static String MM = "MM";
+
+	public static String YYYY_MM = "yyyy-MM";
+
+	public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+	public static String MM_DD = "MM.dd";
+
+    public static String YYYYMMDD = "yyyyMMdd";
+    public static String HHMMSS = "HHmmss";
+
+	public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+	public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+	private static JSONObject holiday = new JSONObject();
+
+	private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+	/**
+	 * 获取当前Date型日期
+	 *
+	 * @return Date() 当前日期
+	 */
+	public static Date getNowDate() {
+		return new Date();
+	}
+
+	/**
+	 * 获取当前日期, 默认格式为yyyy-MM-dd
+	 *
+	 * @return String
+	 */
+	public static String getDate() {
+		return dateTimeNow(YYYY_MM_DD);
+	}
+
+	public static final String getTime() {
+		return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+	}
+
+	public static final String dateTimeNow() {
+		return dateTimeNow(YYYYMMDDHHMMSS);
+	}
+
+	public static final String dateTimeNow(final String format) {
+		return parseDateToStr(format, new Date());
+	}
+
+	public static final String dateTime(final Date date) {
+		return parseDateToStr(YYYY_MM_DD, date);
+	}
+
+	public static final String parseDateToStr(final String format, final Date date) {
+		return new SimpleDateFormat(format).format(date);
+	}
+
+	public static final Date dateTime(final String format, final String ts) {
+		try {
+			if (StringUtils.isEmpty(ts)) return null;
+			return new SimpleDateFormat(format).parse(ts);
+		} catch (ParseException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 日期路径 即年/月/日 如2018/08/08
+	 */
+	public static final String datePath() {
+		Date now = new Date();
+		return DateFormatUtils.format(now, "yyyy/MM/dd");
+	}
+
+	/**
+	 * 日期路径 即年/月/日 如20180808
+	 */
+	public static final String dateTime() {
+		Date now = new Date();
+		return DateFormatUtils.format(now, "yyyyMMdd");
+	}
+
+	/**
+	 * 日期型字符串转化为日期 格式
+	 */
+	public static Date parseDate(Object str) {
+		if (str == null) {
+			return null;
+		}
+		try {
+			return parseDate(str.toString(), parsePatterns);
+		} catch (ParseException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * 获取服务器启动时间
+	 */
+	public static Date getServerStartDate() {
+		long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+		return new Date(time);
+	}
+
+	/**
+	 * 计算相差天数
+	 */
+	public static int differentDaysByMillisecond(Date date1, Date date2) {
+		return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+	}
+
+	/**
+	 * 是否时间
+	 * @param dateStr
+	 * @return
+	 */
+	public static boolean isDate(String dateStr , String format){
+		try{
+			Date date = dateTime(format, dateStr);
+			String endStr = parseDateToStr(format, date);
+			return endStr.equals(dateStr);
+		}catch (Exception e){
+
+		}
+		return false;
+	}
+
+	/**
+	 * 计算两个时间差
+	 */
+	public static String getDatePoor(Date endDate, Date nowDate) {
+		long nd = 1000 * 24 * 60 * 60;
+		long nh = 1000 * 60 * 60;
+		long nm = 1000 * 60;
+		// long ns = 1000;
+		// 获得两个时间的毫秒时间差异
+		long diff = endDate.getTime() - nowDate.getTime();
+		// 计算差多少天
+		long day = diff / nd;
+		// 计算差多少小时
+		long hour = diff % nd / nh;
+		// 计算差多少分钟
+		long min = diff % nd % nh / nm;
+		// 计算差多少秒//输出结果
+		// long sec = diff % nd % nh % nm / ns;
+		return day + "天" + hour + "小时" + min + "分钟";
+	}
+
+	/**
+	 * 计算两个时间差多少秒
+	 */
+	public static Long getMinPoorSec(Date endDate, Date nowDate) {
+		long nd = 1000 * 24 * 60 * 60;
+		long nh = 1000 * 60 * 60;
+		long nm = 1000 * 60;
+		long ns = 1000;
+		// 获得两个时间的毫秒时间差异
+		long diff = endDate.getTime() - nowDate.getTime();
+		// 计算差多少天
+		//long day = diff / nd;
+		// 计算差多少小时
+		//long hour = diff % nd / nh;
+		// 计算差多少分钟
+		//long min = diff % nd % nh / nm;
+		// 计算差多少秒//输出结果
+		return diff / ns;
+	}
+
+	/**
+	 * 时间操作
+	 *
+	 * @param date 时间
+	 * @param type 操作类型 年月日时分秒
+	 * @param num  数量
+	 * @return
+	 */
+	public static Date addCalendar(Date date, String type, Integer num) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		switch (type) {
+			case "year":
+				calendar.add(Calendar.YEAR, num);
+				break;
+			case "month":
+				calendar.add(Calendar.MONTH, num);
+				break;
+			case "day":
+				calendar.add(Calendar.DAY_OF_MONTH, num);
+				break;
+			case "hour":
+				calendar.add(Calendar.HOUR_OF_DAY, num);
+				break;
+			case "minute":
+				calendar.add(Calendar.MINUTE, num);
+				break;
+			case "second":
+				calendar.add(Calendar.SECOND, num);
+				break;
+		}
+		return calendar.getTime();
+	}
+
+	/**
+	 * 获取指定的工作日
+	 *
+	 * @param date
+	 * @param num
+	 * @return
+	 * @throws ParseException
+	 */
+	public static List<Date> getWorkDays(Date date, Integer num) throws ParseException {
+		List<Date> workdays = new ArrayList<>();
+		for (int i = 0; i < num; i++) {
+			date = getNextWorkDay(date);
+			workdays.add(date);
+		}
+		return workdays;
+	}
+
+	/**
+	 * 获取指定工作天数后的工作日
+	 *
+	 * @param date
+	 * @param num
+	 * @return
+	 * @throws ParseException
+	 */
+	public static Date getAfterNumWorkDay(Date date, Integer num) throws ParseException {
+		for (int i = 0; i < num; i++) {
+			date = getNextWorkDay(date);
+		}
+		return date;
+	}
+
+	/**
+	 * 获取当前时间的下一个工作日
+	 *
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static Date getNextWorkDay(Date date) throws ParseException {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		Date nextDate = getNextDate(calendar);
+		if (!isWeekend(nextDate)) {
+			return nextDate;
+		} else {
+			return getNextWorkDay(nextDate);
+		}
+	}
+
+	public static Timestamp getTimestampNow() {
+		return Timestamp.valueOf(LocalDateTime.now());
+	}
+
+	/**
+	 * 获取下一日期
+	 *
+	 * @param calendar
+	 * @return
+	 */
+	public static Date getNextDate(Calendar calendar) {
+		calendar.add(Calendar.DAY_OF_MONTH, +1);
+		return calendar.getTime();
+	}
+
+	/**
+	 * 是否是 休息日
+	 *
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static boolean isWeekend(Date date) throws ParseException {
+		//判断当前时间是否在holidays 内
+		String dateTimes = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, date);
+		try {
+			String type = holiday.getString(dateTimes);
+			if (StringUtils.isNotBlank(type) && Objects.equals(type, "休")) {
+				return true;
+			}
+			//判断是否上班 如果上班则不进行 下面周六周日计算
+			if (StringUtils.isNotBlank(type) && Objects.equals(type, "班")) {
+				return false;
+			}
+		}catch (Exception e){
+			log.error(" 获取 holiday error:{}", e.getMessage());
+		}
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * 获取指定时间的开始时间
+	 *
+	 * @param date
+	 * @return
+	 */
+	public static Date getStartTimeByDate(Date date) {
+		if (null == date) date = new Date();
+		return parseDate(dateTime(date));
+	}
+
+	/**
+	 * 获取指定时间的开始时间
+	 *
+	 * @param date
+	 * @return
+	 */
+	public static Date getEndTimeByDate(Date date) {
+		if (null == date) date = new Date();
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		Date nextDate = getNextDate(calendar);
+		date = parseDate(dateTime(nextDate));
+		calendar.setTime(date);
+		calendar.add(Calendar.SECOND, -1);
+		return calendar.getTime();
+	}
+
+	/**
+	 * 根据身份证号判断是否未成年
+	 *
+	 * @param certNo 身份证号
+	 * @return
+	 */
+	public static boolean isMinor(String certNo) {
+		if (certNo.length() != 18) {
+			throw new ServiceException(500, "您好,暂时仅支持二代身份证校验!");
+		}
+
+		int year = Integer.valueOf(certNo.substring(6).substring(0, 4));// 得到年份
+		int month = Integer.valueOf(certNo.substring(10).substring(0, 2));// 得到月份
+		int day = Integer.valueOf(certNo.substring(12).substring(0, 2));//得到日
+
+		LocalDate today = LocalDate.now();
+		//System.out.println("Today : " + today);
+		LocalDate birthDate = LocalDate.of(year, month, day);
+		// System.out.println("BirthDate : " + birthDate);
+		Period p = Period.between(birthDate, today);
+		//System.out.printf("年龄 : %d 年 %d 月 %d 日", p.getYears(), p.getMonths(), p.getDays());
+
+		return p.getYears() >= 18 && p.getYears() < 70;
+	}
+
+	/**
+	 * 获取指定几天后的日期
+	 * @param date 当前日期
+	 * @param day 几天后的日期
+	 * @return
+	 */
+	public static Date getFutureDate(Date date,int day) {
+		Calendar calc =Calendar.getInstance();
+		calc.setTime(date);
+		calc.add(Calendar.DATE, day);
+		return calc.getTime();
+	}
+
+	public static int getCurrentHour() {
+		Calendar calc =Calendar.getInstance();
+		return calc.get(Calendar.HOUR_OF_DAY);
+	}
+
+	public static int getCurrentDate() {
+		Calendar calc =Calendar.getInstance();
+		return calc.get(Calendar.DATE);
+	}
+
+	public static boolean isFirDayOfMonth(){
+		return getCurrentDate()==1;
+	}
+
+
+	/**
+	 * 转换ISO日期格式
+	 * @param date
+	 * @return
+	 */
+	public static String tranISOStr(Date date) {
+		//当前时间转IS0 8601
+		TimeZone tz = TimeZone.getTimeZone("GMT-01");
+		DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+		df.setTimeZone(tz);
+		return df.format(date);
+	}
+
+
+	/**
+	 * 比较2个时间相隔几天
+	 * @param befDate
+	 * @param aftDate
+	 * @return
+	 */
+	public static int compareDate(Date befDate,Date aftDate) {
+		int days = (int) ((aftDate.getTime() - befDate.getTime()) / (1000*3600*24));
+		return days;
+	}
+
+	/**
+	 * 计算相差分钟
+	 */
+	public static int differentMinutesByMillisecond(Date date1, Date date2) {
+		return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 60)));
+	}
+
+	/**
+	 * 计算相差秒数
+	 */
+	public static int differentSecond(Date date1, Date date2) {
+		return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 )));
+	}
+
+	/**
+	 * 获取本月第一天
+	 * @return
+	 */
+	public static Date getFirstDayOfMonth(){
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(new Date());
+		cal.set(Calendar.DAY_OF_MONTH, 1);
+		return parseDate(DateUtils.parseDateToStr(YYYY_MM_DD,cal.getTime()));
+	}
+
+	/**
+	 * 获取上个月第X天
+	 * @return
+	 */
+	public static Date getLastMonthDay(int day){
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(new Date());
+		cal.add(Calendar.MONTH, -1);
+		cal.set(Calendar.DAY_OF_MONTH, day);
+		return parseDate(DateUtils.parseDateToStr(YYYY_MM_DD,cal.getTime()));
+	}
+
+	// 上个月
+	public static String getLastMonthStr(){
+		// 获取当前日期
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(new Date());
+		calendar.add(Calendar.MONTH, -1);
+		return DateUtils.parseDateToStr(YYYY_MM, calendar.getTime());
+	}
+
+	/**
+	 * 获取X个月第X天
+	 * @return
+	 */
+	public static Date getLastByMonthDay(int month, int day){
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(new Date());
+		cal.add(Calendar.MONTH, month);
+		cal.set(Calendar.DAY_OF_MONTH, day);
+		return parseDate(DateUtils.parseDateToStr(YYYY_MM_DD,cal.getTime()));
+	}
+
+	public static Date getDateByDay(int day){
+		// 获取当前日期
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(new Date());
+		calendar.add(Calendar.DAY_OF_MONTH, day);
+		return parseDate(DateUtils.parseDateToStr(YYYY_MM_DD, calendar.getTime()));
+	}
+
+	/**
+	 * data转LocalDateTime
+	 * @param date
+	 * @return
+	 */
+	public static LocalDateTime toLocalDateTime(Date date) {
+		return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
+	}
+
+	/**
+	 * 2个时间间隔天数
+	 * @param dateBef
+	 * @param dateAft
+	 * @return
+	 */
+	public static long intervalDayOfDays(Date dateBef, Date dateAft) {
+		return ChronoUnit.DAYS.between(toLocalDateTime(dateBef), toLocalDateTime(dateAft));
+	}
+
+	/**
+	 * 间隔小时
+	 * @param dateBef
+	 * @param dateAft
+	 * @return
+	 */
+	public static double intervalHourOfDays(Date dateBef, Date dateAft) {
+		//return ChronoUnit.HOURS.between(toLocalDateTime(dateBef), toLocalDateTime(dateAft));
+		if (dateBef == null || dateAft == null) {
+			throw new IllegalArgumentException("时间不能为空");
+		}
+
+		long millisDiff = dateAft.getTime() - dateBef.getTime();
+		return millisDiff / (1000.0 * 60 * 60); // 毫秒转小时,保留小数
+	}
+
+	/**
+	 * 获取当前月和日 格式 5.14
+	 * @return
+	 */
+	public static String getCurMonthDay() {
+		Calendar calendar = Calendar.getInstance();
+		int month = calendar.get(Calendar.MONTH) + 1;
+		int day = calendar.get(Calendar.DAY_OF_MONTH);
+		return month+ Constants.dot +day;
+	}
+
+	/**
+	 * 判断生日是否小于18岁
+	 * @param birthDate
+	 * @return
+	 */
+	public static boolean isUnder18(Date birthDate) {
+		if (birthDate == null) {
+			throw new IllegalArgumentException("Birth date cannot be null");
+		}
+
+		// 获取当前日期
+		Calendar today = Calendar.getInstance();
+
+		// 获取出生日期
+		Calendar birthDay = Calendar.getInstance();
+		birthDay.setTime(birthDate);
+
+		// 计算年龄
+		int age = today.get(Calendar.YEAR) - birthDay.get(Calendar.YEAR);
+
+		// 如果当前日期还未到出生月份,或者同月份但日期未到,年龄减一
+		if (today.get(Calendar.MONTH) < birthDay.get(Calendar.MONTH) || (today.get(Calendar.MONTH) == birthDay.get(Calendar.MONTH) && today.get(Calendar.DAY_OF_MONTH) < birthDay.get(Calendar.DAY_OF_MONTH))) {
+			age--;
+		}
+
+		// 判断是否小于 18 岁
+		return age < 18;
+	}
+
+    public static boolean isBefore(Date registerTime, Date date) {
+		return registerTime.before(date);
+    }
+}

+ 12 - 0
micro-common/src/main/java/com/poyee/common/utils/HostPropertyDefiner.java

@@ -0,0 +1,12 @@
+package com.poyee.common.utils;
+
+import ch.qos.logback.core.PropertyDefinerBase;
+
+public class HostPropertyDefiner extends PropertyDefinerBase {
+
+    @Override
+    public String getPropertyValue() {
+        return IpUtils.getHostName();
+    }
+
+}

+ 209 - 0
micro-common/src/main/java/com/poyee/common/utils/IpUtils.java

@@ -0,0 +1,209 @@
+package com.poyee.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 获取IP方法
+ * 
+ * @author zheng
+ */
+@Slf4j
+public class IpUtils
+{
+    public static String getIpAddr(HttpServletRequest request) {
+        if (request == null) {
+            return "unknown";
+        }
+
+        String ip = request.getHeader("x-forwarded-for");
+        //log.info("x-forwarded-for:{}",ip);
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+            //log.info("Proxy-Client-IP:{}",ip);
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Forwarded-For");
+            //log.info("X-Forwarded-For:{}",ip);
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+            //log.info("WL-Proxy-Client-IP:{}",ip);
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("remoteip");
+            //log.info("remoteip:{}",ip);
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+            //log.info("getRemoteAddr:{}",ip);
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Real-IP");
+            //log.info("X-Real-IP:{}",ip);
+        }
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+    }
+
+    public static boolean internalIp(String ip)
+    {
+        byte[] addr = textToNumericFormatV4(ip);
+        return internalIp(addr) || "127.0.0.1".equals(ip);
+    }
+
+    private static boolean internalIp(byte[] addr)
+    {
+        if (StringUtils.isNull(addr) || addr.length < 2)
+        {
+            return true;
+        }
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        switch (b0)
+        {
+            case SECTION_1:
+                return true;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4)
+                {
+                    return true;
+                }
+            case SECTION_5:
+                switch (b1)
+                {
+                    case SECTION_6:
+                        return true;
+                }
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * 将IPv4地址转换成字节
+     * 
+     * @param text IPv4地址
+     * @return byte 字节
+     */
+    public static byte[] textToNumericFormatV4(String text)
+    {
+        if (text.length() == 0)
+        {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try
+        {
+            long l;
+            int i;
+            switch (elements.length)
+            {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L)) {
+                        return null;
+                    }
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L)) {
+                        return null;
+                    }
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+        return bytes;
+    }
+
+    public static String getHostIp()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostAddress();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "127.0.0.1";
+    }
+
+    public static String getHostName()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostName();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "未知";
+    }
+
+    public static String getRealIp(){
+        String ipAddr = getIpAddr(ServletUtils.getRequest());
+        if(StringUtils.isNotEmpty(ipAddr)) {
+            String[] ipArray = ipAddr.split(",");
+            String ip = ipArray[0];
+            return ip;
+        }
+        return null;
+    }
+}

+ 181 - 0
micro-common/src/main/java/com/poyee/common/utils/ServletUtils.java

@@ -0,0 +1,181 @@
+package com.poyee.common.utils;
+
+import com.poyee.common.domain.Convert;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+ * 客户端工具类
+ * 
+ * @author zheng
+ */
+public class ServletUtils
+{
+    /**
+     * 定义移动端请求的所有可能类型
+     */
+    private final static String[] agent = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     * 
+     * @param response 渲染对象
+     * @param string 待渲染的字符串
+     * @return null
+     */
+    public static String renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.indexOf("application/json") != -1)
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 判断User-Agent 是不是来自于手机
+     */
+    public static boolean checkAgentIsMobile(String ua)
+    {
+        boolean flag = false;
+        if (!ua.contains("Windows NT") || (ua.contains("Windows NT") && ua.contains("compatible; MSIE 9.0;")))
+        {
+            // 排除 苹果桌面系统
+            if (!ua.contains("Windows NT") && !ua.contains("Macintosh"))
+            {
+                for (String item : agent)
+                {
+                    if (ua.contains(item))
+                    {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return flag;
+    }
+
+    public static String getXUSERBASE64()
+    {
+        HttpServletRequest request = getRequestAttributes().getRequest();
+        String header = request.getHeader("X-USER-BASE64");
+        if(StringUtils.isEmpty(header)){
+            header = request.getHeader("Authorization");
+            if(StringUtils.isNotEmpty(header) && header.startsWith("Bearer ")){
+                header = header.replace("Bearer ","");
+            }
+        }
+        return header;
+    }
+
+
+
+}

+ 500 - 0
micro-common/src/main/java/com/poyee/common/utils/StringUtils.java

@@ -0,0 +1,500 @@
+package com.poyee.common.utils;
+
+
+import com.poyee.common.domain.StrFormatter;
+
+import java.security.SecureRandom;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Random;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串工具类
+ *
+ * @author zheng
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    public static final String NULLSTR = "";
+
+    /** 下划线 */
+    public static final char SEPARATOR = '_';
+
+    public static final String CHINESE_ENGLISH_DIGITS_PATTERN = "[\\p{IsHan}A-Za-z0-9]+";
+    private static final SecureRandom RANDOM = new SecureRandom();
+    /**
+     * 检查传入的内容是否仅包含中文、英文和数字。
+     *
+     * @param content 需要检查的内容。
+     * @return 返回{@code true}如果内容只包含中文、英文和数字,否则返回{@code false}。
+     */
+    public static boolean isValidChineseEnglishOnly(String content) {
+        return content != null && Pattern.compile(CHINESE_ENGLISH_DIGITS_PATTERN).matcher(content).matches();
+    }
+
+    /**
+     * 获取参数不为空值
+     *
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     *
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     *
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     *
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     *
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     *
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     *
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     *
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 下划线转驼峰命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     *
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     *
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法
+     * 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+
+    //public static void main(String[] args) {
+    //    boolean result= Pattern.compile(Constants.NUM_REG).matcher("12333").find();
+    //    System.out.println(result);
+    //}
+
+    /**
+     * 姓名脱敏
+     * @param name 姓名
+     * @param len 从第几个开始脱敏
+     * @return
+     */
+    public static String nameDesensitization(String name, int len){
+        if(StringUtils.isEmpty(name)) {
+            return name;
+        }
+        String prefix = name.substring(0, len);
+
+        return prefix + "***";
+    }
+
+    public static String desenstiseStr(String params,int atLength){
+        if(StringUtils.isEmpty(params)){
+            return null;
+        }
+        params = params.replaceAll("\\*", "0");
+        int strLength = params.length();
+        if(strLength <= atLength){
+            return params;
+        }
+        int i = strLength - atLength;
+        char[] chars = new char[i];
+        return params.replaceAll("\\w*(\\w{"+atLength+"})",new String(chars).replace(chars[0], '*')+"$1");
+    }
+    public static String generateRandomStr() {
+        String CHARACTERS =
+                "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz";
+        StringBuilder sb = new StringBuilder(6);
+        for (int i = 0; i < 6; i++) {
+            int index = RANDOM.nextInt(CHARACTERS.length());
+            sb.append(CHARACTERS.charAt(index));
+        }
+        return sb.toString();
+    }
+    public static String desensitizeName(String name) {
+        // 如果姓名为空或长度小于4,不处理
+        if (name == null || name.length() < 4) {
+            return name;
+        }
+
+        int length = name.length();
+
+        if (length == 4) {
+            // 姓名正好是4个字,返回前两个字 + "***" + 后两个字
+            return name.substring(0, 2) + "***" + name.substring(2);
+        } else {
+            // 否则,返回前两个字 + "***" + 最后两个字
+            return name.substring(0, 2) + "***" + name.substring(length - 2);
+        }
+    }
+    /**
+     * 获取长度为 N 的随机字母+数字
+     * @return 随机数字
+     */
+    public static String getRandomNumber(int len) {
+        final String SYMBOLS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // 数字和26个字母组成
+        final Random RANDOM = new SecureRandom();
+        char[] nonceChars = new char[len];  //指定长度为N位/自己可以要求设置
+
+        for (int index = 0; index < nonceChars.length; ++index) {
+            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
+        }
+        return new String(nonceChars);
+    }
+}

+ 129 - 0
micro-common/src/main/java/com/poyee/common/utils/UserUtils.java

@@ -0,0 +1,129 @@
+package com.poyee.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.poyee.common.config.CommonConfig;
+import com.poyee.common.dto.UserInfo;
+import com.poyee.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author by po'yi
+ * @Classname UserUtils
+ * @Description 用户工具类
+ * @Date 2022/8/30 10:56
+ */
+@Slf4j
+public class UserUtils {
+
+	/**
+	 * 查询请求头中用户部分信息
+	 * 该方法不接受任何参数,通过读取请求头中的"X-USER-BASE64"字段,获取用户信息的Base64编码字符串。
+	 * 对该字符串进行解码,并尝试将其转换为UserInfo对象返回。
+	 * 如果无法解码或转换失败,则返回null。
+	 *
+	 * @return UserInfo 如果成功解析用户信息,则返回UserInfo对象;否则返回null。
+	 */
+	public static UserInfo getSimpleUserInfo() {
+		String userInfoStr = ServletUtils.getRequest().getHeader("X-USER-BASE64");
+		log.debug("请求用户信息base64:{}", userInfoStr);
+		if (StringUtils.isEmpty(userInfoStr)) {
+			return null;
+		}
+		try {
+			String user = new String(Base64Util.decodeV2(userInfoStr));
+			log.debug("请求用户:{}", user);
+			return JSON.parseObject(user, UserInfo.class);
+		} catch (IllegalArgumentException | IllegalStateException e) {
+			log.error("请求用户信息base64解析异常:{}", userInfoStr, e);
+			throw new ServiceException("用户信息格式错误!");
+		} catch (Exception e) {
+			log.error("请求用户信息base64解析异常: {}", userInfoStr, e);
+			throw new ServiceException("系统异常!");
+		}
+	}
+
+	/**
+	 * 仅用于开发环境获取简化的用户信息。
+	 * @param isNeedLogin 是否需要登录。如果为true,则必须提供有效的用户信息;如果为false,则可以返回null或默认用户信息。
+	 * @return UserInfo 对象,包含用户信息。如果环境配置为生产环境且需要登录,但未提供用户信息,则抛出用户不存在异常。
+	 * 在开发环境中,如果未提供用户信息且需要登录,则返回默认用户信息;如果不需要登录,则返回null。
+	 * 解析用户信息时,如果遇到任何异常,都将抛出相应错误。
+	 */
+	public static UserInfo getSimpleUserInfo(boolean isNeedLogin) {
+		String userInfoStr = ServletUtils.getRequest().getHeader("X-USER-BASE64");
+		log.debug("请求用户信息base64:{}", userInfoStr);
+		if (StringUtils.isEmpty(userInfoStr)) {
+			if (CommonConfig.isProdEnv() && isNeedLogin) {
+				throw new ServiceException(500, "用户不存在!");
+			}
+			if (CommonConfig.isDevEnv() && isNeedLogin) {
+				return getDefaultUserInfo();
+			}
+			return null;
+		}
+
+		try {
+			String user = new String(Base64Util.decodeV2(userInfoStr),StandardCharsets.UTF_8);
+			log.debug("请求用户:{}", user);
+			return JSON.parseObject(user, UserInfo.class);
+		} catch (IllegalArgumentException | IllegalStateException e) {
+			log.error("请求用户信息base64解析异常:{}", userInfoStr, e);
+			throw new ServiceException("用户信息格式错误!");
+		} catch (Exception e) {
+			log.error("未知异常: {}", userInfoStr, e);
+			throw new ServiceException("系统异常!");
+		}
+	}
+
+	private static UserInfo getDefaultUserInfo() {
+		//必须登陆
+		UserInfo userInfo = new UserInfo();
+		userInfo.setNickname("yu");
+		userInfo.setMerchantName("HStest105");
+		userInfo.setRoleCode("shipping");
+		userInfo.setRoleCode("admin");
+		userInfo.setMerchantId(105);
+		userInfo.setId(26961);
+		//userInfo.setMerchantId(105);
+		userInfo.setMerchantId(181);
+		//userInfo.setMerchantId(13);
+		//userInfo.setId(15160);
+		//userInfo.setMerchantId(181);
+		//userInfo.setId(15167);
+		//userInfo.setId(15261);
+		//userInfo.setId(2442);
+		//userInfo.setId(15400);
+		userInfo.setId(2442);
+		return userInfo;
+	}
+
+	/**
+	 * 用户昵称脱敏
+	 * @param input
+	 * @return
+	 */
+	public static String hideUserPhone(String input) {
+		if (StringUtils.isEmpty(input)) {
+			return "匿名用户";
+		}
+		// 如果是手机号 (11 位数字)
+		if (input.matches("\\d{11}")) {
+			return input.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
+		}
+
+		// 如果是邮箱,格式通常为 xxx@xxx.com
+		if (input.matches("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
+			// 只脱敏@前面的部分,保留前三个字符
+			return input.replaceAll("^(\\w{3})\\w+(@.*$)", "$1****$2");
+		}
+
+		// 如果是纯数字(不包含其他字符),并且长度大于等于 4
+		if (input.matches("\\d+") && input.length() >= 4) {
+			// 保留前3位,后4位,其他的替换为****
+			return input.replaceAll("(\\d{3})\\d+(\\d{4})", "$1****$2");
+		}
+		return input;
+	}
+}

+ 67 - 0
micro-common/src/main/java/com/poyee/common/utils/bean/DozerUtils.java

@@ -0,0 +1,67 @@
+package com.poyee.common.utils.bean;
+
+import com.github.dozermapper.core.DozerBeanMapperBuilder;
+import com.github.dozermapper.core.Mapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class DozerUtils {
+
+    /**
+     * commonMapper,如果没有传mapper过来,默认使用这个
+     * dozer/dozer-mapping.xml 是相对resources目录的路径
+     */
+    public static Mapper  mapper = DozerBeanMapperBuilder.create()
+            .withMappingFiles("dozer/dozer-mapping.xml")
+            .build();
+
+    /**
+     * 单个对象转换
+     * 传入需要转换的对象,返回转换后的对象
+     * 用法:CommonDozerUtil.map(dto,Destination.class)
+     *
+     * @param source           源对象
+     * @param destinationClass
+     * @param <T>
+     * @return
+     */
+    public static <T> T map(Object source, Class<T> destinationClass) {
+        if (source != null) {
+            return mapper.map(source, destinationClass);
+        }
+        return null;
+    }
+
+    /**
+     * list转换
+     * 用法:CommonDozerUtil.mapList(list,Destination.class)
+     *
+     * @param sourceList
+     * @param destinationClass
+     * @param <T>
+     * @return
+     */
+    public static <T> List<T> mapList(Collection<?> sourceList, Class<T> destinationClass) {
+        List<T> destinationList = new ArrayList<>();
+        if (sourceList != null && sourceList.size() > 0) {
+            for (Object sourceObject : sourceList) {
+                T destinationObject = map(sourceObject, destinationClass);
+                destinationList.add(destinationObject);
+            }
+        }
+        return destinationList;
+    }
+
+    /**
+     * 将对象A的值拷贝到对象B中
+     *
+     * @param source            对象A
+     * @param destinationObject 对象B
+     */
+    public static void copy(Object source, Object destinationObject) {
+        mapper.map(source, destinationObject);
+    }
+
+}

+ 36 - 0
micro-common/src/main/java/com/poyee/common/utils/bean/JSONTools.java

@@ -0,0 +1,36 @@
+package com.poyee.common.utils.bean;
+
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+
+import java.util.List;
+
+public class JSONTools {
+
+	public static String obj2json(Object obj){
+		return JSON.toJSONString(obj);
+	}
+
+	public static Object jsonStr2obj(String json){
+		return JSON.parse(json);
+	}
+
+	public static <T> T  jsonStr2obj(String json,Class<T> classes){
+		return JSON.parseObject(json, classes);
+	}
+
+
+	public static JSONObject parseObject(String json){
+		return JSON.parseObject(json);
+	}
+
+	public static <T> List<T> parseObjectList(String json, Class<T> classes) {
+		return JSON.parseArray(json, classes);
+	}
+
+	public static List<JSONObject> toJsonObjectList(String json) {
+		return JSON.parseArray(json, JSONObject.class);
+	}
+
+}

+ 35 - 0
micro-dao/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>com.poyee</groupId>
+        <artifactId>poyee-micro</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>micro-dao</artifactId>
+    <version>1.0.0</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.poyee</groupId>
+            <artifactId>micro-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 13 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/AppActPrizeRecordMapper.java

@@ -0,0 +1,13 @@
+package com.poyee.dao.mapper;
+
+import com.poyee.common.domain.entity.ActCountParam;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ * 
+ * @author tencheer
+ * @date 2022-08-04
+ */
+public interface AppActPrizeRecordMapper {
+    int getActCount(ActCountParam countParam);
+}

+ 24 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/AppCarouselPictureMapper.java

@@ -0,0 +1,24 @@
+package com.poyee.dao.mapper;
+
+import com.poyee.common.domain.entity.AppCarouselPicture;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 轮播图Mapper接口
+ * 
+ * @author tencheer
+ * @date 2021-07-09
+ */
+public interface AppCarouselPictureMapper 
+{
+    /**
+	 * 查询首页banner
+	 *
+	 * @param types
+	 * @param isLimit
+	 * @return
+	 */
+	List<AppCarouselPicture> getBanner(@Param("list") List<String> types, @Param("isLimit")boolean isLimit);
+}

+ 14 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/AppCategoryPaymentMapper.java

@@ -0,0 +1,14 @@
+package com.poyee.dao.mapper;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ * 
+ * @author tencheer
+ * @date 2023-05-20
+ */
+public interface AppCategoryPaymentMapper {
+
+	List<Long> getUserIdByCatId(Long catId);
+}

+ 21 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/BaseApiMapper.java

@@ -0,0 +1,21 @@
+package com.poyee.dao.mapper;
+
+import com.poyee.common.domain.entity.AppActConfig;
+import com.poyee.common.domain.entity.AppVersionParam;
+import com.poyee.common.domain.entity.ApplicationInfo;
+import com.poyee.common.dto.AppUserInfoDto;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface BaseApiMapper {
+    ApplicationInfo selectNextVersionApp(AppVersionParam applicationInfo);
+
+    List<AppActConfig> selectAppActConfig();
+
+    int getOrderCountByTime(@Param("userId") Integer userId, @Param("historyLimitDay") int historyLimitDay);
+
+    AppUserInfoDto searchUserInfoById(@Param("id") Integer id);
+
+    int countUserCardRecord(@Param("userId") Integer userId, @Param("couponIds") List<String> couponIds);
+}

+ 5 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/GroupApiMapper.java

@@ -0,0 +1,5 @@
+package com.poyee.dao.mapper;
+
+public interface GroupApiMapper {
+    String findOneRateGroupPic();
+}

+ 23 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/SysDictDataMapper.java

@@ -0,0 +1,23 @@
+package com.poyee.dao.mapper;
+
+import com.poyee.common.domain.entity.SysDictData;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 字典表 数据层
+ *
+ * @author zheng
+ */
+@Mapper
+public interface SysDictDataMapper {
+
+    /**
+     * 根据字典类型查询字典数据
+     *
+     * @param dictType 字典类型
+     * @return 字典数据集合信息
+     */
+    public List<SysDictData> selectDictDataByType(String dictType);
+}

+ 13 - 0
micro-dao/src/main/java/com/poyee/dao/mapper/TzyCardTaskRemindMapper.java

@@ -0,0 +1,13 @@
+package com.poyee.dao.mapper;
+
+import com.poyee.common.domain.entity.TzyCardTaskRemind;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface TzyCardTaskRemindMapper {
+
+    List<TzyCardTaskRemind> getRemindByUserId(Integer userId);
+
+    int updateRemind(@Param("ids") List<Long> ids);
+}

+ 27 - 0
micro-dao/src/main/resources/mapper/AppActPrizeRecordMapper.xml

@@ -0,0 +1,27 @@
+<?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.poyee.dao.mapper.AppActPrizeRecordMapper">
+
+    <select id="getActCount" parameterType="object" resultType="int">
+        SELECT count(0) FROM app_act_prize_record
+        <where>
+            <if test="actId!=null"> and act_id = #{actId} </if>
+            <if test="curDay"> and create_time>=CURRENT_DATE </if>
+            <if test="startHour!=null"> and create_time >= (select date_trunc('HOUR',current_date) + #{startHour}*interval '1 HOUR' )</if>
+            <if test="endHour!=null"> and create_time &lt; (select date_trunc('HOUR',current_date) + #{endHour}*interval '1 HOUR' )</if>
+            <if test="startTime!=null"> and create_time >= #{startTime} </if>
+            <if test="endTime!=null"> and create_time &lt; #{endTime} </if>
+            <if test="refId!=null"> and base_order_id =#{refId}</if>
+            <if test="userId!=null"> and user_id =#{userId}</if>
+            <if test="excludeShare"> and share_user_id is null</if>
+            <if test="onlyShare"> and share_user_id is not null</if>
+            <if test="userAndShare"> and (share_user_id = #{shareUserId} or ( user_id = #{shareUserId} and share_user_id is not null ) )</if>
+            <if test="actType!=null and actType!=''">
+                and act_id in (SELECT id FROM app_act_manage WHERE type=#{actType} and status=1)
+            </if>
+        </where>
+    </select>
+
+</mapper>

+ 42 - 0
micro-dao/src/main/resources/mapper/AppCarouselPictureMapper.xml

@@ -0,0 +1,42 @@
+<?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.poyee.dao.mapper.AppCarouselPictureMapper">
+    
+    <resultMap type="AppCarouselPicture" id="AppCarouselPictureResult">
+        <result property="id"    column="id"    />
+        <result property="appid"    column="appid"    />
+        <result property="sort"    column="sort"    />
+        <result property="path"    column="path"    />
+        <result property="msg"    column="msg"    />
+        <result property="redirectPath"    column="redirect_path"    />
+        <result property="remark"    column="remark"    />
+        <result property="status"    column="status"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="departId"    column="depart_id"    />
+        <result property="startTime"    column="start_time"    />
+        <result property="endTime"    column="end_time"    />
+        <result property="type"    column="type"    />
+        <result property="subType"    column="sub_type"    />
+        <result property="name"    column="name"    />
+        <result property="description"    column="description"    />
+    </resultMap>
+
+    <select id="getBanner"  resultMap="AppCarouselPictureResult">
+        select path, redirect_path,type,msg,sub_type,id,name,description
+        from app_carousel_picture
+        WHERE now() BETWEEN start_time and end_time and status= 0
+        <if test="list!=null and list.size() > 0">
+            and type in
+            <foreach item="type" collection="list" open="(" separator="," close=")">
+                #{type}
+            </foreach>
+        </if>
+        ORDER BY type,sort,create_time desc
+        <if test="isLimit">limit 10 </if>
+    </select>
+</mapper>

+ 12 - 0
micro-dao/src/main/resources/mapper/AppCategoryPaymentMapper.xml

@@ -0,0 +1,12 @@
+<?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.poyee.dao.mapper.AppCategoryPaymentMapper">
+
+    <select id="getUserIdByCatId" parameterType="Long" resultType="Long">
+        SELECT user_id FROM app_user_category WHERE cat_id=#{catId}
+    </select>
+
+
+</mapper>

+ 115 - 0
micro-dao/src/main/resources/mapper/BaseApiMapper.xml

@@ -0,0 +1,115 @@
+<?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.poyee.dao.mapper.BaseApiMapper">
+<!--  验证app版本  -->
+    <select id="selectNextVersionApp" parameterType="object" resultType="com.poyee.common.domain.entity.ApplicationInfo">
+        SELECT
+        tai.is_update isUpdate,
+        tai.wgt_url wgtUrl,
+        tai.auto_update autoUpdate ,
+        tai.auto_restart autoRestart,
+        tai.tips,
+        tai.show_log showLog,
+        tai.release_type releaseType
+        FROM
+        tzy_app_info tai
+        WHERE
+        cast(replace(tai.app_version,'.','') as integer) >  cast(replace(#{atVersion},'.','') as integer)
+        and tai.type = #{type} and is_update=1 and release_type='public'
+        and (char_length(app_release_note)=0 or app_release_note = #{atVersion} )
+        order by tai.build_version desc limit 1
+    </select>
+
+    <!-- 定义结果映射 -->
+    <resultMap id="AppActConfigResultMap" type="com.poyee.common.domain.entity.AppActConfig">
+        <id property="id" column="id"/>
+        <result property="type" column="type"/>
+        <result property="userGrowth" column="user_growth"/>
+        <result property="groupInfoId" column="group_info_id"/>
+        <result property="set" column="set"/>
+        <result property="status" column="status"/>
+        <result property="description" column="description"/>
+        <result property="createTime" column="create_time"/>
+        <result property="actName" column="act_name"/>
+        <result property="startTime" column="start_time"/>
+        <result property="endTime" column="end_time"/>
+        <result property="couponIds" column="coupon_ids"/>
+        <result property="historyLimitDay" column="history_limit_day"/>
+        <result property="startHour" column="start_hour"/>
+        <result property="endHour" column="end_hour"/>
+        <result property="actImg" column="act_img"/>
+        <result property="imgType" column="img_type"/>
+        <result property="actUrl" column="act_url"/>
+        <result property="sortValue" column="sort_value"/>
+        <result property="remindTime" column="remind_time"/>
+        <result property="clickType" column="click_type"/>
+        <result property="lastTime" column="last_time"/>
+        <result property="subType" column="sub_type"/>
+        <result property="op" column="op"/>
+        <result property="catId" column="cat_id"/>
+    </resultMap>
+
+    <select id="selectAppActConfig" resultMap="AppActConfigResultMap">
+        SELECT *
+        FROM app_act_config
+        WHERE status = 1
+        ORDER BY sort_value DESC, id DESC
+    </select>
+
+    <select id="getOrderCountByTime" resultType="int">
+        SELECT COUNT(0)
+        FROM card_group_order_info
+        WHERE user_id = #{userId}
+        AND status = 101
+        AND (now() - create_time::timestamp &lt; interval '${historyLimitDay} day')
+    </select>
+
+    <!--查询applet信息-->
+    <select id="searchUserInfoById" parameterType="integer" resultType="com.poyee.common.dto.AppUserInfoDto">
+        SELECT
+        abu.id ,
+        abu.openid ,
+        abu.unionid ,
+        abu.realname ,
+        abu.nickname ,
+        abu.avatar ,
+        abu.level,
+        COALESCE(abu.point,0) point,
+        COALESCE(abu.growth_num,0) growthNum,
+        abu.refuse_pick_up refusePickUp,
+        abu.create_time registerTime,
+        abu.register_channel registerChannel,
+        aa.account,
+        aa.phone,
+        aa.del_flg delFlg,
+        aa.email,
+        ar.code rolecode,
+        abu.member_level memberLevel,
+        abu.member_name memberName,
+        abu.current_month_growth currentMonthGrowth,
+        COALESCE(abu.member_init_flag,0) memberInitFlag,
+        abu.member_keep_growth memberKeepGrowth,
+        abu.sms_register_id smsRegisterId,
+        abu.face_verify faceVerify,
+        COALESCE(abu.daily_limit,0) dailyLimit,
+        COALESCE(abu.weekly_limit,0) weeklyLimit,
+        COALESCE(abu.monthly_limit,0) monthlyLimit
+        FROM
+        app_base_user abu
+        left join app_account aa on aa.account = abu.username
+        left join app_role ar on ar.id = aa.roleid
+        where
+        abu.id = #{id} and aa.del_flg=0
+    </select>
+
+
+    <select id="countUserCardRecord" resultType="int">
+        SELECT count(0)
+        FROM app_user_card_record
+        WHERE user_id = #{userId}
+        AND card_id IN
+        <foreach item="item" index="index" collection="couponIds" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+</mapper>

+ 12 - 0
micro-dao/src/main/resources/mapper/GroupApiMapper.xml

@@ -0,0 +1,12 @@
+<?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.poyee.dao.mapper.GroupApiMapper">
+
+    <select id="findOneRateGroupPic"  resultType="String">
+        select cover_picture
+        from card_group_info
+        WHERE status =201 and show_applet='1' and real_sold_num>1
+        order by COALESCE(round(cast(real_sold_num as numeric) / cast(copies as numeric),4),0) desc limit 1
+    </select>
+
+</mapper>

+ 42 - 0
micro-dao/src/main/resources/mapper/SysDictDataMapper.xml

@@ -0,0 +1,42 @@
+<?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.poyee.dao.mapper.SysDictDataMapper">
+	
+	<resultMap type="SysDictData" id="SysDictDataResult">
+		<id     property="dictCode"   column="dict_code"   />
+		<result property="dictSort"   column="dict_sort"   />
+		<result property="dictLabel"  column="dict_label"  />
+		<result property="dictValue"  column="dict_value"  />
+		<result property="dictType"   column="dict_type"   />
+		<result property="cssClass"   column="css_class"   />
+		<result property="listClass"  column="list_class"  />
+		<result property="isDefault"  column="is_default"  />
+		<result property="status"     column="status"      />
+		<result property="remark"     column="remark"      />
+		<result property="createBy"   column="create_by"   />
+		<result property="createTime" column="create_time" />
+		<result property="updateBy"   column="update_by"   />
+		<result property="updateTime" column="update_time" />
+		<result property="abroadFlag" column="abroad_flag" />
+		<result property="limitTime" column="limit_time" />
+		<result property="propConfig" column="prop_config" />
+	</resultMap>
+	
+	<sql id="selectDictDataVo">
+        select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status,
+		remark,abroad_flag,limit_time,prop_config
+		from sys_dict_data
+    </sql>
+
+	<select id="selectDictDataByType" parameterType="java.lang.String" resultMap="SysDictDataResult">
+	    <include refid="selectDictDataVo"/>
+		<where>
+		    <if test="dictType != null and dictType != ''">
+				AND dict_type = #{dictType}
+			</if>
+		</where>
+	</select>
+
+</mapper>

+ 27 - 0
micro-dao/src/main/resources/mapper/TzyCardTaskInfoMapper.xml

@@ -0,0 +1,27 @@
+<?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.poyee.dao.mapper.TzyCardTaskRemindMapper">
+
+    <resultMap id="cardTaskRemind" type="com.poyee.common.domain.entity.TzyCardTaskRemind">
+        <id column="remindId" property="id"/>
+        <result column="img_url" property="imgUrl"/>
+    </resultMap>
+
+
+    <select id="getRemindByUserId" resultMap="cardTaskRemind">
+        select cti.img_url,ctr.id remindId from tzy_card_task_info cti
+        LEFT JOIN tzy_card_task_remind ctr
+        on cti.id= ctr.task_id
+        where ctr.user_id=#{userId} and ctr.remind=0
+    </select>
+
+    <update id="updateRemind">
+        update tzy_card_task_remind set remind=1 where id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 42 - 0
micro-manager/pom.xml

@@ -0,0 +1,42 @@
+<?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>com.poyee</groupId>
+        <artifactId>poyee-micro</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>micro-manager</artifactId>
+    <version>1.0.0</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.poyee</groupId>
+            <artifactId>micro-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.poyee</groupId>
+            <artifactId>micro-dao</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis</groupId>
+            <artifactId>mybatis</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 19 - 0
micro-manager/src/main/java/com/poyee/manager/CacheRedisManager.java

@@ -0,0 +1,19 @@
+package com.poyee.manager;
+
+import com.poyee.common.domain.entity.AppActConfig;
+import com.poyee.common.domain.entity.TzyCardTaskRemind;
+
+import java.util.List;
+
+/**
+ * 有查询或更新的缓存
+ * 相对逻辑较复杂
+ * 有后台更新的数据最好用这个,注解缓存要key入参数存在
+ */
+public interface CacheRedisManager {
+    List<TzyCardTaskRemind> getTaskRemind(Integer userId);
+
+    void updateTaskRemind(Integer userId, List<Long> ids);
+
+    List<AppActConfig> getAppActConfigs();
+}

+ 47 - 0
micro-manager/src/main/java/com/poyee/manager/CacheSqlManager.java

@@ -0,0 +1,47 @@
+package com.poyee.manager;
+
+import com.poyee.common.domain.entity.*;
+import com.poyee.common.dto.AppUserInfoDto;
+
+import java.util.List;
+
+/**
+ * 注解式缓存,仅临时存储数据,比较简单
+ * @author zhenhua.bian
+ * @date 2025/10/23
+ */
+public interface CacheSqlManager {
+    List<SysDictData> getDict(String dictType);
+
+    ApplicationInfo selectNextVersionApp(AppVersionParam appVersionParam);
+
+    int getActCount(ActCountParam countParam);
+
+    List<AppCarouselPicture> getBannerByType(List<String> types);
+
+    String getOverPicture();
+
+    /**
+     * 查询已购买订单数
+     */
+    int getBuyOrderCount(Integer userId, Integer historyLimitDay);
+
+    /**
+     * 查询用户信息
+     * @param id
+     * @return
+     */
+    AppUserInfoDto searchUserInfoById(Integer id);
+
+    /**
+     * 查询用户券数量
+     */
+    int getUserCouponCount(Integer userId, List<String> couponIds);
+
+    /**
+     * 查询标签下用户id
+     * @param catId
+     * @return
+     */
+    List<Long> getUserIdByCatId(Long catId);
+}

+ 8 - 0
micro-manager/src/main/java/com/poyee/manager/QiNiuManager.java

@@ -0,0 +1,8 @@
+package com.poyee.manager;
+
+/**
+ * 查询七牛云token
+ */
+public interface QiNiuManager {
+    String getUpToken();
+}

+ 106 - 0
micro-manager/src/main/java/com/poyee/manager/RedisManager.java

@@ -0,0 +1,106 @@
+package com.poyee.manager;
+
+import com.poyee.common.config.LimitRule;
+import org.redisson.api.RLock;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 缓存管理类
+ */
+public interface RedisManager {
+    /**
+     * 通用方法
+     */
+    boolean expire(String key, long time);
+    long getExpire(String key);
+    boolean hasKey(String key);
+    void del(String... key);
+
+    /**
+     * String 类型
+     */
+    Object get(String key);
+    List<Object> multiGet(List<String> keys);
+    boolean set(String key, Object value);
+    boolean set(String key, Object value, long time);
+    long incr(String key, long delta);
+    long decr(String key, long delta);
+
+
+    /**
+     * Hash 类型
+     */
+    Object hget(String key, String item);
+    Map<Object, Object> hmget(String key);
+    Set<Object> hGetKeys(String key);
+    boolean hmset(String key, Map<String, Object> map);
+    boolean hmset(String key, Map<String, Object> map, long time);
+    boolean hset(String key, String item, Object value);
+    long hSize(String key);
+    boolean hset(String key, String item, Object value, long time);
+    void hdel(String key, Object... item);
+    boolean hHasKey(String key, String item);
+    double hincr(String key, String item, double by);
+    double hdecr(String key, String item, double by);
+
+    /**
+     * Set 类型
+     */
+    Set<Object> sGet(String key);
+    boolean sHasKey(String key, Object value);
+    long sSet(String key, Object... values);
+    long sSetAndTime(String key, long time, Object... values);
+    long sGetSetSize(String key);
+    long setRemove(String key, Object... values);
+
+    /**
+     * ZSet 类型
+     */
+    Set<Object> zSGet(String key);
+    boolean zSHasKey(String key, Object value);
+    Boolean zSSet(String key, Object value, double score);
+    long zSSetAndTime(String key, long time, Object... values);
+    long zSGetSetSize(String key);
+    long zSetRemove(String key, Object... values);
+
+    /**
+     * List 类型
+     */
+    List<Object> lGet(String key, long start, long end);
+    Object rightPop(String key);
+    long lGetListSize(String key);
+    Object lGetIndex(String key, long index);
+    boolean lSet(String key, Object value);
+    boolean lPut(String key, List value);
+    boolean lCommit(String key, List value);
+    boolean lSet(String key, Object value, long time);
+    boolean lSet(String key, List<Object> value);
+    boolean lSet(String key, List<Object> value, long time);
+    boolean lUpdateIndex(String key, long index, Object value);
+    long lRemove(String key, long count, Object value);
+
+    /**
+     * lock
+     */
+    RLock lock(String lockKey);
+    RLock lock(String lockKey, long leaseTime);
+    RLock lock(String lockKey, TimeUnit unit, long timeout);
+    boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime);
+    boolean tryLock(String lockKey, TimeUnit unit, long waitTime);
+    void unlock(String lockKey);
+    void unlock(RLock lock);
+
+    /**
+     * 工具
+     */
+    Set<String> keys(String keyPrefix);
+    Object eval(String lua, List<Object> keys, Object... args);
+    boolean tryAccess(String key, int seconds, int limitCount);
+    boolean tryAccess(String key, LimitRule limitRule);
+    Boolean setIfAbsent(String key, String val, int time, TimeUnit timeUnit);
+
+}

+ 44 - 0
micro-manager/src/main/java/com/poyee/manager/aspect/ValueAspectHandler.java

@@ -0,0 +1,44 @@
+package com.poyee.manager.aspect;
+
+import com.poyee.common.annotation.ValueAspect;
+import com.poyee.common.domain.entity.SysDictData;
+import com.poyee.manager.CacheSqlManager;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+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 javax.annotation.Resource;
+
+import java.util.List;
+
+@Aspect
+@Component
+@Slf4j
+public class ValueAspectHandler {
+    @Resource
+    private CacheSqlManager cacheSqlManager;
+
+    // 配置织入点
+    @Pointcut("@annotation(com.poyee.common.annotation.ValueAspect)")
+    public void valueAspectPointcut() {
+    }
+
+    @Around("valueAspectPointcut()")
+    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+        try {
+            // 直接返回字典值,不执行原方法
+            //List<SysDictData> dict = cacheSqlManager.getDict(valueAspect.value());
+        /*if (CollectionUtils.isNotEmpty(dict)) {
+            return dict.get(0).getDictValue();
+        }
+        return valueAspect.defaultValue();*/
+            System.out.println("xxx");
+            return joinPoint.proceed();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 63 - 0
micro-manager/src/main/java/com/poyee/manager/impl/CacheRedisManagerImpl.java

@@ -0,0 +1,63 @@
+package com.poyee.manager.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.poyee.common.constant.Constants;
+import com.poyee.common.constant.RedisKeyConstants;
+import com.poyee.common.domain.entity.AppActConfig;
+import com.poyee.common.domain.entity.TzyCardTaskRemind;
+import com.poyee.dao.mapper.BaseApiMapper;
+import com.poyee.dao.mapper.TzyCardTaskRemindMapper;
+import com.poyee.manager.CacheRedisManager;
+import com.poyee.manager.RedisManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Component
+public class CacheRedisManagerImpl implements CacheRedisManager {
+    @Resource
+    private RedisManager redisManager;
+
+    @Resource
+    private TzyCardTaskRemindMapper taskRemindMapper;
+
+    @Resource
+    private BaseApiMapper baseApiMapper;
+
+    @Override
+    public List<TzyCardTaskRemind> getTaskRemind(Integer userId) {
+        Object o = redisManager.get(RedisKeyConstants.REMINDER_TASK + userId);
+        if (Objects.nonNull(o)) {
+            return JSON.parseArray(o.toString(), TzyCardTaskRemind.class);
+        }
+        List<TzyCardTaskRemind> taskReminds = taskRemindMapper.getRemindByUserId(userId);
+        redisManager.set(RedisKeyConstants.REMINDER_TASK + userId,
+                JSON.toJSONString(taskReminds), RedisKeyConstants.REMINDER_TASK_TIMEOUT);
+        return taskReminds;
+    }
+
+    @Override
+    public void updateTaskRemind(Integer userId, List<Long> ids) {
+        int i = taskRemindMapper.updateRemind(ids);
+        redisManager.set(RedisKeyConstants.REMINDER_TASK + userId,
+                JSON.toJSONString(Collections.emptyList()));
+        log.info("更新任务提醒成功,userId={},ids={}, count={}", userId, ids, i);
+    }
+
+    @Override
+    public List<AppActConfig> getAppActConfigs() {
+        Object o = redisManager.get(Constants.APP_ACT_CACHE);
+        if (Objects.nonNull(o)) {
+            return JSON.parseArray(o.toString(), AppActConfig.class);
+        }
+        List<AppActConfig> appActConfigs = baseApiMapper.selectAppActConfig();
+        redisManager.set(Constants.APP_ACT_CACHE,
+                JSON.toJSONString(appActConfigs), RedisKeyConstants.COMMON_DAY_TIMEOUT);
+        return appActConfigs;
+    }
+}

+ 100 - 0
micro-manager/src/main/java/com/poyee/manager/impl/CacheSqlManagerImpl.java

@@ -0,0 +1,100 @@
+package com.poyee.manager.impl;
+
+import com.poyee.common.domain.entity.*;
+import com.poyee.common.dto.AppUserInfoDto;
+import com.poyee.dao.mapper.*;
+import com.poyee.manager.CacheSqlManager;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Component
+public class CacheSqlManagerImpl implements CacheSqlManager {
+    private static final String OVER_PICTURE_CACHE_KEY = "one";
+
+    @Resource
+    private SysDictDataMapper sysDictDataMapper;
+
+    @Resource
+    private BaseApiMapper baseApiMapper;
+
+    @Resource
+    private AppActPrizeRecordMapper actPrizeRecordMapper;
+
+    @Resource
+    private AppCarouselPictureMapper appCarouselPictureMapper;
+
+    @Resource
+    private GroupApiMapper groupApiMapper;
+
+    @Resource
+    private TzyCardTaskRemindMapper tzyCardTaskRemindMapper;
+
+    @Resource
+    private AppCategoryPaymentMapper appCategoryPaymentMapper;
+
+
+    @Override
+    @Cacheable(cacheNames = "DICT_DATA_CACHE_KEY#600", key = "#dictType", unless = "#result == null")
+    public List<SysDictData> getDict(@NotNull String dictType) {
+        return sysDictDataMapper.selectDictDataByType(dictType);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_VERSION_CACHE_KEY#600",
+            key = "#appVersionParam.atVersion + '_' + #appVersionParam.type", unless = "#result == null")
+    public ApplicationInfo selectNextVersionApp(AppVersionParam appVersionParam) {
+        return baseApiMapper.selectNextVersionApp(appVersionParam);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_ACT_COUNT_CACHE_KEY#600",
+            key = "#countParam.actId + '_' + #countParam.userId", unless = "#result == null")
+    public int getActCount(ActCountParam countParam) {
+        return actPrizeRecordMapper.getActCount(countParam);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_BANNER_CACHE_KEY#600",
+            key = "T(String).join('_', #types)", unless = "#result == null")
+    public List<AppCarouselPicture> getBannerByType(List<String> types) {
+        return appCarouselPictureMapper.getBanner(types, false);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_PICTURE_CACHE_KEY#600",
+            key = "'" + OVER_PICTURE_CACHE_KEY + "'", unless = "#result == null")
+    public String getOverPicture() {
+        return groupApiMapper.findOneRateGroupPic();
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_BUY_ORDER_COUNT_CACHE_KEY#3600",
+            key = "#userId + '_' + #historyLimitDay", unless = "#result == null")
+    public int getBuyOrderCount(Integer userId, Integer historyLimitDay) {
+        return baseApiMapper.getOrderCountByTime(userId, historyLimitDay);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_USER_INFO_CACHE_KEY#86400",
+            key = "#id", unless = "#result == null")
+    public AppUserInfoDto searchUserInfoById(Integer id) {
+        return baseApiMapper.searchUserInfoById(id);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "APP_USER_COUPON_COUNT_CACHE_KEY#3600",
+            key = "#userId", unless = "#result == null")
+    public int getUserCouponCount(Integer userId, List<String> couponIds) {
+        return baseApiMapper.countUserCardRecord(userId, couponIds);
+    }
+
+    @Override
+    @Cacheable(cacheNames = "app_cat_user_id#86400", key = "#catId", unless = "#result == null")
+    public List<Long> getUserIdByCatId(Long catId) {
+        return appCategoryPaymentMapper.getUserIdByCatId(catId);
+    }
+}

+ 19 - 0
micro-manager/src/main/java/com/poyee/manager/impl/QiNiuManagerImpl.java

@@ -0,0 +1,19 @@
+package com.poyee.manager.impl;
+
+import com.poyee.common.constant.BusConstants;
+import com.poyee.manager.QiNiuManager;
+import com.qiniu.util.Auth;
+import org.springframework.stereotype.Component;
+
+@Component
+public class QiNiuManagerImpl implements QiNiuManager {
+    private static Auth auth = null;
+
+    static {
+        auth = Auth.create(BusConstants.accessKey, BusConstants.secretKey);
+    }
+    @Override
+    public String getUpToken() {
+        return auth.uploadToken(BusConstants.bucketName);
+    }
+}

+ 970 - 0
micro-manager/src/main/java/com/poyee/manager/impl/RedisManagerImpl.java

@@ -0,0 +1,970 @@
+package com.poyee.manager.impl;
+
+import com.poyee.common.config.LimitRule;
+import com.poyee.manager.RedisManager;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RScript;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Component
+public class RedisManagerImpl implements RedisManager {
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+    @Autowired
+    private RedissonClient redissonClient;
+
+    // =============================common============================
+
+    /**
+     * 指定缓存失效时间
+     *
+     * @param key
+     *            键
+     * @param time
+     *            时间(秒)
+     * @return
+     */
+    public boolean expire(String key, long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 根据key 获取过期时间
+     *
+     * @param key
+     *            键 不能为null
+     * @return 时间(秒) 返回0代表为永久有效
+     */
+    public long getExpire(String key) {
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 判断key是否存在
+     *
+     * @param key
+     *            键
+     * @return true 存在 false不存在
+     */
+    public boolean hasKey(String key) {
+        try {
+            return redisTemplate.hasKey(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 删除缓存
+     *
+     * @param key
+     *            可以传一个值 或多个
+     */
+    @SuppressWarnings("unchecked")
+    public void del(String... key) {
+        if (key != null && key.length > 0) {
+            if (key.length == 1) {
+                redisTemplate.delete(key[0]);
+            } else {
+                redisTemplate.delete(CollectionUtils.arrayToList(key));
+            }
+        }
+    }
+
+    // ============================String=============================
+    /**
+     * 普通缓存获取
+     *
+     * @param key
+     *            键
+     * @return 值
+     */
+    public Object get(String key) {
+        return key == null ? null : redisTemplate.opsForValue().get(key);
+    }
+
+    public List<Object> multiGet(List<String> keys) {
+        if (keys == null || keys.isEmpty()) {
+            return Collections.emptyList();
+        }
+        // 批量查询 Redis
+        List<Object> values = redisTemplate.opsForValue().multiGet(keys);
+        // 记录每个 Key 的查询结果大小(可选)
+        if (values != null) {
+            for (int i = 0; i < keys.size(); i++) {
+                String key = keys.get(i);
+                Object value = (i < values.size()) ? values.get(i) : null;
+            }
+        }
+        return values != null ? values : Collections.emptyList();
+    }
+
+
+    /**
+     * 普通缓存放入
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @return true成功 false失败
+     */
+    public boolean set(String key, Object value) {
+        try {
+            redisTemplate.opsForValue().set(key, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+
+    }
+
+    /**
+     * 普通缓存放入并设置时间
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @param time
+     *            时间(秒) time要大于0 如果time小于等于0 将设置无限期
+     * @return true成功 false 失败
+     */
+    public boolean set(String key, Object value, long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+            } else {
+                set(key, value);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。
+     *
+     * @param key
+     *            键
+     * @param delta 要增加几(大于0)
+     * @return
+     */
+    public long incr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递减
+     *
+     * @param key
+     *            键
+     * @param delta 要减少几(小于0)
+     * @return
+     */
+    public long decr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+
+    // ================================Map=================================
+    /**
+     * HashGet
+     *
+     * @param key
+     *            键 不能为null
+     * @param item
+     *            项 不能为null
+     * @return 值
+     */
+    public Object hget(String key, String item) {
+        return redisTemplate.opsForHash().get(key, item);
+    }
+
+    /**
+     * 获取hashKey对应的所有键值
+     *
+     * @param key
+     *            键
+     * @return 对应的多个键值
+     */
+    public Map<Object, Object> hmget(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 获取hashKey对应的所有键值key2
+     *
+     * @param key
+     *            键
+     * @return 对应的多个键值
+     */
+    public Set<Object> hGetKeys(String key) {
+        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
+        return entries.keySet();
+    }
+
+    /**
+     * HashSet
+     *
+     * @param key
+     *            键
+     * @param map
+     *            对应多个键值
+     * @return true 成功 false 失败
+     */
+    public boolean hmset(String key, Map<String, Object> map) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * HashSet 并设置时间
+     *
+     * @param key
+     *            键
+     * @param map
+     *            对应多个键值
+     * @param time
+     *            时间(秒)
+     * @return true成功 false失败
+     */
+    public boolean hmset(String key, Map<String, Object> map, long time) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key
+     *            键
+     * @param item
+     *            项
+     * @param value
+     *            值
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key, String item, Object value) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * hase表数量
+     * @param key
+     * @return
+     */
+    public long hSize(String key) {
+        return redisTemplate.opsForHash().size(key);
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key
+     *            键
+     * @param item
+     *            项
+     * @param value
+     *            值
+     * @param time
+     *            时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key, String item, Object value, long time) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 删除hash表中的值
+     *
+     * @param key
+     *            键 不能为null
+     * @param item
+     *            项 可以使多个 不能为null
+     */
+    public void hdel(String key, Object... item) {
+        redisTemplate.opsForHash().delete(key, item);
+    }
+
+    /**
+     * 判断hash表中是否有该项的值
+     *
+     * @param key
+     *            键 不能为null
+     * @param item
+     *            项 不能为null
+     * @return true 存在 false不存在
+     */
+    public boolean hHasKey(String key, String item) {
+        return redisTemplate.opsForHash().hasKey(key, item);
+    }
+
+    /**
+     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+     *
+     * @param key
+     *            键
+     * @param item
+     *            项
+     * @param by
+     *            要增加几(大于0)
+     * @return
+     */
+    public double hincr(String key, String item, double by) {
+        return redisTemplate.opsForHash().increment(key, item, by);
+    }
+
+    /**
+     * hash递减
+     *
+     * @param key
+     *            键
+     * @param item
+     *            项
+     * @param by
+     *            要减少记(小于0)
+     * @return
+     */
+    public double hdecr(String key, String item, double by) {
+        return redisTemplate.opsForHash().increment(key, item, -by);
+    }
+
+    // ============================set=============================
+    /**
+     * 根据key获取Set中的所有值
+     *
+     * @param key
+     *            键
+     * @return
+     */
+    public Set<Object> sGet(String key) {
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return null;
+        }
+    }
+
+    /**
+     * 根据value从一个set中查询,是否存在
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @return true 存在 false不存在
+     */
+    public boolean sHasKey(String key, Object value) {
+        try {
+            return redisTemplate.opsForSet().isMember(key, value);
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 将数据放入set缓存
+     *
+     * @param key
+     *            键
+     * @param values
+     *            值 可以是多个
+     * @return 成功个数
+     */
+    public long sSet(String key, Object... values) {
+        try {
+            return redisTemplate.opsForSet().add(key, values);
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 将set数据放入缓存
+     *
+     * @param key
+     *            键
+     * @param time
+     *            时间(秒)
+     * @param values
+     *            值 可以是多个
+     * @return 成功个数
+     */
+    public long sSetAndTime(String key, long time, Object... values) {
+        try {
+            Long count = redisTemplate.opsForSet().add(key, values);
+            if (time > 0)
+                expire(key, time);
+            return count;
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key
+     *            键
+     * @return
+     */
+    public long sGetSetSize(String key) {
+        try {
+            return redisTemplate.opsForSet().size(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 移除值为value的
+     *
+     * @param key
+     *            键
+     * @param values
+     *            值 可以是多个
+     * @return 移除的个数
+     */
+    public long setRemove(String key, Object... values) {
+        try {
+            Long count = redisTemplate.opsForSet().remove(key, values);
+            return count;
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    // ============================zset=============================
+    /**
+     * 根据key获取Set中的所有值
+     *
+     * @param key
+     *            键
+     * @return
+     */
+    public Set<Object> zSGet(String key) {
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return null;
+        }
+    }
+
+    /**
+     * 根据value从一个set中查询,是否存在
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @return true 存在 false不存在
+     */
+    public boolean zSHasKey(String key, Object value) {
+        try {
+            return redisTemplate.opsForSet().isMember(key, value);
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    public Boolean zSSet(String key, Object value, double score) {
+        try {
+            return redisTemplate.opsForZSet().add(key, value, score);
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+
+
+    /**
+     * 将set数据放入缓存
+     *
+     * @param key
+     *            键
+     * @param time
+     *            时间(秒)
+     * @param values
+     *            值 可以是多个
+     * @return 成功个数
+     */
+    public long zSSetAndTime(String key, long time, Object... values) {
+        try {
+            Long count = redisTemplate.opsForSet().add(key, values);
+            if (time > 0)
+                expire(key, time);
+            return count;
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key
+     *            键
+     * @return
+     */
+    public long zSGetSetSize(String key) {
+        try {
+            return redisTemplate.opsForSet().size(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 移除值为value的
+     *
+     * @param key
+     *            键
+     * @param values
+     *            值 可以是多个
+     * @return 移除的个数
+     */
+    public long zSetRemove(String key, Object... values) {
+        try {
+            Long count = redisTemplate.opsForSet().remove(key, values);
+            return count;
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+    // ===============================list=================================
+
+    /**
+     * 获取list缓存的内容
+     *
+     * @取出来的元素 总数 end-start+1
+     *
+     * @param key
+     *            键
+     * @param start
+     *            开始 0 是第一个元素
+     * @param end
+     *            结束 -1代表所有值
+     * @return
+     */
+    public List<Object> lGet(String key, long start, long end) {
+        try {
+            return redisTemplate.opsForList().range(key, start, end);
+        } catch (Exception e) {
+            log.error(key, e);
+            return null;
+        }
+    }
+
+
+    public Object rightPop(String key) {
+        try {
+            return redisTemplate.opsForList().rightPop(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取list缓存的长度
+     *
+     * @param key
+     *            键
+     * @return
+     */
+    public long lGetListSize(String key) {
+        try {
+            return redisTemplate.opsForList().size(key);
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * 通过索引 获取list中的值
+     *
+     * @param key
+     *            键
+     * @param index
+     *            索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
+     * @return
+     */
+    public Object lGetIndex(String key, long index) {
+        try {
+            return redisTemplate.opsForList().index(key, index);
+        } catch (Exception e) {
+            log.error(key, e);
+            return null;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @param
+     *
+     * @return
+     */
+    public boolean lSet(String key, Object value) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public boolean lPut(String key, List value) {
+        if(null == value) return false;
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    public boolean lCommit(String key ,List value){
+        try {
+            redisTemplate.delete(key);
+            lPut(key, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+    /**
+     * 将list放入缓存
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @param time
+     *            时间(秒)
+     * @return
+     */
+    public boolean lSet(String key, Object value, long time) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            if (time > 0)
+                expire(key, time);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @return
+     */
+    public boolean lSet(String key, List<Object> value) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key
+     *            键
+     * @param value
+     *            值
+     * @param time
+     *            时间(秒)
+     * @return
+     */
+    public boolean lSet(String key, List<Object> value, long time) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            if (time > 0)
+                expire(key, time);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 根据索引修改list中的某条数据
+     *
+     * @param key
+     *            键
+     * @param index
+     *            索引
+     * @param value
+     *            值
+     * @return
+     */
+    public boolean lUpdateIndex(String key, long index, Object value) {
+        try {
+            redisTemplate.opsForList().set(key, index, value);
+            return true;
+        } catch (Exception e) {
+            log.error(key, e);
+            return false;
+        }
+    }
+
+    /**
+     * 移除N个值为value
+     *
+     * @param key
+     *            键
+     * @param count
+     *            移除多少个
+     * @param value
+     *            值
+     * @return 移除的个数
+     */
+    public long lRemove(String key, long count, Object value) {
+        try {
+            Long remove = redisTemplate.opsForList().remove(key, count, value);
+            return remove;
+        } catch (Exception e) {
+            log.error(key, e);
+            return 0;
+        }
+    }
+
+    /**
+     * lock(), 拿不到lock就不罢休,不然线程就一直block
+     */
+    public RLock lock(String lockKey) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.lock();
+        return lock;
+    }
+
+    /**
+     * leaseTime为加锁时间,单位为秒
+     */
+    public RLock lock(String lockKey, long leaseTime) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.lock(leaseTime, TimeUnit.SECONDS);
+        return lock;
+    }
+
+    /**
+     * timeout为加锁时间,时间单位由unit确定
+     */
+    public RLock lock(String lockKey, TimeUnit unit, long timeout) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.lock(timeout, unit);
+        return lock;
+    }
+
+    /**
+     * tryLock(),马上返回,拿到lock就返回true,不然返回false。
+     * 带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
+     */
+    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
+        RLock lock = redissonClient.getLock(lockKey);
+        try {
+            return lock.tryLock(waitTime, leaseTime, unit);
+        } catch (Exception e) {
+            log.error("异常:{}", e);
+            return false;
+        }
+    }
+
+    /**
+     * 自动续期锁
+     * @param lockKey
+     * @param unit
+     * @param waitTime
+     * @return
+     */
+    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime) {
+        RLock lock = redissonClient.getLock(lockKey);
+        try {
+            return lock.tryLock(waitTime, -1, unit);
+        } catch (Exception e) {
+            log.error("异常:{}", e);
+            return false;
+        }
+    }
+
+    /**
+     * 释放 key 的锁
+     */
+    public void unlock(String lockKey) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.unlock();
+    }
+
+    /**
+     * 释放锁
+     */
+    public void unlock(RLock lock) {
+        lock.unlock();
+    }
+
+    public  Set<String> keys(String keyPrefix) {
+        return redisTemplate.keys(keyPrefix);
+    }
+
+    public Object eval(String lua,List<Object> keys, Object...  args) {
+        Object eval=redissonClient.getScript().eval(RScript.Mode.READ_WRITE, lua, RScript.ReturnType.VALUE,keys,args);
+        return eval;
+    }
+
+    /**
+     * 访问限制
+     * @param key ip等
+     * @param seconds 秒
+     * @param limitCount 次数
+     * @return
+     */
+    public boolean tryAccess(String key, int seconds, int limitCount) {
+        LimitRule limitRule = new LimitRule();
+        limitRule.setLimitCount(limitCount);
+        limitRule.setSeconds(seconds);
+        return this.tryAccess(key, limitRule);
+    }
+
+
+    /**
+     * 访问限制
+     * @param key ip等
+     * @param limitRule 限制规则
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public boolean tryAccess(String key, LimitRule limitRule) {
+        String newKey = "Limit:" + key;
+        int count = -1;
+        boolean var10=false;
+        try {
+            List<Object> keys = new ArrayList();
+            keys.add(newKey);
+            String[] args = new String[4];
+            args[0]=Math.max(limitRule.getLimitCount(), limitRule.getLockCount()) + "";
+            args[1]=limitRule.getSeconds() + "";
+            args[2]=limitRule.getLockCount() + "";
+            args[3]=limitRule.getLockTime() + "";
+            count = Integer.valueOf(eval(this.buildLimitLuaScript(limitRule.enableLimitLock()), keys, args).toString());
+            var10 = count <= limitRule.getLimitCount();
+        } catch (Exception e) {
+            log.error("lua执行异常:", e);
+        }
+
+        return var10;
+    }
+
+    private String buildLimitLuaScript(boolean isLimit) {
+        StringBuilder lua = new StringBuilder();
+        lua.append("\nlocal c");
+        lua.append("\nc = redis.call('get',KEYS[1])");
+        lua.append("\nif c and tonumber(c) > tonumber(ARGV[1]) then");
+        lua.append("\nreturn c;");
+        lua.append("\nend");
+        lua.append("\nc = redis.call('incr',KEYS[1])");
+        lua.append("\nif tonumber(c) == 1 then");
+        lua.append("\nredis.call('expire',KEYS[1],ARGV[2])");
+        lua.append("\nend");
+        if (isLimit) {
+            lua.append("\nif tonumber(c) > tonumber(ARGV[3]) then");
+            lua.append("\nredis.call('expire',KEYS[1],ARGV[4])");
+            lua.append("\nend");
+        }
+
+        lua.append("\nreturn c;");
+        return lua.toString();
+    }
+
+    public Boolean setIfAbsent(String key, String val, int time, TimeUnit timeUnit) {
+        return redisTemplate.opsForValue().setIfAbsent(key, val, time, timeUnit);
+    }
+}

+ 30 - 0
micro-service/pom.xml

@@ -0,0 +1,30 @@
+<?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>com.poyee</groupId>
+        <artifactId>poyee-micro</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>micro-service</artifactId>
+    <version>1.0.0</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.poyee</groupId>
+            <artifactId>micro-manager</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 71 - 0
micro-service/src/main/java/com/poyee/service/BusService.java

@@ -0,0 +1,71 @@
+package com.poyee.service;
+
+import com.poyee.common.domain.vo.AppActAdVO;
+import com.poyee.common.domain.vo.AppActManageVO;
+import com.poyee.common.domain.vo.AppCarouselPictureVO;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 一些通用信息或外部调用
+ */
+public interface BusService {
+    /**
+     * 获取七牛云token
+     * @return
+     */
+    String getQiNiuToken();
+
+    /**
+     * 获取store版本
+     * @param version
+     * @param phoneType
+     * @return
+     */
+    Map<String, Object> getStoreVersion(String version, String phoneType);
+
+    /**
+     * 获取app版本
+     * @param version
+     * @param phoneType
+     * @return
+     */
+    Map<String, Object> getAppVersion(String version, String phoneType);
+
+    /**
+     * 获取活动列表
+     * @param userId
+     * @return
+     */
+    List<AppActManageVO> getActList(Integer userId);
+
+    /**
+     * 获取banner
+     * @param types
+     * @return
+     */
+    Map<String, List<AppCarouselPictureVO>> getBannerByType(List<String> types);
+
+    /**
+     * 获取售罄底图
+     * @return
+     */
+    String getOverPicture();
+
+    /**
+     * 获取用户的提醒
+     * @param userId
+     * @return
+     */
+    List<AppActAdVO> getAppActAd(Integer userId);
+
+    /**
+     * 查询第一个开屏广告
+     * @param userId
+     * @param actList
+     * @return
+     */
+    Pair<AppActAdVO, List<AppActAdVO>> getOpenAd(Integer userId, List<AppActAdVO> actList);
+}

+ 24 - 0
micro-service/src/main/java/com/poyee/service/DictService.java

@@ -0,0 +1,24 @@
+package com.poyee.service;
+
+import com.poyee.common.domain.entity.SysDictData;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * 词表读取
+ * @author: zhenhua.bian
+ * @date: 2025/10/26
+ */
+public interface DictService {
+    /**
+     * 根据类型集合和状态读取
+     * @param types
+     * @param label
+     * @param status
+     * @return
+     */
+    HashMap<String, List<SysDictData>> getDict(List<String> types, String label, String status);
+
+    List<SysDictData> getDictByType(String type, String label, String status);
+}

+ 346 - 0
micro-service/src/main/java/com/poyee/service/impl/BusServiceImpl.java

@@ -0,0 +1,346 @@
+package com.poyee.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.poyee.common.annotation.ValueAspect;
+import com.poyee.common.constant.BusConstants;
+import com.poyee.common.constant.Constants;
+import com.poyee.common.constant.DictConstants;
+import com.poyee.common.constant.RedisKeyConstants;
+import com.poyee.common.domain.entity.*;
+import com.poyee.common.domain.vo.AppActAdVO;
+import com.poyee.common.domain.vo.AppActManageVO;
+import com.poyee.common.domain.vo.AppCarouselPictureVO;
+import com.poyee.common.dto.AppUserInfoDto;
+import com.poyee.common.utils.DateUtils;
+import com.poyee.common.utils.bean.DozerUtils;
+import com.poyee.common.utils.bean.JSONTools;
+import com.poyee.manager.CacheRedisManager;
+import com.poyee.manager.CacheSqlManager;
+import com.poyee.manager.QiNiuManager;
+import com.poyee.manager.RedisManager;
+import com.poyee.service.BusService;
+import com.poyee.service.DictService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class BusServiceImpl implements BusService {
+
+    @Resource
+    private RedisManager redisManager;
+
+    @Resource
+    private QiNiuManager qiNiuManager;
+
+    @Resource
+    private CacheSqlManager cacheSqlManager;
+
+    @Resource
+    private CacheRedisManager cacheRedisManager;
+
+    @Resource
+    private ThreadPoolTaskExecutor executor;
+
+    @Resource
+    private DictService dictService;
+
+    @ValueAspect(value = "stop_update_version", defaultValue = "11111")
+    public String getAppOnlineVersionIos() {
+        return "default";
+    }
+
+
+    @Override
+    public String getQiNiuToken() {
+        Object cacheStr = redisManager.get(BusConstants.QI_NIU_TOKEN);
+        if (Objects.nonNull(cacheStr) && StringUtils.isNotEmpty(cacheStr.toString())) {
+            return cacheStr.toString();
+        }
+        String upToken = qiNiuManager.getUpToken();
+        if (StringUtils.isNotEmpty(upToken)) {
+            redisManager.set(BusConstants.QI_NIU_TOKEN, upToken, BusConstants.QI_NIU_TOKEN_EXPIRE_TIME);
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("qiNiu={}", upToken);
+        }
+        return upToken;
+    }
+
+    @Override
+    public Map<String, Object> getStoreVersion(String version, String phoneType) {
+        Map<String, Object> storeVersion = new HashMap<>();
+        storeVersion.put("code", 0);
+
+        if (StringUtils.isAnyEmpty(version, phoneType)) {
+            return storeVersion;
+        }
+        String dictLabel = Constants.PHONE_TYPE_IOS.equals(phoneType) ?
+                DictConstants.APP_ONLINE_VERSION_IOS : DictConstants.APP_ONLINE_VERSION_ANDROID;
+        List<SysDictData> sysDictDataList = dictService.getDictByType(DictConstants.APP_ONLINE_VERSION, dictLabel, null);
+        if (CollectionUtils.isEmpty(sysDictDataList)) {
+            return storeVersion;
+        }
+        SysDictData sysDictData = sysDictDataList.get(0);
+        if (StringUtils.isNotEmpty(sysDictData.getDictValue())) {
+            Integer appVersion = Integer.valueOf(version.replaceAll("\\.", ""));
+            Integer dataVersion = Integer.valueOf(sysDictData.getDictValue().replaceAll("\\.", ""));
+            log.debug("appVersion={},dataVersion={}", appVersion, dataVersion);
+            if (appVersion < dataVersion) {
+                storeVersion.put("check", "1");
+                storeVersion.put("versionCode", dataVersion);
+                storeVersion.put("versionName", sysDictData.getDictValue());
+                storeVersion.put("versionInfo", sysDictData.getRemark());
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("storeVersion={}", JSON.toJSONString(storeVersion));
+        }
+        return storeVersion;
+    }
+
+    /**
+     * app 版本 version 传入被dictLabel所用
+     * @param version
+     * @param phoneType
+     * @return
+     */
+    @Override
+    public Map<String, Object> getAppVersion(String version, String phoneType) {
+        Map<String,  Object> appVersion = new HashMap<>();
+        appVersion.put("code", 0);
+
+        if (StringUtils.isAnyEmpty(version, phoneType)) {
+            return appVersion;
+        }
+        String app = getAppOnlineVersionIos();
+            log.debug("appOnlineVersionIos={},", app);
+        //阻止热更新
+        List<SysDictData> sysDictDataList = dictService.getDictByType(DictConstants.STOP_UPDATE_VERSION, version, null);
+        if (CollectionUtils.isNotEmpty(sysDictDataList)) {
+            return appVersion;
+        }
+        //查询最新版本
+        ApplicationInfo applicationInfo = cacheSqlManager.selectNextVersionApp(new AppVersionParam(version, phoneType));
+        if (Objects.isNull(applicationInfo)) {
+            return appVersion;
+        }
+        appVersion.put("code", 1);
+        appVersion.put("appinfo", applicationInfo);
+        if (log.isDebugEnabled()) {
+            log.debug("appVersion={}", JSON.toJSONString(appVersion));
+        }
+        return appVersion;
+    }
+
+    @Override
+    public List<AppActManageVO> getActList(Integer userId) {
+        List<SysDictData> dictDataList = dictService.getDictByType(Constants.FIRST_PAGE_DRAW_ACT, null, "1");
+        if (CollectionUtils.isEmpty(dictDataList)) {
+            return new ArrayList<>();
+        }
+        List<AppActManageVO> collect = dictDataList.stream().map(data ->
+                        JSONTools.jsonStr2obj(data.getDictValue(), AppActManageVO.class)).
+                filter(e -> checkActTime(e, userId)).collect(Collectors.toList());
+        if (log.isDebugEnabled()) {
+            log.debug("getActList={}", JSON.toJSONString(collect));
+        }
+        return collect;
+    }
+
+    private boolean checkActTime(AppActManageVO appActManageVO, Integer userId) {
+        if (appActManageVO == null) {
+            return false;
+        }
+        if (appActManageVO.getActStartTimestamp() != null &&
+                (appActManageVO.getActStartTimestamp() > System.currentTimeMillis() &&
+                        appActManageVO.getActStartTimestamp() - System.currentTimeMillis() > 180000L)) {
+            return false;
+        }
+        if (appActManageVO.getActEndTimestamp() != null && appActManageVO.getActEndTimestamp() < System.currentTimeMillis()) {
+            return false;
+        }
+        ActCountParam param = new ActCountParam(appActManageVO.getId().intValue(), true)
+                .setStartTime(appActManageVO.getStartTime())
+                .setEndTime(appActManageVO.getEndTime());
+        int totalActCount = cacheSqlManager.getActCount(param);
+        if (appActManageVO.getLimitTimeNum() != null && appActManageVO.getLimitTimeNum() > 0 &&
+                totalActCount >= appActManageVO.getLimitTimeNum()) {
+            return false;
+        }
+        param.setUserId(userId);
+        int actCount = cacheSqlManager.getActCount(param);
+        appActManageVO.setLimitTimeNum(null);
+        return actCount == 0;
+    }
+
+    @Override
+    public Map<String, List<AppCarouselPictureVO>> getBannerByType(List<String> types) {
+        List<AppCarouselPicture> banners = cacheSqlManager.getBannerByType(types);
+        if (CollectionUtils.isEmpty(banners)) {
+            return new HashMap<>();
+        }
+        Map<String, List<AppCarouselPictureVO>> appCarouselPictureVOS = banners.stream()
+                .map(b -> DozerUtils.map(b, AppCarouselPictureVO.class))
+                .collect(Collectors.groupingBy(AppCarouselPictureVO::getType));
+        if (log.isDebugEnabled()) {
+            log.debug("appCarouselPictureVOS={}", JSON.toJSONString(appCarouselPictureVOS));
+        }
+        return appCarouselPictureVOS;
+    }
+
+    @Override
+    public String getOverPicture() {
+        String overPicture = cacheSqlManager.getOverPicture();
+        if (log.isDebugEnabled()) {
+            log.debug("overPicture={}", overPicture);
+        }
+        return overPicture;
+    }
+
+    @Override
+    public List<AppActAdVO> getAppActAd(Integer userId) {
+        List<AppActAdVO> appActAdVOS = new ArrayList<>();
+        List<TzyCardTaskRemind> taskRemind = cacheRedisManager.getTaskRemind(userId);
+        List<Long> taskIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(taskRemind)) {
+            for (TzyCardTaskRemind remind : taskRemind) {
+                AppActAdVO appActAdVO = AppActAdVO.builder()
+                        .actImg(remind.getImgUrl())
+                        .imgType("0")
+                        .actUrl("/pageC/myCoupon/couponList")
+                        .clickType(0)
+                        .couponIds("10")
+                        .lastTime(5)
+                        .build();
+                appActAdVOS.add(appActAdVO);
+                taskIds.add(remind.getId());
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("用户提醒={}", JSON.toJSONString(appActAdVOS));
+        }
+        if (CollectionUtils.isNotEmpty(taskIds)) {
+            CompletableFuture.runAsync(() -> cacheRedisManager.updateTaskRemind(userId, taskIds));
+        }
+        return appActAdVOS;
+    }
+
+    @Override
+    public Pair<AppActAdVO, List<AppActAdVO>> getOpenAd(Integer userId, List<AppActAdVO> actList) {
+        List<AppActConfig> appActConfigs = getAppActConfigs(userId);
+        if (log.isDebugEnabled()) {
+            log.debug("过滤后数据={}", JSON.toJSONString(appActConfigs));
+        }
+        if (Objects.isNull(appActConfigs)) {
+            return null;
+        }
+        Map<String, List<AppActConfig>> groupActs =
+                appActConfigs.stream().filter(e -> StringUtils.isNotEmpty(e.getSubType()))
+                        .collect(Collectors.groupingBy(AppActConfig::getSubType));
+        //开屏广告
+        List<AppActConfig> open_ad = groupActs.get("open_ad");
+        //首页活动
+        List<AppActConfig> firstPageActs = groupActs.get("first_page");
+        List<AppActAdVO> appActAdVOS = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(firstPageActs)) {
+            List<AppActAdVO> collect = firstPageActs.stream().filter(act -> checkActFilter(act, userId))
+                    .map(act -> DozerUtils.map(act, AppActAdVO.class)).collect(Collectors.toList());
+            appActAdVOS.addAll(collect);
+        }
+        if (CollectionUtils.isNotEmpty(actList)) {
+            appActAdVOS.addAll(actList);
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("两部分合并={}", JSON.toJSONString(appActAdVOS));
+        }
+        AppActAdVO appActAdVO = null;
+        if (CollectionUtils.isNotEmpty(open_ad)) {
+            appActAdVO = DozerUtils.map(open_ad.get(0), AppActAdVO.class);
+        }
+        return new ImmutablePair<>(appActAdVO, appActAdVOS);
+    }
+
+    private List<AppActConfig> getAppActConfigs(Integer userId) {
+        List<AppActConfig> appActConfigs = cacheRedisManager.getAppActConfigs();
+        if (CollectionUtils.isNotEmpty(appActConfigs)) {
+            int currentHour = DateUtils.getCurrentHour();
+            Date now = new Date();
+            return appActConfigs.stream().filter(act -> {
+                if (now.before(act.getStartTime()) || now.after(act.getEndTime())) {
+                    return false;
+                }
+                if (currentHour < act.getStartHour() || currentHour >= act.getEndHour()) {
+                    return false;
+                }
+                if (act.getCatId() != null && act.getCatId() > 0) {
+                    List<Long> userIds = cacheSqlManager.getUserIdByCatId(act.getCatId());
+                    return CollectionUtils.isNotEmpty(userIds) && userIds.contains(userId.longValue());
+                }
+                return true;
+            }).collect(Collectors.toList());
+        }
+        return appActConfigs;
+    }
+
+    private boolean checkActFilter(AppActConfig act, Integer userId) {
+        try {
+            boolean isRemind = act.getRemindTime() > 0;
+            String key = String.format(RedisKeyConstants.ACT_REMIND_CACHE_USERID, act.getId(), userId);
+            if (isRemind && redisManager.hasKey(key)) {
+                //限制时间内不再提示
+                return false;
+            }
+            boolean needLogin = act.getHistoryLimitDay() > 0 || act.getUserGrowth() > 0;
+            //判断条件
+            if (!needLogin) {
+                if (isRemind) {
+                    redisManager.set(key, 1, act.getRemindTime() * 3600);
+                }
+                return true;
+            }
+
+            boolean buyFlag = true;
+            if (act.getHistoryLimitDay() > 0) {
+                int buyOrderCount = cacheSqlManager.getBuyOrderCount(userId, act.getHistoryLimitDay());
+                if (buyOrderCount == 0) {
+                    buyFlag = false;
+                }
+            }
+
+            boolean growthFlag = true;
+            if (act.getUserGrowth() > 0) {
+                AppUserInfoDto user = cacheSqlManager.searchUserInfoById(userId);
+                if (user.getGrowthNum() < act.getUserGrowth() * 100) {
+                    growthFlag = false;
+                }
+            }
+            boolean reminderFlag = act.getOp() == 0 ? buyFlag || growthFlag : buyFlag && growthFlag;
+            if (reminderFlag && StringUtils.isNotEmpty(act.getCouponIds())) {
+                int userCouponCount = cacheSqlManager.getUserCouponCount(userId,
+                        Arrays.asList(act.getCouponIds().split(",")));
+                if (userCouponCount > 0) {
+                    return false;
+                }
+            }
+            log.debug("用户={},reminderFlag={},isRemind={}", userId, reminderFlag, isRemind);
+            if (reminderFlag && isRemind) {
+                redisManager.set(key, 1, act.getRemindTime() * 3600);
+            }
+            return reminderFlag;
+        } catch (Exception e) {
+            log.error("checkActFilter error", e);
+            return false;
+        }
+    }
+}

+ 80 - 0
micro-service/src/main/java/com/poyee/service/impl/DictServiceImpl.java

@@ -0,0 +1,80 @@
+package com.poyee.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.poyee.common.constant.Constants;
+import com.poyee.common.domain.entity.SysDictData;
+import com.poyee.manager.CacheSqlManager;
+import com.poyee.service.DictService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class DictServiceImpl implements DictService {
+    @Resource
+    private CacheSqlManager cacheSqlManager;
+    @Override
+    public HashMap<String, List<SysDictData>> getDict(List<String> types, String label, String status) {
+        String sqlStatus;
+        if (StringUtils.isEmpty(status)) {
+            sqlStatus = Constants.STATUS_OK;
+        } else if (Constants.All.equals( status)) {
+            sqlStatus = null;
+        } else {
+            sqlStatus = status;
+        }
+        HashMap<String, List<SysDictData>> dictDataMap = new HashMap<>();
+        for (String type : types) {
+            List<SysDictData> dictDataList = cacheSqlManager.getDict(type);
+            List<SysDictData> collect = dictDataList.stream().filter(dictData ->
+                            checkDictType(label, sqlStatus, dictData)).
+                    collect(Collectors.toList());
+            dictDataMap.put(type, collect);
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("dict result {},{}, {}, {}", JSON.toJSONString(types), label, sqlStatus, JSON.toJSONString(dictDataMap));
+        }
+        return dictDataMap;
+    }
+
+    @Override
+    public List<SysDictData> getDictByType(String type, String label, String status) {
+        String sqlStatus;
+        if (StringUtils.isEmpty(status)) {
+            sqlStatus = Constants.STATUS_OK;
+        } else if (Constants.All.equals( status)) {
+            sqlStatus = null;
+        } else {
+            sqlStatus = status;
+        }
+        List<SysDictData> dictDataList = cacheSqlManager.getDict(type);
+        List<SysDictData> collect = dictDataList.stream().filter(dictData ->
+                        checkDictType(label, sqlStatus, dictData)).
+                collect(Collectors.toList());
+        if (log.isDebugEnabled()) {
+            log.debug("collect result {},{}, {}, {}", type, label, sqlStatus, JSON.toJSONString(collect));
+        }
+        return collect;
+    }
+
+    /**
+     * 支持 查询label, status 关键子
+     * @param label
+     * @param staus
+     * @param sysDictData
+     * @return
+     */
+    private boolean checkDictType(String label, String staus, SysDictData sysDictData) {
+        if (StringUtils.isNotEmpty(label) && !label.equals(sysDictData.getDictLabel())) {
+            return false;
+        }
+        return StringUtils.isEmpty(staus) || sysDictData.getStatus().equals(staus);
+    }
+}

+ 215 - 0
pom.xml

@@ -0,0 +1,215 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+    <modules>
+        <module>micro-common</module>
+        <module>micro-dao</module>
+        <module>micro-manager</module>
+        <module>micro-service</module>
+        <module>web-controller</module>
+    </modules>
+
+	<groupId>com.poyee</groupId>
+	<artifactId>poyee-micro</artifactId>
+	<version>1.0.0</version>
+    <packaging>pom</packaging>
+    <name>poyee-micro</name>
+
+    <properties>
+        <sourceEncoding>UTF-8</sourceEncoding>
+        <java.version>1.8</java.version>
+        <mahout.version>0.9</mahout.version>
+        <dozer.version>6.5.2</dozer.version>
+        <bee.version>1.17</bee.version>
+        <log.version>1.2.17</log.version>
+        <lombok.version>1.18.34</lombok.version>
+        <fastjson.version>2.0.10</fastjson.version>
+        <redis.version>3.5.0</redis.version>
+        <mybatis.boot>2.1.3</mybatis.boot>
+        <druid.version>1.2.4</druid.version>
+        <mybatis.version>3.5.5</mybatis.version>
+        <mybatis.spring>2.0.7</mybatis.spring>
+        <postgresql.version>42.6.0</postgresql.version>
+        <janino.version>3.0.12</janino.version>
+        <logappender.version>1.8.5</logappender.version>
+        <logfluent.version>0.3.4</logfluent.version>
+    </properties>
+
+	<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-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.micrometer</groupId>
+            <artifactId>micrometer-registry-prometheus</artifactId>
+        </dependency>
+        <!-- SpringBoot 拦截器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>2.2.5.RELEASE</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.poyee</groupId>
+                <artifactId>micro-common</artifactId>
+                <version>1.0.0</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.poyee</groupId>
+                <artifactId>micro-dao</artifactId>
+                <version>1.0.0</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.poyee</groupId>
+                <artifactId>micro-manager</artifactId>
+                <version>1.0.0</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.poyee</groupId>
+                <artifactId>micro-service</artifactId>
+                <version>1.0.0</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.poyee</groupId>
+                <artifactId>web-controller</artifactId>
+                <version>1.0.0</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>${lombok.version}</version>
+                <scope>provided</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>com.github.dozermapper</groupId>
+                <artifactId>dozer-core</artifactId>
+                <version>${dozer.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>log4j</groupId>
+                <artifactId>log4j</artifactId>
+                <version>${log.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+            <!--七牛云存储-->
+            <dependency>
+                <groupId>com.qiniu</groupId>
+                <artifactId>qiniu-java-sdk</artifactId>
+                <version>[7.8.0, 7.8.99]</version>
+            </dependency>
+
+            <!-- MyBatis Spring Boot Starter -->
+            <dependency>
+                <groupId>org.mybatis.spring.boot</groupId>
+                <artifactId>mybatis-spring-boot-starter</artifactId>
+                <version>${mybatis.boot}</version>
+            </dependency>
+            <!--阿里数据库连接池 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.postgresql</groupId>
+                <artifactId>postgresql</artifactId>
+                <version>${postgresql.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.redisson</groupId>
+                <artifactId>redisson</artifactId>
+                <version>${redis.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.mybatis</groupId>
+                <artifactId>mybatis</artifactId>
+                <version>${mybatis.version}</version>
+            </dependency>
+
+            <!-- 不变组件-->
+            <dependency>
+                <groupId>com.github.xiaoymin</groupId>
+                <artifactId>knife4j-spring-boot-starter</artifactId>
+                <version>2.0.9</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>io.springfox</groupId>
+                        <artifactId>springfox-core</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-swagger2</artifactId>
+                <version>2.10.5</version>
+            </dependency>
+            <dependency>
+                <groupId>io.swagger</groupId>
+                <artifactId>swagger-annotations</artifactId>
+                <version>1.5.21</version>
+            </dependency>
+            <dependency>
+                <groupId>io.swagger</groupId>
+                <artifactId>swagger-models</artifactId>
+                <version>1.5.21</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${sourceEncoding}</encoding>
+                    <compilerArgs>
+                        <arg>-Xlint:unchecked</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 66 - 0
web-controller/pom.xml

@@ -0,0 +1,66 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.poyee</groupId>
+		<artifactId>poyee-micro</artifactId>
+        <version>1.0.0</version>
+	</parent>
+
+	<artifactId>web-controller</artifactId>
+	<version>1.0.0</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.poyee</groupId>
+            <artifactId>micro-service</artifactId>
+        </dependency>
+
+        <!-- logback if解析 -->
+        <dependency>
+            <groupId>org.codehaus.janino</groupId>
+            <artifactId>janino</artifactId>
+            <version>3.0.12</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sndyuk</groupId>
+            <artifactId>logback-more-appenders</artifactId>
+            <version>1.8.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.fluentd</groupId>
+            <artifactId>fluent-logger</artifactId>
+            <version>0.3.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 20 - 0
web-controller/src/main/java/com/poyee/SvrApplication.java

@@ -0,0 +1,20 @@
+package com.poyee;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+@MapperScan("com.poyee.**.mapper")
+@EnableCaching
+@EnableAspectJAutoProxy(proxyTargetClass = true)
+@SpringBootApplication(scanBasePackages = {"com.poyee"})
+public class SvrApplication {
+    public static void main(String[] args) {
+        System.out.println("SvrApplication start...");
+        SpringApplication.run(SvrApplication.class, args);
+        System.out.println("SvrApplication end...");
+    }
+}
+

+ 174 - 0
web-controller/src/main/java/com/poyee/controller/AppCommonController.java

@@ -0,0 +1,174 @@
+package com.poyee.controller;
+
+
+import com.poyee.common.constant.RetConstants;
+import com.poyee.common.domain.entity.SysDictData;
+import com.poyee.common.domain.vo.AppActAdVO;
+import com.poyee.common.domain.vo.AppActManageVO;
+import com.poyee.common.domain.vo.AppCarouselPictureVO;
+import com.poyee.common.dto.InDto;
+import com.poyee.common.dto.OutDTO;
+import com.poyee.common.dto.UserInfo;
+import com.poyee.common.utils.UserUtils;
+import com.poyee.service.BusService;
+import com.poyee.service.DictService;
+import lombok.extern.slf4j.Slf4j;
+import io.swagger.annotations.Api;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * 抽取APP部分接口
+ * @author: zhenhua.bian
+ * @date: 2025/10/26
+ */
+
+@Api(value = "app通用接口", tags = "app通用接口")
+@Slf4j
+@RestController
+@RequestMapping("/api/micro")
+public class AppCommonController {
+    @Resource
+    private DictService dictService;
+
+    @Resource
+    private BusService busService;
+
+    /**
+     * 根据type获取字典数据
+     * @param inDto
+     * @return
+     */
+    @PostMapping("/getDict")
+    public OutDTO getDict(@RequestBody InDto inDto) {
+        try {
+            String type = inDto.getString("type");
+            if (StringUtils.isEmpty(type)) {
+                return OutDTO.error500("参数错误");
+            }
+            //支持逗号分隔
+            List<String> types = Arrays.asList(type.split(","));
+            HashMap<String, List<SysDictData>> dictDataMap = dictService.getDict(types, null, inDto.getString("status"));
+            return OutDTO.ok().put("typeData", dictDataMap);
+        } catch (Exception e) {
+            log.error("getDict error", e);
+            return OutDTO.error500("系统异常");
+        }
+    }
+
+    /**
+     * 查询七牛云token
+     * @return
+     */
+    @PostMapping("/getQnToken")
+    @ResponseBody
+    public OutDTO getQnToken() {
+        try {
+            String token = busService.getQiNiuToken();
+            if (StringUtils.isEmpty(token)) {
+                return OutDTO.errorRet(RetConstants.ERROR_NOT_FOUND);
+            }
+            return OutDTO.ok().put("token", token);
+        } catch (Exception e) {
+            log.error("getQnToken error", e);
+            return OutDTO.error500("系统异常");
+        }
+    }
+
+    /**
+     * 查询版本号
+     * @param inDto
+     * @return
+     */
+    @PostMapping("/getLastVersion")
+    @ResponseBody
+    public OutDTO getLastVersion(@RequestBody InDto inDto) {
+        try {
+            String version = inDto.getVersion();
+            String phoneType = inDto.getString("type");
+            Map<String, Object> appVersion = busService.getAppVersion(version, phoneType);
+            Map<String, Object> storeVersion = busService.getStoreVersion(version, phoneType);
+            return OutDTO.ok().put("storeUpdate", storeVersion).put("hotUpdateShow", appVersion);
+        } catch (Exception e) {
+            log.error("getLastVersion error", e);
+            return OutDTO.error500("系统异常");
+        }
+    }
+
+    /**
+     * 获取首页红包
+     * @param inDto
+     * @return
+     */
+    @PostMapping("/getHomeRedPacket")
+    @ResponseBody
+    public OutDTO getHomeRedPacket(@RequestBody InDto inDto) {
+        try {
+            UserInfo userInfo = UserUtils.getSimpleUserInfo(true);
+            if (Objects.isNull(userInfo) || Objects.isNull(userInfo.getId())) {
+                return OutDTO.error500("请先登陆!");
+            }
+            List<AppActManageVO> actList = busService.getActList(userInfo.getId());
+            return OutDTO.ok().put("acts", actList);
+        } catch (Exception e) {
+
+            return OutDTO.error500("系统异常");
+        }
+    }
+
+    /**
+     * 获取banner
+     * @param inDto
+     * @return
+     */
+    @PostMapping("/getBanner")
+    @ResponseBody
+    public OutDTO getBanner(@RequestBody InDto inDto) {
+        try {
+            String type = inDto.getString("type");
+            if (StringUtils.isEmpty(type)) {
+                return OutDTO.error500("参数为空!");
+            }
+            //banner
+            Map<String, List<AppCarouselPictureVO>> banners = busService.getBannerByType(Arrays.asList(type.split(",")));
+            //售罄底图
+            String overPicture = busService.getOverPicture();
+            return OutDTO.ok().put("banner", banners)
+                    .put("ratePic", overPicture);
+        } catch (Exception e) {
+            log.error("getBanner error", e);
+            return OutDTO.error500("系统异常");
+        }
+    }
+
+    /**
+     * 获取开屏广告
+     * @param inDto
+     * @return
+     */
+    @PostMapping("/getAppAct")
+    @ResponseBody
+    public OutDTO getAppActAd(@RequestBody InDto inDto) {
+        try {
+            Integer userId = inDto.getUserId();
+            if (Objects.isNull(userId) || userId <= 0) {
+                return OutDTO.error500("请先登陆!");
+            }
+            List<AppActAdVO> actList = busService.getAppActAd(userId);
+            Pair<AppActAdVO, List<AppActAdVO>> openAd = busService.getOpenAd(userId, actList);
+            if (Objects.isNull(openAd)) {
+                return OutDTO.ok().put("page_act", actList);
+            } else {
+                return OutDTO.ok().put("page_act", openAd.getValue())
+                        .put("open_act", openAd.getKey());
+            }
+        } catch (Exception e) {
+            log.error("getAppAct error", e);
+            return OutDTO.error500("系统异常");
+        }
+    }
+}

+ 16 - 0
web-controller/src/main/java/com/poyee/controller/DeploymentController.java

@@ -0,0 +1,16 @@
+package com.poyee.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RestController
+@RequestMapping
+public class DeploymentController {
+
+    @RequestMapping("/health")
+    public void check(){
+        //checkMq();
+    }
+
+}

+ 75 - 0
web-controller/src/main/resources/application-prod.yml

@@ -0,0 +1,75 @@
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为80
+  port: 80
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # tomcat最大线程数,默认为200
+    max-threads: 800
+    # Tomcat启动初始化的线程数,默认值25
+    min-spare-threads: 30
+    #超时时间
+    connection-timeout: 600000
+    basedir: /tmp/logs
+    accesslog:
+      enabled: true
+      buffered: true
+      prefix: access_log
+      file-date-format: .yyyy-MM-dd
+
+
+# 日志配置
+logging:
+  console.enabled: ${CONSOLE_ENABLED:true}
+  file.enabled: ${FILE_ENABLED:false}
+  level:
+    com.tzy: info
+    org.springframework: warn
+  fluentd:
+    enabled: ${FLUENTD_ENABLED:false}
+    host: ${FLUENTD_HOST:127.0.0.1}
+    port: ${FLUENTD_PORT:24225}
+
+# Spring配置
+spring:
+  jackson:
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+  profiles:
+    active: druid
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size:  50MB
+      # 设置总上传的文件大小
+      max-request-size:  50MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  redis:
+    database: 1
+    host: ${REDIS_HOST:172.29.19.234}
+    #host: hobbystock.cn
+    port: ${REDIS_PORT:6379}
+    password: #Pass2021    # 密码(默认为空)
+    timeout: 60000  # 连接超时时长(毫秒)
+    pool:
+      max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
+      max-wait: -1ms    # 连接池最大阻塞等待时间(使用负值表示没有限制)
+      max-idle: 10      # 连接池中的最大空闲连接
+      min-idle: 5       # 连接池中的最小空闲连接
+
+# MyBatis
+mybatis:
+  # 搜索指定包别名
+  typeAliasesPackage: com.tzy.**.domain
+  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 加载全局的配置文件
+  configLocation: classpath:mybatis/mybatis-config.xml
+

+ 111 - 0
web-controller/src/main/resources/application.yml

@@ -0,0 +1,111 @@
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为80
+  port: 8082
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # tomcat最大线程数,默认为200
+    max-threads: 800
+    # Tomcat启动初始化的线程数,默认值25
+    min-spare-threads: 30
+    #超时时间
+    connection-timeout: 600000
+    accesslog:
+      enabled: true
+      buffered: true
+      prefix: access_log
+      file-date-format: .yyyy-MM-dd
+
+
+# 日志配置
+logging:
+  console.enabled: ${CONSOLE_ENABLED:true}
+  file.enabled: ${FILE_ENABLED:false}
+  level:
+    com.poyee: debug
+    org.teasoft: debug
+    org.springframework: warn
+    feign:
+      client:
+        config:
+          default: info
+  fluentd:
+    enabled: ${FLUENTD_ENABLED:false}
+    host: ${FLUENTD_HOST:127.0.0.1}
+    port: ${FLUENTD_PORT:24225}
+  audit:
+    enabled: ${AUDIT_ENABLED:false}
+    host: ${AUDIT_HOST:192.168.1.51}
+    port: ${AUDIT_PORT:24225}
+  bee:
+    enabled: true
+
+# Spring配置
+spring:
+  application:
+    name: app-micro
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: org.postgresql.Driver
+    url: jdbc:postgresql://192.168.50.8:5432/ahx_app
+    username: postgres
+    password: 123456
+  redis:
+    database: 1
+    host: 192.168.50.8
+    #host: hobbystock.cn
+    port: 6379
+    password: Pass2010    # 密码(默认为空)
+    timeout: 60000  # 连接超时时长(毫秒)
+    pool:
+      max-active: 100  # 连接池最大连接数(使用负值表示没有限制)
+      max-wait: -1ms    # 连接池最大阻塞等待时间(使用负值表示没有限制)
+      max-idle: 10      # 连接池中的最大空闲连接
+      min-idle: 5       # 连接池中的最小空闲连接
+
+# MyBatis
+mybatis:
+  # 搜索指定包别名
+  typeAliasesPackage: com.poyee.**.domain
+ # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include:
+          - health
+          - info
+          - metrics
+          - rabbit
+          - redis
+          - prometheus
+  endpoint:
+    health.show-details: never
+    metrics:
+      enabled: true
+    prometheus:
+      enabled: true
+  metrics:
+    export:
+      prometheus:
+        enabled: true
+        step: 1ms
+        descriptions: true
+  tags:
+    application: poyee-micro
+
+  health:
+    defaults.enabled: false
+    db.enabled: true
+    diskspace.enabled: true
+
+# knife4j 配置
+knife4j:
+  # 是否开启 knife4j
+  enabled: true
+  #生产模式屏蔽
+  production: true

+ 11 - 0
web-controller/src/main/resources/dozer/dozer-mapping.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
+    <configuration>
+        <!--失败不抛出异常,继续转下一个字段-->
+        <stop-on-errors>false</stop-on-errors>
+        <!--排除映射空值-->
+        <map-null>false</map-null>
+    </configuration>
+</mappings>

+ 21 - 0
web-controller/src/main/resources/logback-fluentd.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<included>
+    <appender name="FLUENT_SYNC" class="ch.qos.logback.more.appenders.DataFluentAppender">
+        <tag>logback</tag>
+        <label>poyee-micro.${hostname}</label>
+        <remoteHost>${logging.fluentd.host}</remoteHost>
+        <port>${logging.fluentd.port}</port>
+
+        <encoder charset="UTF-8">
+            <pattern>%logger{15}:%L - %msg</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="FLUENT" class="ch.qos.logback.classic.AsyncAppender">
+        <queueSize>500</queueSize>
+        <neverBlock>true</neverBlock>
+        <maxFlushTime>15000</maxFlushTime>
+        <includeCallerData>false</includeCallerData>
+        <appender-ref ref="FLUENT_SYNC" />
+    </appender>
+</included>

+ 125 - 0
web-controller/src/main/resources/logback.xml

@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="../logs" />
+    <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%X{TRACE_ID}] [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+    <springProperty scope="context" name="logging.console.enabled" source="logging.console.enabled"/>
+    <springProperty scope="context" name="logging.file.enabled" source="logging.file.enabled"/>
+    <springProperty scope="context" name="logging.fluentd.enabled" source="logging.fluentd.enabled"/>
+    <springProperty scope="context" name="logging.fluentd.host" source="logging.fluentd.host"/>
+    <springProperty scope="context" name="logging.fluentd.port" source="logging.fluentd.port"/>
+
+    <define name="hostname" class="com.poyee.common.utils.HostPropertyDefiner"/>
+
+    <if condition='p("logging.fluentd.enabled").equals("true")'>
+        <then>
+            <include resource="logback-fluentd.xml" />
+        </then>
+    </if>
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+	
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+	
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+	
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <if condition='p("logging.console.enabled").equals("true")'>
+            <then>
+                <appender-ref ref="console" />
+            </then>
+        </if>
+        <if condition='p("logging.file.enabled").equals("true")'>
+            <then>
+                <appender-ref ref="file_info" />
+                <appender-ref ref="file_error" />
+            </then>
+        </if>
+        <if condition='p("logging.fluentd.enabled").equals("true")'>
+            <then>
+                <appender-ref ref="FLUENT"/>
+            </then>
+        </if>
+    </root>
+
+    <!-- 系统模块日志级别控制  -->
+    <logger name="com.ruoyi" level="info" />
+    <!-- Spring日志级别控制  -->
+    <logger name="org.springframework" level="warn" />
+
+<!--    <logger name="druid.sql" level="debug" />-->
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <if condition='p("logging.file.enabled").equals("true")'>
+            <then>
+                <appender-ref ref="sys-user"/>
+            </then>
+        </if>
+    </logger>
+</configuration>