zwhui преди 1 година
родител
ревизия
ddcc5eaf06
променени са 25 файла, в които са добавени 2512 реда и са изтрити 0 реда
  1. 212 0
      wholesale/pom.xml
  2. 69 0
      wholesale/src/main/java/com/yhlxj/Application.java
  3. 40 0
      wholesale/src/main/java/com/yhlxj/dao/MyMetaObjectHandler.java
  4. 37 0
      wholesale/src/main/java/com/yhlxj/dao/MybatisPlusConfig.java
  5. 11 0
      wholesale/src/main/java/com/yhlxj/dao/mapper/WebInfoMapper.java
  6. 36 0
      wholesale/src/main/java/com/yhlxj/dao/model/BaseEntity.java
  7. 66 0
      wholesale/src/main/java/com/yhlxj/dao/model/dto/Result.java
  8. 28 0
      wholesale/src/main/java/com/yhlxj/dao/model/entity/WebInfo.java
  9. 35 0
      wholesale/src/main/java/com/yhlxj/dao/model/response/SubmitResult.java
  10. 794 0
      wholesale/src/main/java/com/yhlxj/redis/RedisService.java
  11. 42 0
      wholesale/src/main/java/com/yhlxj/service/WebInfoService.java
  12. 40 0
      wholesale/src/main/java/com/yhlxj/service/common/EnvCommonService.java
  13. 141 0
      wholesale/src/main/java/com/yhlxj/service/impl/WebInfoServiceImpl.java
  14. 15 0
      wholesale/src/main/java/com/yhlxj/service/task/Scheduler.java
  15. 55 0
      wholesale/src/main/java/com/yhlxj/util/IpUtils.java
  16. 110 0
      wholesale/src/main/java/com/yhlxj/util/SpringCtxUtils.java
  17. 131 0
      wholesale/src/main/java/com/yhlxj/web/GlobalExceptionHandler.java
  18. 29 0
      wholesale/src/main/java/com/yhlxj/web/WholesaleController.java
  19. 52 0
      wholesale/src/main/java/com/yhlxj/web/config/JacksonConfig.java
  20. 19 0
      wholesale/src/main/java/com/yhlxj/web/config/WebSocketConfiguration.java
  21. 334 0
      wholesale/src/main/java/com/yhlxj/web/util/StpUserUtil.java
  22. 0 0
      wholesale/src/main/resources/application-dev.yml
  23. 0 0
      wholesale/src/main/resources/application-prd.yml
  24. 111 0
      wholesale/src/main/resources/config/logback-debug.xml
  25. 105 0
      wholesale/src/main/resources/config/logback.xml

+ 212 - 0
wholesale/pom.xml

@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.netflix</groupId>
+    <artifactId>wholesale</artifactId>
+    <packaging>jar</packaging>
+
+
+    <properties>
+        <java.version>11</java.version>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <io-undertow.version>2.0.30.Final</io-undertow.version>
+        <xnio-nio.version>3.7.7.Final</xnio-nio.version>
+    </properties>
+
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-json</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.hibernate.validator</groupId>
+                    <artifactId>hibernate-validator</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.undertow</groupId>
+                    <artifactId>undertow-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>io.undertow</groupId>
+                    <artifactId>undertow-servlet</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.xnio</groupId>
+            <artifactId>xnio-nio</artifactId>
+            <version>${xnio-nio.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+            <version>${io-undertow.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.xnio</groupId>
+                    <artifactId>xnio-nio</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.jboss.xnio</groupId>
+                    <artifactId>xnio-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+            <version>${io-undertow.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.undertow</groupId>
+                    <artifactId>undertow-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.netflix</groupId>
+            <artifactId>netflix-common</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15on</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.zxing</groupId>
+                    <artifactId>core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-test</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alipay.sdk</groupId>
+                    <artifactId>alipay-sdk-java</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-aop</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+            </exclusions>
+            <version>1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-dao-redis-jackson</artifactId>
+            <version>1.26.0</version>
+        </dependency>
+
+        <!-- sa-token -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-spring-boot-starter</artifactId>
+            <version>1.26.0</version>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>${start-class}</mainClass>
+                    <layout>ZIP</layout><!-- Replace with your main class -->
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArgument>-Xlint:unchecked</compilerArgument>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
+        <finalName>wholesale</finalName>
+    </build>
+
+</project>

+ 69 - 0
wholesale/src/main/java/com/yhlxj/Application.java

@@ -0,0 +1,69 @@
+package com.yhlxj;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import io.undertow.UndertowOptions;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
+
+@SpringBootApplication
+@EnableScheduling
+public class Application {
+
+	public static void main(String[] args) {
+		SpringApplication.run(Application.class, args);
+		System.out.println("=====running=====");
+	}
+
+
+	@Bean
+	public MethodValidationPostProcessor methodValidationPostProcessor (){
+		return new MethodValidationPostProcessor();
+	}
+
+	@Bean
+	public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
+		StringRedisTemplate template = new StringRedisTemplate(factory);
+		//定义key序列化方式
+		//RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型会出现异常信息;需要我们上面的自定义key生成策略,一般没必要
+		//定义value的序列化方式
+		Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+		ObjectMapper om = new ObjectMapper();
+		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+		om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
+				ObjectMapper.DefaultTyping.NON_FINAL,
+				JsonTypeInfo.As.WRAPPER_ARRAY);
+		jackson2JsonRedisSerializer.setObjectMapper(om);
+
+		// template.setKeySerializer(redisSerializer);
+		template.setValueSerializer(jackson2JsonRedisSerializer);
+		template.setHashValueSerializer(jackson2JsonRedisSerializer);
+		template.afterPropertiesSet();
+		return template;
+	}
+
+	/**
+	 * undertow 容器配置
+	 */
+	@Bean
+	public UndertowServletWebServerFactory factory() {
+		UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
+		// 开启http2 开启keep-alive 允许cookie最大化
+		factory.addBuilderCustomizers(builder ->
+				builder.setServerOption(UndertowOptions.ENABLE_HTTP2, false).
+						setServerOption(UndertowOptions.ALLOW_EQUALS_IN_COOKIE_VALUE, true).
+						setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, true));
+		return factory;
+	}
+}

+ 40 - 0
wholesale/src/main/java/com/yhlxj/dao/MyMetaObjectHandler.java

@@ -0,0 +1,40 @@
+package com.yhlxj.dao;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @className MyMetaObjectHandler
+ * @description
+ * @date 2020/7/29 2:44 下午
+ */
+@Component
+public class MyMetaObjectHandler implements MetaObjectHandler {
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        //根据属性名称设置值
+        this.setFieldValByName("createdTime",new Date(),metaObject);
+        this.setFieldValByName("updateTime",new Date(),metaObject);
+        //this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
+        //this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
+        /* 上面选其一使用,下面的已过时(注意 strictInsertFill 有多个方法,详细查看源码) */
+        //this.setFieldValByName("operator", "Jerry", metaObject);
+        //this.setInsertFieldValByName("operator", "Jerry", metaObject);
+
+    }
+
+    @Override
+    public void updateFill(MetaObject metaObject) {
+
+        this.setFieldValByName("updateTime", new Date(), metaObject);
+        //this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
+        //this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
+        /* 上面选其一使用,下面的已过时(注意 strictUpdateFill 有多个方法,详细查看源码) */
+        //this.setFieldValByName("operator", "Tom", metaObject);
+        //this.setUpdateFieldValByName("operator", "Tom", metaObject);
+    }
+}

+ 37 - 0
wholesale/src/main/java/com/yhlxj/dao/MybatisPlusConfig.java

@@ -0,0 +1,37 @@
+package com.yhlxj.dao;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @author chan
+ * @className MybatisConfig
+ * @date 2020/7/15 3:05 下午
+ */
+
+@EnableTransactionManagement
+@Configuration
+@MapperScan(basePackages = {"com.yhlxj.dao.mapper"})
+public class MybatisPlusConfig {
+
+    /**
+     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
+        return interceptor;
+    }
+
+    @Bean
+    public ConfigurationCustomizer configurationCustomizer() {
+        return configuration -> configuration.setUseDeprecatedExecutor(false);
+    }
+}

+ 11 - 0
wholesale/src/main/java/com/yhlxj/dao/mapper/WebInfoMapper.java

@@ -0,0 +1,11 @@
+package com.yhlxj.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yhlxj.dao.model.entity.WebInfo;
+
+/**
+ * @author zwhui
+ * @date 2025/6/3 18:03
+ */
+public interface WebInfoMapper extends BaseMapper<WebInfo> {
+}

+ 36 - 0
wholesale/src/main/java/com/yhlxj/dao/model/BaseEntity.java

@@ -0,0 +1,36 @@
+package com.yhlxj.dao.model;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @className BaseEntity
+ * @description
+ * @date 2020/7/29 2:28 下午
+ */
+@Data
+@Accessors(chain = true)
+public class BaseEntity {
+
+    @TableId(value = "id",type =IdType.AUTO)
+    private Long id;
+
+    /**
+     * 创建时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createdTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+}

+ 66 - 0
wholesale/src/main/java/com/yhlxj/dao/model/dto/Result.java

@@ -0,0 +1,66 @@
+package com.yhlxj.dao.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author chan
+ * @date 2021-03-22 8:48 下午
+ */
+@Data
+@NoArgsConstructor
+public class Result<T> {
+	/**
+	 * 错误码
+	 */
+	private Integer code;
+
+	/**
+	 * 信息, 一般为状态的描述
+	 */
+	private String msg;
+
+	/**
+	 * 调用成功失败
+	 */
+	private boolean flag;
+
+	/**
+	 * 传递的数据
+	 */
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	private T data;
+
+	/**
+	 * 构造函数
+	 *  @param code
+	 * @param msg
+	 * @param data
+	 */
+	public Result(@JsonProperty("code") Integer code,
+                  @JsonProperty("msg") String msg,
+                  @JsonProperty("flag") boolean flag,
+                  @JsonProperty("data") T data) {
+		this.code = code;
+		this.msg = msg;
+		this.flag = flag;
+		this.data = data;
+	}
+
+	/**
+	 * 静态工厂构造方法
+	 *
+	 * @param code 状态码
+	 * @param msg 错误信息
+	 * @param data DTO
+	 * @param <T>DTO类型
+	 * @return
+	 */
+	public static <T> Result<T> of(Integer code, String msg,boolean flag ,T data) {
+		return new Result<>(code, msg,flag,data);
+	}
+
+
+}

+ 28 - 0
wholesale/src/main/java/com/yhlxj/dao/model/entity/WebInfo.java

@@ -0,0 +1,28 @@
+package com.yhlxj.dao.model.entity;
+
+import com.yhlxj.dao.model.BaseEntity;
+import lombok.Data;
+
+
+/**
+ * @author zwhui
+ * @date 2025/6/3 17:27
+ */
+@Data
+public class WebInfo extends BaseEntity {
+    /**
+     * 网站前缀
+     */
+    private String prefix;
+
+    /**
+     * 账号
+     */
+    private String account;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+}

+ 35 - 0
wholesale/src/main/java/com/yhlxj/dao/model/response/SubmitResult.java

@@ -0,0 +1,35 @@
+package com.yhlxj.dao.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+public class SubmitResult {
+    /**
+     * 状态码: 1(提交成功), 22(排队中), other(错误)
+     */
+    private int code;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 任务ID
+     */
+    private String result;
+
+    //private Long instanceId;
+
+    @JsonIgnore
+    private Long apiChannelId = 1L;
+
+    /**
+     * 扩展字段
+     */
+    private Map<String, Object> properties = new HashMap<>();
+}

+ 794 - 0
wholesale/src/main/java/com/yhlxj/redis/RedisService.java

@@ -0,0 +1,794 @@
+package com.yhlxj.redis;
+
+import com.cyksj.common.util.StringUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.core.ZSetOperations;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * @description 定义常用的 Redis操作
+ * @author chan
+ * @date 2021-03-31 5:34 下午
+ */
+@Service
+@SuppressWarnings("all")
+public class RedisService {
+
+    @Resource
+    private RedisTemplate<String, Object> redisTemplate;
+
+    public static String env = "dev";
+
+    @Value("${spring.profiles.active}")
+    private String active;
+
+    @PostConstruct
+    public void init(){
+        env = active + ":";
+    }
+
+
+    /**
+     * 指定缓存失效时间
+     *
+     * @param key  键
+     * @param time 时间(秒)
+     * @return Boolean
+     */
+    public Boolean expire(String key, Long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除缓存
+     *
+     * @param key 可以传一个值 或多个
+     */
+    public void del(String... key) {
+        if (key != null && key.length > 0) {
+            if (key.length == 1) {
+                redisTemplate.delete(key[0]);
+            } else {
+                redisTemplate.delete(Arrays.asList(key));
+            }
+        }
+    }
+
+    /**
+     * 普通缓存获取
+     *
+     * @param key 键
+     * @return 值
+     */
+    public Object get(String key) {
+        return key == null ? null : redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * String缓存获取
+     * @param key 键
+     * @return 值
+     */
+    public String getStr(String key) {
+            return key == null ? null : StringUtil.getString(redisTemplate.opsForValue().get(key));
+    }
+
+    /**
+     * 普通缓存放入
+     *
+     * @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) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 递增
+     *
+     * @param key   键
+     * @param delta 要增加几(大于0)
+     * @return Long
+     */
+    public Long incr(String key, Long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递减
+     *
+     * @param key   键
+     * @param delta 要减少几
+     * @return Long
+     */
+    public Long decr(String key, Long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * HashSet
+     *
+     * @param key 键
+     * @param map 对应多个键值
+     * @return true 成功 false 失败
+     */
+    public Boolean hmset(String key, Map<Object, Object> map) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * HashSet 并设置时间
+     *
+     * @param key  键
+     * @param map  对应多个键值
+     * @param time 时间(秒)
+     * @return true成功 false失败
+     */
+    public Boolean hmset(String key, Map<Object, Object> map, Long time) {
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 向一张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) {
+            e.printStackTrace();
+            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 Double
+     */
+    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 Double
+     */
+    public Double hdecr(String key, String item, Double by) {
+        return redisTemplate.opsForHash().increment(key, item, -by);
+    }
+
+    /**
+     * 根据 key获取 Set中的所有值
+     *
+     * @param key 键
+     * @return Set
+     */
+    public Set<Object> sGet(String key) {
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 将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) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key 键
+     * @return Long
+     */
+    public Long sGetSetSize(String key) {
+        try {
+            return redisTemplate.opsForSet().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 移除值为value的
+     *
+     * @param key    键
+     * @param values 值 可以是多个
+     * @return 移除的个数
+     */
+    public Long setRemove(String key, Object... values) {
+        try {
+            return redisTemplate.opsForSet().remove(key, values);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 获取list缓存的内容
+     *
+     * @param key   键
+     * @param start 开始
+     * @param end   结束 0 到 -1代表所有值
+     * @return List
+     */
+    public List<Object> lGet(String key, Long start, Long end) {
+        try {
+            return redisTemplate.opsForList().range(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取list缓存的长度
+     *
+     * @param key 键
+     * @return Long
+     */
+    public Long lGetListSize(String key) {
+        try {
+            return redisTemplate.opsForList().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 通过索引 获取list中的值
+     *
+     * @param key   键
+     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;
+     *              index<0时,-1,表尾,-2倒数第二个元素,依次类推
+     * @return Object
+     */
+    public Object lGetIndex(String key, Long index) {
+        try {
+            return redisTemplate.opsForList().index(key, index);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lSet(String key, Object value) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return Boolean
+     */
+    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) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lSet(String key, List<Object> value) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return Boolean
+     */
+    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) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据索引修改list中的某条数据
+     *
+     * @param key   键
+     * @param index 索引
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean lUpdateIndex(String key, Long index, Object value) {
+        try {
+            redisTemplate.opsForList().set(key, index, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 移除N个值为value
+     *
+     * @param key   键
+     * @param count 移除多少个
+     * @param value 值
+     * @return 移除的个数
+     */
+    public Long lRemove(String key, Long count, Object value) {
+        try {
+            return redisTemplate.opsForList().remove(key, count, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    public boolean setNx(String key, Object value, Long time) {
+        if (time > 0) {
+            return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
+        }
+        return false;
+    }
+
+
+    /**
+     * 添加元素到ZSet
+     */
+    public Boolean zAdd(String key, double score, Object value) {
+        try {
+            return redisTemplate.opsForZSet().add(key, value, score);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    // 增加ZSet元素的分数
+    public Double zIncrementScore(String key, String value, double delta) {
+        try {
+            return redisTemplate.opsForZSet().incrementScore(key, value, delta);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+
+    // 封装获取ZSet分数操作
+    public Double zScore(String key, Object value) {
+        try {
+            return redisTemplate.opsForZSet().score(key, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    // 封装ZSet添加或更新分数操作
+    public Boolean zAddOrUpdateScore(String key, Object value, double score) {
+        try {
+            return redisTemplate.opsForZSet().add(key, value, score);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 获取ZSet的大小
+     */
+    public Long zCard(String key) {
+        try {
+            return redisTemplate.opsForZSet().zCard(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    /**
+     * 获取ZSet的大小
+     */
+    public Long zCount(String key, long start, long end) {
+        try {
+            return redisTemplate.opsForZSet().count(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    // 封装获取ZSet范围内成员的方法
+    public Set<Object> zRange(String key, long start, long end) {
+        try {
+            ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
+            return zSetOperations.range(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    /**
+     * 删除ZSet中分数范围内的元素
+     */
+    public Long zRemoveRangeByScore(String key, double min, double max) {
+        try {
+            return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+    /**
+     * 返回有序集 key 中,所有分数介于 min 和 max 之间(包括等于 min 或 max)的成员。
+     * 有序集成员按分数值递增(从小到大)次序排列。
+     * 此方法还支持限制返回的元素数量。
+     *
+     * @param key 有序集合的key
+     * @param min 分数范围的最小值
+     * @param max 分数范围的最大值
+     * @param offset 开始返回的索引位置
+     * @param count 返回的最大元素数量
+     * @return 介于最小值和最大值之间的成员的集合
+     */
+    public Set<Object> zRangeByScore(String key, double min, double max, long offset, long count) {
+        return redisTemplate.opsForZSet().rangeByScore(key, min, max, offset, count);
+    }
+
+    /**
+     * 从ZSet获取所有成员及其分数
+     * @param key ZSet的键
+     * @return ZSet中所有成员及其分数的集合
+     */
+    public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScores(String key, long start, long end){
+        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
+    }
+
+    /**
+     * 检查指定值是否存在于有序集合中
+     * @param key
+     * @param value
+     * @return
+     */
+    public boolean checkValueExistsInZSet(String key, String value) {
+        // 检查指定值是否存在于有序集合中
+        return redisTemplate.opsForZSet().score(key, value) != null;
+    }
+
+    /**
+     * 从ZSet中删除指定的成员
+     *
+     * @param key ZSet的键
+     * @param value 要删除的成员值
+     * @return 被成功移除的成员数量
+     */
+    public Long zRemove(String key, Object value) {
+        try {
+            return redisTemplate.opsForZSet().remove(key, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0L;
+        }
+    }
+
+
+
+
+    public Set<String> keys(String name) {
+        return redisTemplate.keys(name);
+    }
+
+    public String getSet(String key, String s) {
+        return StringUtil.getString(redisTemplate.opsForValue().getAndSet(key,s));
+    }
+
+    /**
+     * 尝试加锁
+     * @param lockKey 锁的键
+     * @param expireTime 锁的过期时间(秒)
+     * @return 是否成功获取锁
+     */
+    public boolean tryLock(String lockKey, long expireTime) {
+        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
+        Boolean success = ops.setIfAbsent(lockKey, "LOCKED", expireTime, TimeUnit.SECONDS);
+        return success != null && success;
+    }
+
+    /**
+     * 释放锁
+     * @param lockKey 锁的键
+     */
+    public void unlock(String lockKey) {
+        redisTemplate.delete(lockKey);
+    }
+
+    public void multiSet(Map<String, Object> keyValueMap) {
+        redisTemplate.opsForValue().multiSet(keyValueMap);
+    }
+
+    @AllArgsConstructor
+    @Getter
+    public enum key {
+       ;
+
+        private String name;
+
+        private String desc;
+
+        private long timeout;
+
+        public String getEnvName() {
+            return this.name + env;
+        }
+        public String getNameFormat(Object ... str) {
+            return String.format(this.getEnvName(), str);
+        }
+
+    }
+}

+ 42 - 0
wholesale/src/main/java/com/yhlxj/service/WebInfoService.java

@@ -0,0 +1,42 @@
+package com.yhlxj.service;
+
+import com.yhlxj.dao.model.entity.WebInfo;
+
+public interface WebInfoService {
+
+    /**
+     * 检查前缀是否存在
+     * @param prefix 网站前缀
+     * @return 是否存在
+     */
+    boolean checkPrefixExists(String prefix);
+
+    /**
+     * 检查账号是否存在
+     * @param account 账号
+     * @return 是否存在
+     */
+    boolean checkAccountExists(String account);
+
+    /**
+     * 保存WebInfo
+     * @param webInfo WebInfo对象
+     * @return 保存后的WebInfo对象
+     */
+    WebInfo saveWebInfo(WebInfo webInfo);
+
+    /**
+     * 更新WebInfo
+     * @param id ID
+     * @param webInfo WebInfo对象
+     * @return 更新后的WebInfo对象
+     */
+    WebInfo updateWebInfo(Long id, WebInfo webInfo);
+
+    /**
+     * 根据ID获取WebInfo
+     * @param id ID
+     * @return WebInfo对象
+     */
+    WebInfo getWebInfoById(Long id);
+}

+ 40 - 0
wholesale/src/main/java/com/yhlxj/service/common/EnvCommonService.java

@@ -0,0 +1,40 @@
+package com.yhlxj.service.common;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/*
+ *项目名: netflix
+ *文件名: EnvCommon
+ *创建者: JavaZou
+ *创建时间:2022/10/26 17:10
+ */
+@Component
+@Getter
+@Setter
+public class EnvCommonService {
+
+	public static final String active = "dev";
+
+	public static final String active_prd = "prd";
+
+	public static final String active_pre = "pre";
+
+	public static String DISTRIBUTE_DEFAULT_URL_PREFIX;
+
+	@Value(value = "${spring.profiles.active}")
+	private String env;
+
+	public Boolean isPrdEnv() {
+		return EnvCommonService.active_prd.equals(getEnv());
+	}
+
+	public Boolean isPreEnv() {
+		return EnvCommonService.active_pre.equals(getEnv());
+	}
+
+}

+ 141 - 0
wholesale/src/main/java/com/yhlxj/service/impl/WebInfoServiceImpl.java

@@ -0,0 +1,141 @@
+package com.yhlxj.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.yhlxj.dao.mapper.WebInfoMapper;
+import com.yhlxj.dao.model.entity.WebInfo;
+import com.yhlxj.service.WebInfoService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.regex.Pattern;
+
+@Service
+@RequiredArgsConstructor
+public class WebInfoServiceImpl implements WebInfoService {
+    
+    private final WebInfoMapper webInfoMapper;
+    
+    // 密码正则表达式:必须包含字母和数字
+    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]+$");
+    
+
+    @Override
+    public boolean checkPrefixExists(String prefix) {
+        if (prefix == null || prefix.trim().isEmpty()) {
+            throw new IllegalArgumentException("网站前缀不能为空");
+        }
+        LambdaQueryWrapper<WebInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(WebInfo::getPrefix, prefix);
+        return webInfoMapper.selectCount(queryWrapper) > 0;
+    }
+    
+    @Override
+    public boolean checkAccountExists(String account) {
+        if (account == null || account.trim().isEmpty()) {
+            throw new IllegalArgumentException("账号不能为空");
+        }
+        LambdaQueryWrapper<WebInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(WebInfo::getAccount, account);
+        return webInfoMapper.selectCount(queryWrapper) > 0;
+    }
+    
+    /**
+     * 验证密码格式
+     * @param password 密码
+     * @throws IllegalArgumentException 如果密码格式不正确
+     */
+    private void validatePassword(String password) {
+        if (password == null || password.trim().isEmpty()) {
+            throw new IllegalArgumentException("密码不能为空");
+        }
+        if (password.length() < 6 || password.length() > 20) {
+            throw new IllegalArgumentException("密码长度必须在6-20个字符之间");
+        }
+        if (!PASSWORD_PATTERN.matcher(password).matches()) {
+            throw new IllegalArgumentException("密码必须包含字母和数字");
+        }
+    }
+    
+    /**
+     * 验证WebInfo对象
+     * @param webInfo WebInfo对象
+     * @throws IllegalArgumentException 如果对象验证失败
+     */
+    private void validateWebInfo(WebInfo webInfo) {
+        if (webInfo == null) {
+            throw new IllegalArgumentException("提交的数据不能为空");
+        }
+        if (webInfo.getPrefix() == null || webInfo.getPrefix().trim().isEmpty()) {
+            throw new IllegalArgumentException("网站前缀不能为空");
+        }
+        if (webInfo.getAccount() == null || webInfo.getAccount().trim().isEmpty()) {
+            throw new IllegalArgumentException("账号不能为空");
+        }
+        validatePassword(webInfo.getPassword());
+    }
+    
+    @Override
+    @Transactional
+    public WebInfo saveWebInfo(WebInfo webInfo) {
+        validateWebInfo(webInfo);
+        
+        // 检查前缀唯一性
+        if (checkPrefixExists(webInfo.getPrefix())) {
+            throw new IllegalArgumentException("网站前缀已存在");
+        }
+        
+        // 检查账号唯一性
+        if (checkAccountExists(webInfo.getAccount())) {
+            throw new IllegalArgumentException("账号已存在");
+        }
+        
+        webInfoMapper.insert(webInfo);
+        return webInfo;
+    }
+    
+    @Override
+    @Transactional
+    public WebInfo updateWebInfo(Long id, WebInfo webInfo) {
+        validateWebInfo(webInfo);
+        
+        // 查询原记录
+        WebInfo existingWebInfo = webInfoMapper.selectById(id);
+        if (existingWebInfo == null) {
+            throw new IllegalArgumentException("要更新的记录不存在");
+        }
+        
+        // 检查前缀唯一性(排除自身)
+        if (!existingWebInfo.getPrefix().equals(webInfo.getPrefix())) {
+            LambdaQueryWrapper<WebInfo> prefixQuery = new LambdaQueryWrapper<>();
+            prefixQuery.eq(WebInfo::getPrefix, webInfo.getPrefix())
+                    .ne(WebInfo::getId, id);
+            if (webInfoMapper.selectCount(prefixQuery) > 0) {
+                throw new IllegalArgumentException("网站前缀已被其他记录使用");
+            }
+        }
+        
+        // 检查账号唯一性(排除自身)
+        if (!existingWebInfo.getAccount().equals(webInfo.getAccount())) {
+            LambdaQueryWrapper<WebInfo> accountQuery = new LambdaQueryWrapper<>();
+            accountQuery.eq(WebInfo::getAccount, webInfo.getAccount())
+                    .ne(WebInfo::getId, id);
+            if (webInfoMapper.selectCount(accountQuery) > 0) {
+                throw new IllegalArgumentException("账号已被其他记录使用");
+            }
+        }
+        
+        webInfo.setId(id);
+        webInfoMapper.updateById(webInfo);
+        return webInfo;
+    }
+    
+    @Override
+    public WebInfo getWebInfoById(Long id) {
+        WebInfo webInfo = webInfoMapper.selectById(id);
+        if (webInfo == null) {
+            throw new IllegalArgumentException("记录不存在");
+        }
+        return webInfo;
+    }
+}

+ 15 - 0
wholesale/src/main/java/com/yhlxj/service/task/Scheduler.java

@@ -0,0 +1,15 @@
+package com.yhlxj.service.task;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class Scheduler {
+
+
+
+}

+ 55 - 0
wholesale/src/main/java/com/yhlxj/util/IpUtils.java

@@ -0,0 +1,55 @@
+package com.yhlxj.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.ResourceUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author chan
+ * @className IpUtils
+ * @description ip工具类
+ * @date 2020/11/12 1:39 下午
+ */
+public class IpUtils {
+
+    /**
+     * @Description:获取客户端的IP
+     * @author zrt
+     * @date 2018年9月22日 上午10:39:44
+     */
+    public static String getIpAddr(HttpServletRequest request) {
+        String ipAddress = request.getHeader("x-forwarded-for");
+        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getHeader("Proxy-Client-IP");
+        }
+        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+            ipAddress = request.getRemoteAddr();
+            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
+                //根据网卡取本机配置的IP
+                InetAddress inet = null;
+                try {
+                    inet = InetAddress.getLocalHost();
+                } catch (UnknownHostException e) {
+                    e.printStackTrace();
+                }
+                ipAddress = inet.getHostAddress();
+            }
+        }
+        //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
+        if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15
+            if (ipAddress.indexOf(",") > 0) {
+                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
+            }
+        }
+        return ipAddress;
+    }
+
+}

+ 110 - 0
wholesale/src/main/java/com/yhlxj/util/SpringCtxUtils.java

@@ -0,0 +1,110 @@
+package com.yhlxj.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * @ClassName SpringCtxUtils
+ * @Author chan
+ * @Date 2020-04-27 16:19
+ * @Description
+ */
+@Component
+public final class SpringCtxUtils implements ApplicationContextAware {
+
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringCtxUtils.context = applicationContext;
+    }
+
+    public static ApplicationContext getContext() {
+        return context;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param beanIdOrName bean name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException 异常
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String beanIdOrName) throws BeansException {
+        return StringUtils.isEmpty(beanIdOrName) ? null : (T) context.getBean(beanIdOrName);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clazz {@link Class}
+     * @return T
+     * @throws BeansException 异常
+     */
+    public static <T> T getBean(Class<T> clazz) throws BeansException {
+        return clazz == null ? null : (T) context.getBean(clazz);
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name bean name
+     * @return boolean
+     */
+    public static boolean containsBean(String name) {
+        return context.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name bean name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
+        return context.isSingleton(name);
+    }
+
+    /**
+     * @param name bean name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
+        return context.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name bean name
+     * @return String array
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
+        return context.getAliases(name);
+    }
+
+    /**
+     * <pre>
+     *     静默获取bean,无视异常
+     * </pre>
+     *
+     * @param clazz
+     * @param <T>
+     * @return
+     */
+    public static <T> T getBeanQuietly(Class<T> clazz) {
+        try {
+            return clazz == null ? null : (T) context.getBean(clazz);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

+ 131 - 0
wholesale/src/main/java/com/yhlxj/web/GlobalExceptionHandler.java

@@ -0,0 +1,131 @@
+package com.yhlxj.web;
+
+import cn.hutool.core.lang.Validator;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.enums.GatewayResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.exceptions.PersistenceException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @description 异常全局拦截
+ * @author chan
+ * @date 2021-03-22 9:51 下午
+ */
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    @Autowired
+    protected HttpServletRequest request;
+
+    private final static List<String> token = List.of("token无效", "token已过期");
+
+    @ExceptionHandler(value = {Exception.class})
+    public Result<String> handleNoteException(Exception e) {
+        StringBuilder builder = new StringBuilder(32);
+        builder.append(request.getRequestURI()).append(" -- > ");
+
+        StackTraceElement[] trace = e.getStackTrace();
+        log.info("{}",e);
+        for (StackTraceElement element : trace) {
+            if (StringUtil.startsWith(element.getClassName(), "com.yhlxj")) {
+                builder.append(element.getFileName())
+                        .append("[").append(element.getLineNumber()).append("]")
+                        .append("&");
+            }
+        }
+        builder.deleteCharAt(builder.length() - 1);
+
+        String message = e.getMessage();
+        String value = builder.toString();
+        GatewayApiCode apiCode = null;
+        if (e instanceof BusinessRuntimeException) {
+            BusinessRuntimeException ee = (BusinessRuntimeException) e;
+            String code = ee.getCode();
+            if (Validator.isNumber(code)) {
+                if (GatewayApiCode.CMS_TOKEN_VALID.getCode().equals(Integer.parseInt(code))) {
+                    apiCode = GatewayApiCode.CMS_TOKEN_VALID;
+                }
+                if (apiCode != null) {
+                    return GatewayResponse.FAIL.newBuilder().buildGatewayCode(apiCode).toResult();
+                }else {
+                    return GatewayResponse.FAIL.newBuilder().setCode(Integer.valueOf(ee.getCode())).setMsg(message).toResult(value);
+                }
+            }
+        }
+
+        log.error("全局错误处理: \n Cause: {} \n Value: {}", message, value);
+        return GatewayResponse.FAIL.newBuilder().setMsg(message).toResult(value);
+    }
+
+    @ExceptionHandler(value = ConstraintViolationException.class)
+    public Result<String> ConstraintViolationException(ConstraintViolationException ex) {
+        String message = "";
+        // 使用TreeSet是为了让输出的内容有序输出(默认验证的顺序是随机的)
+        Set<String> errorInfoSet = new TreeSet<String>();
+        Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
+        if (!violations.isEmpty()) {
+            for (ConstraintViolation<?> item : violations) {
+                System.out.println(item.getPropertyPath());
+                // 遍历错误字段信息
+                errorInfoSet.add(item.getMessage());
+            }
+
+            StringBuilder sbf = new StringBuilder();
+            for (String errorInfo : errorInfoSet) {
+                sbf.append(errorInfo);
+                sbf.append(",");
+            }
+            message = sbf.substring(0, sbf.length() - 1);
+        }
+
+        log.error("错误字段 信息: \n Value: {}", message);
+
+        return GatewayResponse.FAIL.newBuilder().buildGatewayCode(GatewayApiCode.PARAMETER_MISSING_ERROR).setMsg(message).toResult();
+    }
+
+    @ExceptionHandler(BindException.class)
+    public Result<String> BindException(BindException bindingResult) {
+
+        // 验证参数信息是否有效
+        if (bindingResult.hasErrors()) {
+            // 获取错误字段信息集合
+            List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
+
+            // 使用TreeSet是为了让输出的内容有序输出(默认验证的顺序是随机的)
+            Set<String> errorInfoSet = new TreeSet<String>();
+            for (FieldError fieldError : fieldErrorList) {
+                // 遍历错误字段信息
+                errorInfoSet.add(fieldError.getDefaultMessage());
+            }
+
+            StringBuilder sbf = new StringBuilder();
+            for (String errorInfo : errorInfoSet) {
+                sbf.append(errorInfo);
+                sbf.append(",");
+            }
+            String message = sbf.substring(0, sbf.length() - 1);
+
+            log.error("验证参数信息是否有效 错误信息: \n Value: {}", message);
+
+            return GatewayResponse.FAIL.newBuilder().buildGatewayCode(GatewayApiCode.PARAMETER_MISSING_ERROR).setMsg(message).toResult();
+
+        }
+        return GatewayResponse.SUCCESS.newBuilder().buildGatewayCode(GatewayApiCode.SUCCESS).setMsg("参数校验通过").toResult();
+    }
+}

+ 29 - 0
wholesale/src/main/java/com/yhlxj/web/WholesaleController.java

@@ -0,0 +1,29 @@
+package com.yhlxj.web;
+
+import com.yhlxj.dao.model.dto.Result;
+import com.yhlxj.dao.model.entity.WebInfo;
+import com.yhlxj.service.WebInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author zwhui
+ * @date 2025/6/3 17:12
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/applets/wholesale")
+public class WholesaleController {
+    private final WebInfoService webInfoService;
+
+    @GetMapping("/test")
+    public String test() {
+        log.info("test");
+        return "test";
+    }
+
+
+
+}

+ 52 - 0
wholesale/src/main/java/com/yhlxj/web/config/JacksonConfig.java

@@ -0,0 +1,52 @@
+package com.yhlxj.web.config;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+
+/**
+ * @ClassName JacksonConfig
+ * @Author chan
+ * @Date 2020-04-24 15:21
+ * @Description json 转换
+ */
+@Configuration
+public class JacksonConfig {
+    @Bean
+    @Primary
+    @ConditionalOnMissingBean(ObjectMapper.class)
+    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
+        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
+        SimpleModule simpleModule = new SimpleModule();
+
+        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
+        objectMapper.registerModule(simpleModule);
+        simpleModule.addSerializer(BigDecimal.class, new JsonSerializer<>() {
+            @Override
+            public void serialize(BigDecimal decimal, JsonGenerator gen, SerializerProvider serializers)
+                    throws IOException {
+                gen.writeString(decimal.toPlainString());
+            }
+        });
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        objectMapper.setDateFormat(format);
+        objectMapper.registerModule(simpleModule);
+        //通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化,属性为NULL 不序列化
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        return objectMapper;
+    }
+
+}

+ 19 - 0
wholesale/src/main/java/com/yhlxj/web/config/WebSocketConfiguration.java

@@ -0,0 +1,19 @@
+package com.yhlxj.web.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+*@author chan
+*@date 2024/6/28 17:33
+*/
+@Configuration
+public class WebSocketConfiguration {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+}

+ 334 - 0
wholesale/src/main/java/com/yhlxj/web/util/StpUserUtil.java

@@ -0,0 +1,334 @@
+package com.yhlxj.web.util;
+
+import cn.dev33.satoken.fun.SaFunction;
+import cn.dev33.satoken.session.SaSession;
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpLogic;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2021/10/12 下午5:59
+ */
+@Component
+public class StpUserUtil {
+    public static final String TYPE = "user";
+
+    // 使用匿名子类 重写`stpLogic对象`的一些方法
+    public static StpLogic stpLogic = new StpLogic("user") {
+        // 重写 StpLogic 类下的 `splicingKeyTokenName` 函数,返回一个与 `StpUtil` 不同的token名称, 防止冲突
+        @Override
+        public String splicingKeyTokenName() {
+            return super.splicingKeyTokenName() + "-user";
+        }
+        // 同理你可以按需重写一些其它方法 ...
+    };
+
+    public StpUserUtil() {
+    }
+
+    public static String getLoginType() {
+        return stpLogic.getLoginType();
+    }
+
+    public static String getTokenName() {
+        return stpLogic.getTokenName();
+    }
+
+    public static void setTokenValue(String tokenValue, int cookieTimeout) {
+        stpLogic.setTokenValue(tokenValue, cookieTimeout);
+    }
+
+    public static String getTokenValue() {
+        return stpLogic.getTokenValue();
+    }
+
+    public static SaTokenInfo getTokenInfo() {
+        return stpLogic.getTokenInfo();
+    }
+
+    public static void login(Object id) {
+        stpLogic.login(id);
+    }
+
+    public static void login(Object id, String device) {
+        stpLogic.login(id, device);
+    }
+
+    public static void login(Object id, boolean isLastingCookie) {
+        stpLogic.login(id, isLastingCookie);
+    }
+
+    public static void login(Object id, SaLoginModel loginModel) {
+        stpLogic.login(id, loginModel);
+    }
+
+    public static void logout() {
+        stpLogic.logout();
+    }
+
+    public static void logoutByTokenValue(String tokenValue) {
+        stpLogic.logoutByTokenValue(tokenValue);
+    }
+
+    public static void logoutByLoginId(Object loginId) {
+        stpLogic.logoutByLoginId(loginId);
+    }
+
+    public static void logoutByLoginId(Object loginId, String device) {
+        stpLogic.logoutByLoginId(loginId, device);
+    }
+
+    public static boolean isLogin() {
+        return stpLogic.isLogin();
+    }
+
+    public static Long getUserIdAfterLogin() {
+        if (isLogin()) {
+            return StpUserUtil.getLoginIdAsLong();
+        }
+        return null;
+    }
+
+    public static void checkLogin() {
+        stpLogic.checkLogin();
+    }
+
+    public static Object getLoginId() {
+        return stpLogic.getLoginId();
+    }
+
+    public static <T> T getLoginId(T defaultValue) {
+        return stpLogic.getLoginId(defaultValue);
+    }
+
+    public static Object getLoginIdDefaultNull() {
+        return stpLogic.getLoginIdDefaultNull();
+    }
+
+    public static String getLoginIdAsString() {
+        return stpLogic.getLoginIdAsString();
+    }
+
+    public static int getLoginIdAsInt() {
+        return stpLogic.getLoginIdAsInt();
+    }
+
+    public static long getLoginIdAsLong() {
+        return stpLogic.getLoginIdAsLong();
+    }
+
+    public static Object getLoginIdByToken(String tokenValue) {
+        return stpLogic.getLoginIdByToken(tokenValue);
+    }
+
+    public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
+        return stpLogic.getSessionByLoginId(loginId, isCreate);
+    }
+
+    public static SaSession getSessionBySessionId(String sessionId) {
+        return stpLogic.getSessionBySessionId(sessionId);
+    }
+
+    public static SaSession getSessionByLoginId(Object loginId) {
+        return stpLogic.getSessionByLoginId(loginId);
+    }
+
+    public static SaSession getSession(boolean isCreate) {
+        return stpLogic.getSession(isCreate);
+    }
+
+    public static SaSession getSession() {
+        return stpLogic.getSession();
+    }
+
+    public static SaSession getTokenSessionByToken(String tokenValue) {
+        return stpLogic.getTokenSessionByToken(tokenValue);
+    }
+
+    public static SaSession getTokenSession() {
+        return stpLogic.getTokenSession();
+    }
+
+    public static void checkActivityTimeout() {
+        stpLogic.checkActivityTimeout();
+    }
+
+    public static void updateLastActivityToNow() {
+        stpLogic.updateLastActivityToNow();
+    }
+
+    public static long getTokenTimeout() {
+        return stpLogic.getTokenTimeout();
+    }
+
+    public static long getSessionTimeout() {
+        return stpLogic.getSessionTimeout();
+    }
+
+    public static long getTokenSessionTimeout() {
+        return stpLogic.getTokenSessionTimeout();
+    }
+
+    public static long getTokenActivityTimeout() {
+        return stpLogic.getTokenActivityTimeout();
+    }
+
+    public static boolean hasRole(Object loginId, String role) {
+        return stpLogic.hasRole(loginId, role);
+    }
+
+    public static boolean hasRole(String role) {
+        return stpLogic.hasRole(role);
+    }
+
+    public static void checkRole(String role) {
+        stpLogic.checkRole(role);
+    }
+
+    public static void checkRoleAnd(String... roleArray) {
+        stpLogic.checkRoleAnd(roleArray);
+    }
+
+    public static void checkRoleOr(String... roleArray) {
+        stpLogic.checkRoleOr(roleArray);
+    }
+
+    public static boolean hasPermission(Object loginId, String permission) {
+        return stpLogic.hasPermission(loginId, permission);
+    }
+
+    public static boolean hasPermission(String permission) {
+        return stpLogic.hasPermission(permission);
+    }
+
+    public static void checkPermission(String permission) {
+        stpLogic.checkPermission(permission);
+    }
+
+    public static void checkPermissionAnd(String... permissionArray) {
+        stpLogic.checkPermissionAnd(permissionArray);
+    }
+
+    public static void checkPermissionOr(String... permissionArray) {
+        stpLogic.checkPermissionOr(permissionArray);
+    }
+
+    public static String getTokenValueByLoginId(Object loginId) {
+        return stpLogic.getTokenValueByLoginId(loginId);
+    }
+
+    public static String getTokenValueByLoginId(Object loginId, String device) {
+        return stpLogic.getTokenValueByLoginId(loginId, device);
+    }
+
+    public static List<String> getTokenValueListByLoginId(Object loginId) {
+        return stpLogic.getTokenValueListByLoginId(loginId);
+    }
+
+    public static List<String> getTokenValueListByLoginId(Object loginId, String device) {
+        return stpLogic.getTokenValueListByLoginId(loginId, device);
+    }
+
+    public static String getLoginDevice() {
+        return stpLogic.getLoginDevice();
+    }
+
+    public static List<String> searchTokenValue(String keyword, int start, int size) {
+        return stpLogic.searchTokenValue(keyword, start, size);
+    }
+
+    public static List<String> searchSessionId(String keyword, int start, int size) {
+        return stpLogic.searchSessionId(keyword, start, size);
+    }
+
+    public static List<String> searchTokenSessionId(String keyword, int start, int size) {
+        return stpLogic.searchTokenSessionId(keyword, start, size);
+    }
+
+    public static void disable(Object loginId, long disableTime) {
+        stpLogic.disable(loginId, disableTime);
+    }
+
+    public static boolean isDisable(Object loginId) {
+        return stpLogic.isDisable(loginId);
+    }
+
+    public static long getDisableTime(Object loginId) {
+        return stpLogic.getDisableTime(loginId);
+    }
+
+    public static void untieDisable(Object loginId) {
+        stpLogic.untieDisable(loginId);
+    }
+
+    public static void switchTo(Object loginId) {
+        stpLogic.switchTo(loginId);
+    }
+
+    public static void endSwitch() {
+        stpLogic.endSwitch();
+    }
+
+    public static boolean isSwitch() {
+        return stpLogic.isSwitch();
+    }
+
+    public static void switchTo(Object loginId, SaFunction function) {
+        stpLogic.switchTo(loginId, function);
+    }
+
+    public static void openSafe(long safeTime) {
+        stpLogic.openSafe(safeTime);
+    }
+
+    public static boolean isSafe() {
+        return stpLogic.isSafe();
+    }
+
+    public static void checkSafe() {
+        stpLogic.checkSafe();
+    }
+
+    public static long getSafeTime() {
+        return stpLogic.getSafeTime();
+    }
+
+    public static void closeSafe() {
+        stpLogic.closeSafe();
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static String getLoginKey() {
+        return stpLogic.getLoginType();
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static void setLoginId(Object loginId) {
+        stpLogic.login(loginId);
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static void setLoginId(Object loginId, String device) {
+        stpLogic.login(loginId, device);
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static void setLoginId(Object loginId, boolean isLastingCookie) {
+        stpLogic.login(loginId, isLastingCookie);
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static void setLoginId(Object loginId, SaLoginModel loginModel) {
+        stpLogic.login(loginId, loginModel);
+    }
+
+}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
wholesale/src/main/resources/application-dev.yml


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
wholesale/src/main/resources/application-prd.yml


+ 111 - 0
wholesale/src/main/resources/config/logback-debug.xml

@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<include resource="org/springframework/boot/logging/logback/defaults.xml" />
+	<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
+
+	<contextName>wholesale-server</contextName>
+
+	<property name="log_home" value="./logs"/>
+
+	<!-- 控制台输出 -->
+	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+		<!-- 日志输出的文件的格式 -->
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+
+	</appender>
+	<!-- 按照每天生成日志文件 -->
+	<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender" level="INFO">
+		<append>true</append>
+
+        <!-- 过滤器,只记录 warn 和 info 级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>NEUTRAL</onMismatch>
+        </filter>
+
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+
+	    <file>${log_home}/wholesale-default.log</file>
+		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+			<FileNamePattern>${log_home}/wholesale-default.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+			<!-- kb/mb/gb -->
+			<maxFileSize>128MB</maxFileSize>
+			<!-- 日志文件保留天数 -->
+			<maxHistory>14</maxHistory>
+		</rollingPolicy>
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+
+	</appender>
+
+	<!-- 按照每天生成日志文件 -->
+	<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<append>true</append>
+
+		<!-- 过滤器,只记录 error 级别的日志 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+
+		<!-- 日志名称 -->
+		<file>${log_home}/wholesale-error.log</file>
+		<!-- 每天生成一个日志文件,保存15天的日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+			<!--日志文件输出的文件名:按天回滚 daily -->
+			<FileNamePattern>${log_home}/wholesale-error.log.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+			<!-- kb/mb/gb -->
+			<maxFileSize>128MB</maxFileSize>
+			<!-- 日志文件保留天数 -->
+			<maxHistory>14</maxHistory>
+			<totalSizeCap>10GB</totalSizeCap>
+		</rollingPolicy>
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<!-- 编码 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+
+	<!-- 异步输出 -->
+	<appender name="ERROR_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
+		<!-- 不丢失日志.默认的. 如果discardingThreshold大于0,队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+		<discardingThreshold>0</discardingThreshold>
+		<queueSize>10240</queueSize>
+		<appender-ref ref="ERROR-APPENDER" />
+	</appender>
+
+    <!-- 异步输出 -->
+	<appender name="ROOT_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
+		<!-- 不丢失日志.默认的. 如果discardingThreshold大于0,队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+		<discardingThreshold>0</discardingThreshold>
+		<queueSize>10240</queueSize>
+		<appender-ref ref="ROOT-APPENDER" />
+	</appender>
+
+    <logger name="jdbc.audit" level="WARN" />
+    <logger name="jdbc.resultset" level="WARN" />
+    <logger name="jdbc.sqlonly" level="WARN" />
+    <logger name="jdbc.sqltiming" level="INFO" />
+    <logger name="jdbc.connection" level="WARN" />
+
+	<root level="INFO">
+		<appender-ref ref="STDOUT" />
+		<appender-ref ref="ERROR_ASYNC" />
+		<appender-ref ref="ROOT_ASYNC" />
+	</root>
+	
+	<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
+</configuration>

+ 105 - 0
wholesale/src/main/resources/config/logback.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<include resource="org/springframework/boot/logging/logback/defaults.xml" />
+	<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
+
+	<contextName>wholesale-server</contextName>
+
+	<property name="log_home" value="./logs"/>
+
+	<!-- 控制台输出 -->
+	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+		<!-- 日志输出的文件的格式 -->
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+
+	</appender>
+	<!-- 按照每天生成日志文件 -->
+	<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender" level="INFO">
+		<append>true</append>
+
+		<!-- 过滤器,只记录 warn 和 info 级别的日志 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>WARN</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>NEUTRAL</onMismatch>
+		</filter>
+
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>INFO</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+
+		<file>${log_home}/wholesale-default.log</file>
+		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+			<FileNamePattern>${log_home}/wholesale-default.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+			<!-- kb/mb/gb -->
+			<maxFileSize>128MB</maxFileSize>
+			<!-- 日志文件保留天数 -->
+			<maxHistory>14</maxHistory>
+		</rollingPolicy>
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+
+	</appender>
+
+	<!-- 按照每天生成日志文件 -->
+	<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<append>true</append>
+
+		<!-- 过滤器,只记录 error 级别的日志 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+
+		<!-- 日志名称 -->
+		<file>${log_home}/wholesale-error.log</file>
+		<!-- 每天生成一个日志文件,保存15天的日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+			<!--日志文件输出的文件名:按天回滚 daily -->
+			<FileNamePattern>${log_home}/wholesale.log.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+			<!-- kb/mb/gb -->
+			<maxFileSize>128MB</maxFileSize>
+			<!-- 日志文件保留天数 -->
+			<maxHistory>14</maxHistory>
+			<totalSizeCap>10GB</totalSizeCap>
+		</rollingPolicy>
+		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+			<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | [%magenta(%thread) %green(%5L)] %highlight(%-5level) %cyan(%logger{50}) : %msg %n</pattern>
+			<!-- 编码 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+
+	<!-- 异步输出 -->
+	<appender name="ERROR_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
+		<!-- 不丢失日志.默认的. 如果discardingThreshold大于0,队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+		<discardingThreshold>0</discardingThreshold>
+		<queueSize>10240</queueSize>
+		<appender-ref ref="ERROR-APPENDER" />
+	</appender>
+
+	<!-- 异步输出 -->
+	<appender name="ROOT_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
+		<!-- 不丢失日志.默认的. 如果discardingThreshold大于0,队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+		<discardingThreshold>0</discardingThreshold>
+		<queueSize>10240</queueSize>
+		<appender-ref ref="ROOT-APPENDER" />
+	</appender>
+
+	<root level="INFO">
+		<appender-ref ref="STDOUT" />
+		<appender-ref ref="ERROR_ASYNC" />
+		<appender-ref ref="ROOT_ASYNC" />
+	</root>
+
+	<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
+</configuration>

Някои файлове не бяха показани, защото твърде много файлове са промени