Commit f40bf8ee5d05aec352ce5e678eefd5972518e543

Authored by 谢茂盛
0 parents

feat:init 项目

Showing 44 changed files with 4899 additions and 0 deletions

Too many changes to show.

To preserve performance only 44 of 176 files are displayed.

.gitignore 0 → 100644
  1 +++ a/.gitignore
  1 +*.iml
  2 +.idea
  3 +logs
  4 +target
0 5 \ No newline at end of file
... ...
README.md 0 → 100644
  1 +++ a/README.md
  1 +todo edit
0 2 \ No newline at end of file
... ...
admin/pom.xml 0 → 100644
  1 +++ a/admin/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>canrd-services</artifactId>
  7 + <groupId>com.canrd.shop</groupId>
  8 + <version>1.0-SNAPSHOT</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>admin</artifactId>
  13 +
  14 + <properties>
  15 + <jjwt.version>0.10.6</jjwt.version>
  16 + </properties>
  17 +
  18 + <dependencies>
  19 + <dependency>
  20 + <groupId>org.springframework.boot</groupId>
  21 + <artifactId>spring-boot-starter-web</artifactId>
  22 + <!-- <version>2.2.5.RELEASE</version>-->
  23 + <exclusions>
  24 + <exclusion>
  25 + <groupId>org.springframework.boot</groupId>
  26 + <artifactId>spring-boot-starter-logging</artifactId>
  27 + </exclusion>
  28 + </exclusions>
  29 + </dependency>
  30 +
  31 + <!-- Lombok 依赖-->
  32 + <dependency>
  33 + <groupId>org.projectlombok</groupId>
  34 + <artifactId>lombok</artifactId>
  35 + <version>1.18.12</version>
  36 + <optional>true</optional>
  37 + </dependency>
  38 + <dependency>
  39 + <groupId>org.springframework.boot</groupId>
  40 + <artifactId>spring-boot-starter-aop</artifactId>
  41 + </dependency>
  42 + <dependency>
  43 + <groupId>org.springframework.boot</groupId>
  44 + <artifactId>spring-boot-starter-test</artifactId>
  45 + <scope>test</scope>
  46 + </dependency>
  47 +
  48 + <dependency>
  49 + <groupId>com.baomidou</groupId>
  50 + <artifactId>mybatis-plus-boot-starter</artifactId>
  51 + </dependency>
  52 + <!-- <dependency>-->
  53 + <!-- <groupId>com.baomidou</groupId>-->
  54 + <!-- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>-->
  55 + <!-- </dependency>-->
  56 + <dependency>
  57 + <groupId>mysql</groupId>
  58 + <artifactId>mysql-connector-java</artifactId>
  59 + </dependency>
  60 + <dependency>
  61 + <groupId>com.alibaba</groupId>
  62 + <artifactId>druid-spring-boot-starter</artifactId>
  63 + </dependency>
  64 +
  65 + <dependency>
  66 + <groupId>org.springframework.boot</groupId>
  67 + <artifactId>spring-boot-starter-log4j2</artifactId>
  68 + </dependency>
  69 + <dependency>
  70 + <groupId>org.springframework.boot</groupId>
  71 + <artifactId>spring-boot-starter-security</artifactId>
  72 + </dependency>
  73 +
  74 + <!--jwt-->
  75 + <dependency>
  76 + <groupId>io.jsonwebtoken</groupId>
  77 + <artifactId>jjwt-api</artifactId>
  78 + <version>${jjwt.version}</version>
  79 + </dependency>
  80 + <dependency>
  81 + <groupId>io.jsonwebtoken</groupId>
  82 + <artifactId>jjwt-impl</artifactId>
  83 + <version>${jjwt.version}</version>
  84 + </dependency>
  85 + <dependency>
  86 + <groupId>io.jsonwebtoken</groupId>
  87 + <artifactId>jjwt-jackson</artifactId>
  88 + <version>${jjwt.version}</version>
  89 + </dependency>
  90 +
  91 +
  92 + <dependency>
  93 + <groupId>com.alibaba</groupId>
  94 + <artifactId>fastjson</artifactId>
  95 + </dependency>
  96 +
  97 + <dependency>
  98 + <groupId>cn.hutool</groupId>
  99 + <artifactId>hutool-crypto</artifactId>
  100 + </dependency>
  101 +
  102 + <dependency>
  103 + <groupId>org.springframework.boot</groupId>
  104 + <artifactId>spring-boot-starter-data-redis</artifactId>
  105 + </dependency>
  106 +
  107 + <dependency>
  108 + <groupId>org.apache.commons</groupId>
  109 + <artifactId>commons-pool2</artifactId>
  110 + </dependency>
  111 + <dependency>
  112 + <groupId>org.apache.commons</groupId>
  113 + <artifactId>commons-lang3</artifactId>
  114 + </dependency>
  115 + <dependency>
  116 + <groupId>org.lionsoul</groupId>
  117 + <artifactId>ip2region</artifactId>
  118 + </dependency>
  119 + <dependency>
  120 + <groupId>eu.bitwalker</groupId>
  121 + <artifactId>UserAgentUtils</artifactId>
  122 + </dependency>
  123 + <!-- RESTful APIs swagger2 -->
  124 + <dependency>
  125 + <groupId>io.springfox</groupId>
  126 + <artifactId>springfox-swagger2</artifactId>
  127 + <exclusions>
  128 + <exclusion>
  129 + <groupId>io.swagger</groupId>
  130 + <artifactId>swagger-annotations</artifactId>
  131 + </exclusion>
  132 + <exclusion>
  133 + <groupId>io.swagger</groupId>
  134 + <artifactId>swagger-models</artifactId>
  135 + </exclusion>
  136 + </exclusions>
  137 + </dependency>
  138 + <dependency>
  139 + <groupId>io.springfox</groupId>
  140 + <artifactId>springfox-swagger-ui</artifactId>
  141 + </dependency>
  142 + <dependency>
  143 + <groupId>io.swagger</groupId>
  144 + <artifactId>swagger-annotations</artifactId>
  145 + </dependency>
  146 + <dependency>
  147 + <groupId>io.swagger</groupId>
  148 + <artifactId>swagger-models</artifactId>
  149 + </dependency>
  150 + <!--工具包-->
  151 + <dependency>
  152 + <groupId>cn.hutool</groupId>
  153 + <artifactId>hutool-all</artifactId>
  154 + </dependency>
  155 + <dependency>
  156 + <groupId>org.apache.poi</groupId>
  157 + <artifactId>poi</artifactId>
  158 + </dependency>
  159 + <dependency>
  160 + <groupId>org.apache.poi</groupId>
  161 + <artifactId>poi-ooxml</artifactId>
  162 + </dependency>
  163 + <dependency>
  164 + <groupId>org.apache.commons</groupId>
  165 + <artifactId>commons-csv</artifactId>
  166 + </dependency>
  167 + <dependency>
  168 + <groupId>joda-time</groupId>
  169 + <artifactId>joda-time</artifactId>
  170 + </dependency>
  171 + <dependency>
  172 + <groupId>com.google.guava</groupId>
  173 + <artifactId>guava</artifactId>
  174 + </dependency>
  175 + </dependencies>
  176 + <build>
  177 + <finalName>canrd-com.canrd.shop.template.service-1.0-SNAPSHOT</finalName>
  178 + <plugins>
  179 + <plugin>
  180 + <groupId>org.apache.maven.plugins</groupId>
  181 + <artifactId>maven-source-plugin</artifactId>
  182 + </plugin>
  183 +
  184 + <plugin>
  185 + <groupId>org.springframework.boot</groupId>
  186 + <artifactId>spring-boot-maven-plugin</artifactId>
  187 + <configuration>
  188 + <executable>true</executable>
  189 + </configuration>
  190 + </plugin>
  191 +
  192 + </plugins>
  193 + </build>
  194 +</project>
0 195 \ No newline at end of file
... ...
admin/src/main/java/com/canrd/shop/AdminApplication.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/AdminApplication.java
  1 +package com.canrd.shop;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.DbType;
  4 +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  5 +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
  6 +import com.canrd.shop.common.directory.Path;
  7 +import org.mybatis.spring.annotation.MapperScan;
  8 +import org.springframework.boot.SpringApplication;
  9 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  10 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  11 +import org.springframework.context.annotation.Bean;
  12 +import org.springframework.transaction.annotation.EnableTransactionManagement;
  13 +
  14 +/**
  15 + * @author: xms
  16 + * @description: 管理后台启动
  17 + * @date: 2023/3/29 18:00
  18 + * @version: 1.0
  19 + */
  20 +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = {"com.canrd.shop"})
  21 +@MapperScan("com.canrd.shop.**.com.canrd.shop.template.mapper")
  22 +@EnableTransactionManagement
  23 +public class AdminApplication {
  24 +
  25 + private static void setLogPath() {
  26 + String appPath = Path.getAppPath(AdminApplication.class);
  27 + System.setProperty("logging.path", appPath);
  28 + }
  29 +
  30 + public static void main(String[] args) {
  31 + setLogPath();
  32 + SpringApplication.run(AdminApplication.class, args);
  33 + }
  34 +
  35 + /**
  36 + * 分页插件
  37 + *
  38 + * @return
  39 + */
  40 + @Bean
  41 + public MybatisPlusInterceptor mybatisPlusInterceptor() {
  42 + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  43 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  44 + return interceptor;
  45 + }
  46 +}
... ...
admin/src/main/java/com/canrd/shop/common/annotation/AnonymousAccess.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/annotation/AnonymousAccess.java
  1 +package com.canrd.shop.common.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 用于标记匿名访问方法
  10 + */
  11 +@Target(ElementType.METHOD)
  12 +@Retention(RetentionPolicy.RUNTIME)
  13 +public @interface AnonymousAccess {
  14 +
  15 +}
... ...
admin/src/main/java/com/canrd/shop/common/constant/Constant.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/constant/Constant.java
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +import java.util.Arrays;
  4 +import java.util.List;
  5 +
  6 +public class Constant {
  7 + /**
  8 + * 分隔符英文的横杠
  9 + */
  10 + public static final String CROSS_BAR_CHARACTER = "-";
  11 + /**
  12 + * 英文的 .
  13 + */
  14 + public static final String POINT_BAR_CHARACTER = ".";
  15 + /**
  16 + * 英文的 !
  17 + */
  18 + public static final String EXCLAMATION_MARK_CHARACTER = "!";
  19 + /**
  20 + * 英文的 /
  21 + */
  22 + public static final String SLASH_MARK_CHARACTER = "/";
  23 + /**
  24 + * 英文的 :
  25 + */
  26 + public static final String COLON_CHARACTER = ":";
  27 +
  28 + /**
  29 + * 英文的 ;
  30 + */
  31 + public static final String SEMICOLON_CHARACTER = ";";
  32 +
  33 + /**
  34 + * 英文的逗号
  35 + */
  36 + public static final String COMMA_CHARACTER = ",";
  37 + /**
  38 + * 英文的*号
  39 + */
  40 + public static final String START_CHARACTER = "*";
  41 + /**
  42 + * 分隔符
  43 + */
  44 + public static final String SPLIT_SYMBOL = ",|,";
  45 +
  46 + /**
  47 + * 特殊分隔符 _
  48 + */
  49 + public static final String SPECIAL_KEY = "_";
  50 +
  51 +
  52 + /**
  53 + * 括号
  54 + */
  55 + public static final String BRACKETS_RIGHT = "]";
  56 + /**
  57 + * 括号
  58 + */
  59 + public static final String BRACKETS_LEFT = "[";
  60 +
  61 + /**
  62 + * 手机号码正则校验
  63 + */
  64 + public static final String PHONE_REGEXP = "^[1][3,4,5,6,7,8,9][0-9]{9}$";
  65 +
  66 + /**
  67 + * 脱敏手机号
  68 + */
  69 + public static final String PHONE_DESENSITIZATION_REGEXP = "^[1][3,4,5,6,7,8,9][0-9][*]{4}[0-9]{4}$";
  70 +
  71 + /**
  72 + * 邮箱
  73 + */
  74 + public static final String EMAIL_REGEXP = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
  75 +
  76 + /**
  77 + * 三位数字
  78 + */
  79 + public static final String THREE_DIGITS_REGEXP = "\\d{3}";
  80 +
  81 + /**
  82 + * 中文 英文 数字
  83 + */
  84 + public static final String CHI_EN_NUM_REGEXP = "^[A-z0-9\\u4e00-\\u9fa5]*$";
  85 +
  86 +
  87 + /**
  88 + * 仅包含英文和数字
  89 + */
  90 + public static final String EN_REGEXP = "^[a-zA-Z]+$";
  91 +
  92 + public static final String EN_NUM_REGEXP = "^[a-z0-9A-Z]+$";
  93 +
  94 + public static final String LINE_EN_NUM_REGEXP = "^[a-z0-9A-Z\\-]+$";
  95 +
  96 + /**
  97 + * 仅包含英文和中文
  98 + */
  99 + public static final String CHI_EN_REGEXP = "^[A-z\\u4e00-\\u9fa5]*$";
  100 +
  101 + /**
  102 + * 纯数字
  103 + */
  104 + public static final String NUMERIC_REGEXP = "^\\d+$";
  105 + /**
  106 + * 纯中文
  107 + */
  108 + public static final String CHI_REGEXP = "^[\u4e00-\u9fa5]+$";
  109 + /**
  110 + * 不超过两位小数
  111 + */
  112 + public static final String DICMAL_REGEXP = "^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,3})?$";
  113 +
  114 + /**
  115 + * 默认空字符串
  116 + */
  117 + public static final String EMPTY_STRING = "";
  118 +
  119 + /**
  120 + * 统一返回data的key
  121 + */
  122 + public static final String RESULT_CHARACTER = "result";
  123 +
  124 + /**
  125 + * 统一返回data的key
  126 + */
  127 + public static final String SUCCESS_RESULT_CHARACTER = "success";
  128 +
  129 + /**
  130 + * 返回的默认结果集
  131 + */
  132 + public static final String RESULT_FAIL = null;
  133 +
  134 + /**
  135 + * ENABLE_FLAG
  136 + */
  137 + public static final String ENABLE_FLAG = "enable_flag";
  138 +
  139 + /**
  140 + * 是否可用 10-可用 20-删除
  141 + */
  142 + public static final int ENABLE_TEN = 10;
  143 + /**
  144 + * 是否可用 10-可用 20-删除
  145 + */
  146 + public static final int UNABLE_TWENTY = 20;
  147 +
  148 + public static final int ONE = 1;
  149 +
  150 + public static final Integer INTEGER_ONE = 1;
  151 +
  152 + public static final int TWO = 2;
  153 +
  154 + public static final int THREE = 3;
  155 +
  156 + public static final int FOUR = 4;
  157 +
  158 + public static final int FIVE = 5;
  159 +
  160 + public static final int SIX = 6;
  161 +
  162 + public static final int SEVEN = 7;
  163 +
  164 + public static final int THIRTY = 30;
  165 +
  166 + public static final int NINETEEN = 19;
  167 +
  168 + public static final int THOUSAND = 1000;
  169 +
  170 + public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";
  171 +
  172 + public static final int ZERO = 0;
  173 +
  174 + public static final String STRING_ZERO = "0";
  175 +
  176 + public static final String ZERO_STRING = "0";
  177 +
  178 + public static final String THOUSAND_STRING = "1000";
  179 +
  180 + public static final String SYSTEM_USER = "System";
  181 +
  182 + public static final String percent50 = "0.5";
  183 +
  184 + public static final String DELETE_SUCCESS_RESULT_CHARACTER = "删除成功";
  185 +
  186 +
  187 + /**
  188 + * token rediskey
  189 + */
  190 + public static final String TOKEN_FLAG = "token:";
  191 + /**
  192 + * token 限制api请求
  193 + */
  194 + public static final String PERMISSION_API_LIMIT = "token_api_limit:";
  195 +
  196 + /**
  197 + * token过期时间
  198 + */
  199 + public static final Integer TOKEN_EXPIRE_HOURS = 1;
  200 + /**
  201 + * 密码3次错误锁定
  202 + */
  203 + public static final int LOCK_ERROR_TIMES = 3;
  204 +
  205 + /**
  206 + * session字段
  207 + */
  208 + public static final String HEAD_TOKEN = "Authorization";
  209 + public static final String ACCESS_TOKEN = "token";
  210 + public static final String REQUEST_ORIGIN = "source";
  211 + public static final String REQUEST_IP = "ip";
  212 + public static final String USER_INFO = "userInfo";
  213 + public static final String FILED_ID = "id";
  214 + public static final String FILED_USER_NAME = "username";
  215 + public static final String FILED_DEVICE_NUM = "deviceNum";
  216 +
  217 + /**
  218 + * 请求来源
  219 + */
  220 + public static final String ORIGIN_WEB = "WEB";
  221 + public static final String ORIGIN_PDA = "PDA";
  222 +
  223 + /**
  224 + * 1001 参数校验不通过
  225 + * 1002 签名验证不通过
  226 + */
  227 + public static final List<String> ERROR_CODE_LIST = Arrays.asList("1001", "1002");
  228 +
  229 + /**
  230 + * 分布式锁超时时间
  231 + */
  232 + public static final long REDIS_LOCK_DEFAULT_TIME_OUT_MILLIS = 3000;
  233 + public static final long REDIS_LOCK_FIVE_SECONDS_TIME_OUT_MILLIS = 5000;
  234 +
  235 + /**
  236 + * 系统来源WMS
  237 + */
  238 + public static final String SYS_ORIGIN_WMS = "WMS";
  239 +
  240 + public static final String STRING_ONE = "1";
  241 +
  242 +
  243 + public static final String STRING_TWO = "2";
  244 +
  245 + public static final String STRING_THREE = "3";
  246 +
  247 + public static final String STRING_FOUR = "4";
  248 +
  249 + public static final String STRING_FIVE = "5";
  250 +
  251 + public static final String STRING_SIX = "6";
  252 +
  253 + public static final String STRING_SEVEN = "7";
  254 +
  255 + public static final String STRING_EIGHT = "8";
  256 +
  257 + public static final String STRING_NINE = "9";
  258 +
  259 + public static final String STRING_TEN = "10";
  260 +
  261 + public static final String STRING_ELEVEN = "11";
  262 +
  263 + public static final String STRING_TWELVE = "12";
  264 +
  265 + /**
  266 + * 异常延时队列后缀
  267 + */
  268 + public static final String ERROR_DELAY_QUEUE_SUFFIX = "error";
  269 +
  270 + /**
  271 + * 推送出库数据延时队列 redis key prefix
  272 + */
  273 + public static final String OUTBOUND_NOTIFY_DELAY_QUEUE_PREFIX = "outbound:notify:";
  274 +
  275 + /**
  276 + * 同步MES库存队列 redis key prefix
  277 + */
  278 + public static final String MES_STOCK_SYNC_QUEUE_PREFIX = "mes:stock_sync:";
  279 +
  280 + /**
  281 + * 分拣详情 错误码: 157205 返回值段
  282 + */
  283 + public static final String SEPARATE_PICK_QUERY_RETURN_FIELD = "separatePickQuery";
  284 + /**
  285 + * 限制上限值
  286 + */
  287 + public static final Integer LIMIT_999 = 999;
  288 +
  289 + /**
  290 + * 东八区
  291 + */
  292 + public static final String GMT_8 = "GMT+8";
  293 +
  294 + /**
  295 + * 英文的 "
  296 + */
  297 + public static final String QUOTATION_MARK_CHARACTER = "\"";
  298 +
  299 +
  300 + /**
  301 + * 英文的 \"
  302 + */
  303 + public static final String QUOTATION_SLASH_MARK_CHARACTER = "\\\"";
  304 +
  305 + public static final String SUCCESS_VALUE = "success";
  306 +
  307 +
  308 + public static final String TRUE = "true";
  309 +
  310 + public static final String ROOT_PARENT_ID = "0";
  311 +
  312 + public static final Long ROOT_PARENT_ID_LONG = 0L;
  313 +
  314 +
  315 + /**
  316 + * 短信验证码 redis key
  317 + */
  318 + public static final String SMS_AUTH_CODE_PREFIX = "sms:auth:code:";
  319 +
  320 + public static final String DEFAULT_PASSWORD = "JBXT123456";
  321 +
  322 + /**
  323 + * 账号在线队列 redis key
  324 + */
  325 + public static final String ACCOUNT_ONLINE_LIST = "account:online:";
  326 +
  327 + /**
  328 + * 缓存导入excel错误信息 redis key
  329 + */
  330 + public static final String EXCEL_IMPORT_ERROR_PREFIX = "excel:import:error:";
  331 +
  332 +}
... ...
admin/src/main/java/com/canrd/shop/common/constant/ElAdminConstant.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/constant/ElAdminConstant.java
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +/**
  4 + * 常用静态常量
  5 + *
  6 + * @date 2018-12-26
  7 + */
  8 +public class ElAdminConstant {
  9 +
  10 + public static final String RESET_PASS = "重置密码";
  11 +
  12 + public static final String RESET_MAIL = "重置邮箱";
  13 +
  14 + /**
  15 + * 用于IP定位转换
  16 + */
  17 + public static final String REGION = "内网IP|内网IP";
  18 +
  19 + /**
  20 + * 常用接口
  21 + */
  22 + public static class Url {
  23 + public static final String SM_MS_URL = "https://sm.ms/api";
  24 + }
  25 +}
... ...
admin/src/main/java/com/canrd/shop/common/constant/ServerResult.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/constant/ServerResult.java
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +
  4 +import java.io.Serializable;
  5 +import java.util.HashMap;
  6 +import java.util.Map;
  7 +
  8 +/**
  9 + * @author : dengbin
  10 + * @Date: 2020/9/5
  11 + * 统一的返回结果实体
  12 + */
  13 +public class ServerResult<T> implements Serializable {
  14 + /**
  15 + * 序列化ID
  16 + */
  17 + private static final long serialVersionUID = -5809782578272943999L;
  18 + /**
  19 + * 返回的状态码
  20 + */
  21 + private int result = ServerResultCode.SUCCESS.getErrorCode();
  22 + /**
  23 + * 返回的消息
  24 + */
  25 + private String message = ServerResultCode.SUCCESS.getErrorDesc();
  26 + /**
  27 + * 返回的数据实体
  28 + */
  29 + private T data = null;
  30 + /**
  31 + *
  32 + */
  33 + final int INIT_SIZE = 128;
  34 +
  35 + /**
  36 + *
  37 + */
  38 + public ServerResult() {
  39 + }
  40 +
  41 + @Override
  42 + public String toString() {
  43 + StringBuilder buffer = new StringBuilder(INIT_SIZE);
  44 + buffer.append("{\"result\":").append(this.result);
  45 + buffer.append(",\"message\":\"").append(this.message != null ? message : "").append("\"");
  46 + buffer.append(",\"data\":").append(data).append("}");
  47 + return buffer.toString();
  48 + }
  49 +
  50 + public int getResult() {
  51 + return result;
  52 + }
  53 +
  54 + public ServerResult setResult(int result) {
  55 + this.result = result;
  56 + return this;
  57 + }
  58 +
  59 + public ServerResult setResult(ServerResultCode serverResultCode) {
  60 + this.result = serverResultCode.getErrorCode();
  61 + this.message = serverResultCode.getErrorDesc();
  62 + return this;
  63 + }
  64 +
  65 + public ServerResult setResult(int errorCode, String errorDesc) {
  66 + this.result = errorCode;
  67 + this.message = errorDesc;
  68 + return this;
  69 + }
  70 +
  71 + public String getMessage() {
  72 + return message;
  73 + }
  74 +
  75 + public ServerResult<T> setMessage(String message) {
  76 + this.message = message;
  77 + return this;
  78 + }
  79 +
  80 + public T getData() {
  81 + return data;
  82 + }
  83 +
  84 + public ServerResult setData(T data) {
  85 + this.data = data;
  86 + return this;
  87 + }
  88 +
  89 + public static <T> ServerResult<T> success() {
  90 + return new ServerResult()
  91 + .setResult(ServerResultCode.SUCCESS)
  92 + .setMessage(ServerResultCode.SUCCESS.getErrorDesc())
  93 + .setData(defaultResult(ServerResultCode.SUCCESS));
  94 + }
  95 +
  96 + public static <T> ServerResult<T> success(T data) {
  97 + return new ServerResult()
  98 + .setResult(ServerResultCode.SUCCESS)
  99 + .setMessage(ServerResultCode.SUCCESS.getErrorDesc())
  100 + .setData(data);
  101 + }
  102 +
  103 + public static <T> ServerResult<T> success(T data, String message) {
  104 + return new ServerResult()
  105 + .setResult(ServerResultCode.SUCCESS)
  106 + .setMessage(message)
  107 + .setData(data);
  108 + }
  109 +
  110 + /**
  111 + * @description 错误码使用系统错误 1000 错误类型自定义
  112 + * @author dengbin
  113 + * @date 2020/9/12
  114 + */
  115 + public static <T> ServerResult<T> fail(String message) {
  116 + return new ServerResult()
  117 + .setResult(ServerResultCode.FAIL)
  118 + .setMessage(message)
  119 + .setData(defaultResult(Constant.RESULT_FAIL));
  120 + }
  121 +
  122 + /**
  123 + * 错误时需要返回相关数据时使用
  124 + *
  125 + * @param data
  126 + * @param <T>
  127 + * @return
  128 + */
  129 + public static <T> ServerResult<T> fail(T data, ServerResultCode serverResultCode) {
  130 + return new ServerResult()
  131 + .setData(data)
  132 + .setResult(serverResultCode)
  133 + .setMessage(serverResultCode.getErrorDesc());
  134 + }
  135 +
  136 + /**
  137 + * 错误时需要返回相关数据时使用(不设值 data)
  138 + *
  139 + * @param sr
  140 + * @param
  141 + * @return
  142 + */
  143 + public static <T> ServerResult<T> fail(ServerResult<?> sr) {
  144 + return new ServerResult<>()
  145 + .setMessage(sr.getMessage())
  146 + .setResult(sr.getResult());
  147 +
  148 + }
  149 +
  150 + /**
  151 + * @description 错误码使用上面的枚举定义的,错误信息重新定义
  152 + * @author dengbin
  153 + * @date 2020/9/12
  154 + */
  155 + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode, String msg) {
  156 + return new ServerResult()
  157 + .setResult(serverResultCode)
  158 + .setMessage(msg)
  159 + .setData(defaultResult(Constant.RESULT_FAIL));
  160 + }
  161 +
  162 + /**
  163 + * @return
  164 + * @description 直接选用上面的枚举错误码,输出定义的错误信息
  165 + * @author dengbin
  166 + * @date 2020/9/12
  167 + */
  168 + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode) {
  169 + return new ServerResult()
  170 + .setResult(serverResultCode)
  171 + .setMessage(serverResultCode.getErrorDesc())
  172 + .setData(defaultResult(Constant.RESULT_FAIL));
  173 + }
  174 +
  175 + /**
  176 + * 错误时需要返回相关数据时使用
  177 + *
  178 + * @param data
  179 + * @param <T>
  180 + * @return
  181 + */
  182 + public static <T> ServerResult<T> fail(T data, int errorCode, String errorDesc) {
  183 + return new ServerResult()
  184 + .setData(data)
  185 + .setResult(errorCode, errorDesc);
  186 + }
  187 +
  188 +
  189 + public static <T> ServerResult<T> fail() {
  190 + return new ServerResult()
  191 + .setResult(ServerResultCode.FAIL.getErrorCode())
  192 + .setMessage(ServerResultCode.FAIL.getErrorDesc())
  193 + .setData(defaultResult(Constant.RESULT_FAIL));
  194 + }
  195 +
  196 +
  197 + /**
  198 + * @description 直接选用上面的枚举错误码,输出定义的错误信息
  199 + * @author dengbin
  200 + * @date 2020/9/12
  201 + */
  202 + public ServerResult failEnum(ServerResultCode serverResultCode) {
  203 + setResult(serverResultCode);
  204 + setMessage(serverResultCode.getErrorDesc());
  205 + return this;
  206 + }
  207 +
  208 + public static <T> ServerResult<T> fail(int errorCode, String errorDesc) {
  209 + return new ServerResult()
  210 + .setResult(errorCode, errorDesc)
  211 + .setData(defaultResult(Constant.RESULT_FAIL));
  212 +
  213 + }
  214 +
  215 + /**
  216 + * 判断当前的状态码是否是SUCCESS
  217 + *
  218 + * @return 结果 ture or false
  219 + */
  220 + public boolean checkSuccess() {
  221 + return result == ServerResultCode.SUCCESS.getErrorCode();
  222 + }
  223 +
  224 + public boolean checkNotSuccess() {
  225 + return !checkSuccess();
  226 + }
  227 +
  228 + private static Map<String, Object> defaultResult(Object object) {
  229 + Map<String, Object> map = new HashMap<>(Constant.ONE);
  230 + map.put(Constant.RESULT_CHARACTER, null);
  231 + return map;
  232 + }
  233 +}
... ...
admin/src/main/java/com/canrd/shop/common/constant/ServerResultCode.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/constant/ServerResultCode.java
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +
  4 +import com.canrd.shop.common.exception.ErrorInfo;
  5 +import lombok.Setter;
  6 +
  7 +
  8 +/**
  9 + * 请求成功 返回 0
  10 + */
  11 +public enum ServerResultCode implements ErrorInfo {
  12 + //成功 "0"
  13 + SUCCESS(0, "成功"),
  14 + FAIL(1000, "系统内部错误,请联系业务系统运维管理员"),
  15 + FIlE_UPLOAD_TOO_LARGE(1051, "上传文件太大,图片文件一般小于2兆"),
  16 +
  17 + //空指针异常
  18 + NULL_POINT(1001, "空指针异常"),
  19 +
  20 + //校验异常
  21 + RUN_ERROR(1002, "程序运行报错"),
  22 + ILLEGAL_ARGUMENT(1003, "参数非法"),
  23 + FILED_ERROR(1004, "传入参数错误"),
  24 + PARAM_ERROR(1005, "入参为空"),
  25 + EMPTY_RESULT(1006, "数据不存在"),
  26 + EMPTY_LIST(1007, "查询结果为空"),
  27 +
  28 + //认证授权异常
  29 + UNAUTHENTICATION(401, "未登录"),
  30 +
  31 +
  32 + //用户
  33 + USER_NOT_EXIT(20001, "用户不存在"),
  34 +
  35 +
  36 + // 公司
  37 + COMPANY_NOT_EXIT(30001, "公司不存在"),
  38 + ;
  39 +
  40 +
  41 + ServerResultCode(Integer errorCode, String errorDesc) {
  42 + this.errorCode = errorCode;
  43 + this.errorDesc = errorDesc;
  44 + }
  45 +
  46 + @Setter
  47 + private Integer errorCode;
  48 + @Setter
  49 + private String errorDesc;
  50 +
  51 + @Override
  52 + public Integer getErrorCode() {
  53 + return this.errorCode;
  54 + }
  55 +
  56 + @Override
  57 + public String getErrorDesc() {
  58 + return this.errorDesc;
  59 + }
  60 +
  61 + /**
  62 + * 根据errorCode获得枚举
  63 + *
  64 + * @param errorCode
  65 + * @return
  66 + */
  67 + public static String getDescByCode(Integer errorCode) {
  68 + if (errorCode == null) {
  69 + return null;
  70 + }
  71 + ServerResultCode[] serverResults = values();
  72 + for (ServerResultCode serverResult : serverResults) {
  73 + if (serverResult.getErrorCode().equals(errorCode)) {
  74 + return serverResult.getErrorDesc();
  75 + }
  76 + }
  77 + return null;
  78 + }
  79 +
  80 +}
0 81 \ No newline at end of file
... ...
admin/src/main/java/com/canrd/shop/common/directory/Path.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/directory/Path.java
  1 +package com.canrd.shop.common.directory;
  2 +
  3 +
  4 +import com.canrd.shop.common.constant.Constant;
  5 +
  6 +/**
  7 + * @author xms
  8 + */
  9 +public class Path {
  10 + /**
  11 + * 获取程序启动路径
  12 + *
  13 + * @param cls,建议直接传 ServiceApplication.class
  14 + * @return 应用启动路径
  15 + */
  16 + public static String getAppPath(Class cls) {
  17 + String path = cls.getResource(Constant.SLASH_MARK_CHARACTER).getPath();
  18 + String os = System.getProperty("os.name").toLowerCase();
  19 + final String OSWINDOW = "windows";
  20 + if (os.indexOf(OSWINDOW) != -1 && path.length() > 1) {
  21 + //windows路径样例: /D:/work/code/shop-services/online-shop-oss/target/classes/
  22 + return path.substring(1);
  23 + }
  24 +
  25 + //linux 路径样例 file:/opt/target/online-shop-oss-SNAPSHOT.jar!/BOOT-INF/classes!/";
  26 + final String FILE = "file:";
  27 + if (path.indexOf(FILE) != -1) {
  28 + path = path.substring(FILE.length());
  29 + }
  30 +
  31 + int pos = -1;
  32 + if ((pos = path.indexOf(Constant.EXCLAMATION_MARK_CHARACTER)) != -1) {
  33 + if (-1 != (pos = path.lastIndexOf(Constant.SLASH_MARK_CHARACTER, pos))) {
  34 + path = path.substring(0, pos + 1);
  35 + }
  36 + }
  37 +
  38 + return path;
  39 + }
  40 +}
... ...
admin/src/main/java/com/canrd/shop/common/exception/BadRequestException.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/BadRequestException.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import lombok.Getter;
  4 +import org.springframework.http.HttpStatus;
  5 +
  6 +import static org.springframework.http.HttpStatus.BAD_REQUEST;
  7 +
  8 +/**
  9 + *
  10 + * @date 2018-11-23
  11 + * 统一异常处理
  12 + */
  13 +@Getter
  14 +public class BadRequestException extends RuntimeException {
  15 +
  16 + private Integer status = BAD_REQUEST.value();
  17 +
  18 + public BadRequestException(String msg) {
  19 + super(msg);
  20 + }
  21 +
  22 + public BadRequestException(HttpStatus status, String msg) {
  23 + super(msg);
  24 + this.status = status.value();
  25 + }
  26 +}
... ...
admin/src/main/java/com/canrd/shop/common/exception/BusinessException.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/BusinessException.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.common.constant.ServerResultCode;
  5 +import lombok.Getter;
  6 +import lombok.Setter;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +
  9 +/**
  10 + * <p>基础异常类,所有自定义异常类都需要继承本类</p>
  11 + *
  12 + * @author A80076
  13 + * @date 2021/1/11
  14 + */
  15 +@Slf4j
  16 +public class BusinessException extends RuntimeException {
  17 +
  18 + private static final long serialVersionUID = 3152549963899218489L;
  19 + @Setter
  20 + @Getter
  21 + private String errorDesc;
  22 + @Setter
  23 + @Getter
  24 + private Integer errorCode;
  25 + @Setter
  26 + @Getter
  27 + private Object data;
  28 +
  29 + public BusinessException() {
  30 + super(ServerResultCode.FAIL.getErrorDesc());
  31 + this.errorCode = ServerResultCode.FAIL.getErrorCode();
  32 + this.errorDesc = ServerResultCode.FAIL.getErrorDesc();
  33 + }
  34 +
  35 + public BusinessException(int errorCode, String errorDesc) {
  36 + super(errorDesc);
  37 + this.errorCode = errorCode;
  38 + this.errorDesc = errorDesc;
  39 + }
  40 +
  41 + public BusinessException(ServerResultCode serverResultCode) {
  42 + super(serverResultCode.getErrorDesc());
  43 + this.errorCode = serverResultCode.getErrorCode();
  44 + this.errorDesc = serverResultCode.getErrorDesc();
  45 + log.error("业务异常: ", this);
  46 + }
  47 +
  48 + public BusinessException(ErrorInfo errorInfo) {
  49 + super(errorInfo.getErrorDesc());
  50 + this.errorCode = errorInfo.getErrorCode();
  51 + this.errorDesc = errorInfo.getErrorDesc();
  52 + log.error("业务异常: ", this);
  53 + }
  54 +
  55 + public BusinessException(ServerResult<?> serverResult) {
  56 + super(serverResult == null ? ServerResultCode.FAIL.getErrorDesc() : serverResult.getMessage());
  57 + if (serverResult == null) {
  58 + this.errorCode = ServerResultCode.FAIL.getErrorCode();
  59 + this.errorDesc = ServerResultCode.FAIL.getErrorDesc();
  60 + } else {
  61 + this.errorCode = serverResult.getResult();
  62 + this.errorDesc = serverResult.getMessage();
  63 + this.data = serverResult.getData();
  64 + }
  65 + log.error("业务异常: ", this);
  66 + }
  67 +
  68 + public BusinessException(String message) {
  69 + super(message);
  70 + }
  71 +
  72 + public BusinessException(Throwable cause) {
  73 + super(cause);
  74 + log.error("业务异常: ", this);
  75 + }
  76 +
  77 + public BusinessException(String message, Throwable cause) {
  78 + super(message, cause);
  79 + log.error("业务异常: ", this);
  80 + }
  81 +}
... ...
admin/src/main/java/com/canrd/shop/common/exception/BusinessExceptionHandlerAdvice.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/BusinessExceptionHandlerAdvice.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.common.constant.ServerResultCode;
  5 +import org.springframework.core.annotation.Order;
  6 +import org.springframework.http.HttpStatus;
  7 +import org.springframework.http.ResponseEntity;
  8 +import org.springframework.web.bind.annotation.ControllerAdvice;
  9 +import org.springframework.web.bind.annotation.ExceptionHandler;
  10 +import org.springframework.web.bind.annotation.ResponseStatus;
  11 +
  12 +import java.util.Optional;
  13 +
  14 +/**
  15 + * 业务异常统一处理类
  16 + *
  17 + * @author A80076
  18 + * @date 2021/1/11
  19 + */
  20 +@ControllerAdvice
  21 +@Order(5)
  22 +public class BusinessExceptionHandlerAdvice {
  23 +
  24 +
  25 + @ExceptionHandler(value = {BusinessException.class})
  26 + @ResponseStatus(value = HttpStatus.OK)
  27 + public ResponseEntity<Object> handleException(BusinessException exception) throws Exception {
  28 + return new ResponseEntity<Object>(handleBusinessException(exception), HttpStatus.OK);
  29 + }
  30 +
  31 + private ServerResult handleBusinessException(BusinessException exception) {
  32 + Integer code = Optional.ofNullable(exception.getErrorCode()).orElse(ServerResultCode.FAIL.getErrorCode());
  33 + String msg = Optional.ofNullable(exception.getMessage()).orElse(ServerResultCode.FAIL.getErrorDesc());
  34 + Object data = Optional.ofNullable(exception.getData()).orElse(null);
  35 + return ServerResult.fail(data, code, msg);
  36 + }
  37 +}
... ...
admin/src/main/java/com/canrd/shop/common/exception/EntityExistException.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/EntityExistException.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import org.springframework.util.StringUtils;
  4 +
  5 +/**
  6 + *
  7 + * @date 2018-11-23
  8 + */
  9 +public class EntityExistException extends RuntimeException {
  10 +
  11 + public EntityExistException(Class clazz, String field, String val) {
  12 + super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
  13 + }
  14 +
  15 + private static String generateMessage(String entity, String field, String val) {
  16 + return StringUtils.capitalize(entity)
  17 + + " with " + field + " " + val + " existed";
  18 + }
  19 +}
0 20 \ No newline at end of file
... ...
admin/src/main/java/com/canrd/shop/common/exception/EntityNotFoundException.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/EntityNotFoundException.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import org.springframework.util.StringUtils;
  4 +
  5 +/**
  6 + *
  7 + * @date 2018-11-23
  8 + */
  9 +public class EntityNotFoundException extends RuntimeException {
  10 +
  11 + public EntityNotFoundException(Class clazz, String field, String val) {
  12 + super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
  13 + }
  14 +
  15 + private static String generateMessage(String entity, String field, String val) {
  16 + return StringUtils.capitalize(entity)
  17 + + " with " + field + " " + val + " does not exist";
  18 + }
  19 +}
0 20 \ No newline at end of file
... ...
admin/src/main/java/com/canrd/shop/common/exception/ErrorInfo.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/ErrorInfo.java
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +/**
  4 + * @author fanzhenyu
  5 + * @date 2023-01-12
  6 + */
  7 +public interface ErrorInfo {
  8 +
  9 + Integer getErrorCode();
  10 +
  11 + String getErrorDesc();
  12 +}
... ...
admin/src/main/java/com/canrd/shop/common/exception/handler/ApiError.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/handler/ApiError.java
  1 +package com.canrd.shop.common.exception.handler;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + *
  10 + * @date 2018-11-23
  11 + */
  12 +@Data
  13 +class ApiError {
  14 +
  15 + private Integer status = 200;
  16 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  17 + private LocalDateTime timestamp;
  18 + private String message;
  19 + private String errorCode;
  20 +
  21 + private ApiError() {
  22 + timestamp = LocalDateTime.now();
  23 + }
  24 +
  25 + public static ApiError error(String message){
  26 + ApiError apiError = new ApiError();
  27 + apiError.setMessage(message);
  28 + return apiError;
  29 + }
  30 +
  31 + public static ApiError error(Integer status, String message){
  32 + ApiError apiError = new ApiError();
  33 + apiError.setStatus(status);
  34 + apiError.setMessage(message);
  35 + return apiError;
  36 + }
  37 +}
  38 +
  39 +
... ...
admin/src/main/java/com/canrd/shop/common/exception/handler/GlobalExceptionHandler.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/exception/handler/GlobalExceptionHandler.java
  1 +package com.canrd.shop.common.exception.handler;
  2 +
  3 +
  4 +import com.canrd.shop.common.constant.ServerResult;
  5 +import com.canrd.shop.common.constant.ServerResultCode;
  6 +import com.canrd.shop.common.exception.BadRequestException;
  7 +import com.canrd.shop.common.exception.BusinessException;
  8 +import com.canrd.shop.common.exception.EntityExistException;
  9 +import com.canrd.shop.common.exception.EntityNotFoundException;
  10 +import com.canrd.shop.common.utils.ThrowableUtil;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.http.HttpStatus;
  13 +import org.springframework.http.ResponseEntity;
  14 +import org.springframework.web.bind.MethodArgumentNotValidException;
  15 +import org.springframework.web.bind.annotation.ExceptionHandler;
  16 +import org.springframework.web.bind.annotation.ResponseStatus;
  17 +import org.springframework.web.bind.annotation.RestControllerAdvice;
  18 +import org.springframework.web.multipart.MaxUploadSizeExceededException;
  19 +
  20 +import java.util.Objects;
  21 +
  22 +/**
  23 + * @date 2018-11-23
  24 + */
  25 +@Slf4j
  26 +@RestControllerAdvice
  27 +public class GlobalExceptionHandler {
  28 + /**
  29 + * @param exception
  30 + * @return
  31 + * @throws Exception
  32 + */
  33 + @ExceptionHandler(value = RuntimeException.class)
  34 + public ResponseEntity<Object> handleServiceException(Exception exception) throws Exception {
  35 + return new ResponseEntity(translateException(exception), HttpStatus.OK);
  36 + }
  37 +
  38 + /**
  39 + * @param exception
  40 + * @return
  41 + * @throws Exception
  42 + */
  43 + @ExceptionHandler(value = Exception.class)
  44 + @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
  45 + public ResponseEntity<Object> handleException(Exception exception) throws Exception {
  46 + return new ResponseEntity<Object>(translateException(exception), HttpStatus.OK);
  47 + }
  48 +
  49 +
  50 + /**
  51 + * 处理所有接口数据验证异常
  52 + *
  53 + * @param e
  54 + * @return
  55 + */
  56 + @ExceptionHandler(MethodArgumentNotValidException.class)
  57 + public ResponseEntity<ServerResult> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
  58 + // 打印堆栈信息
  59 + log.error(ThrowableUtil.getStackTrace(e));
  60 + String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
  61 + String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
  62 + String msg = "不能为空";
  63 + if (msg.equals(message)) {
  64 + message = str[1] + ":" + message;
  65 + }
  66 + return buildResponseEntity(ServerResult.fail(message));
  67 + }
  68 +
  69 + /**
  70 + * 处理自定义异常
  71 + *
  72 + * @param e
  73 + * @return
  74 + */
  75 + @ExceptionHandler(value = BadRequestException.class)
  76 + public ResponseEntity<ServerResult> badRequestException(BadRequestException e) {
  77 + // 打印堆栈信息
  78 + log.error(ThrowableUtil.getStackTrace(e));
  79 + return buildResponseEntity(ServerResult.fail(e.getStatus(), e.getMessage()));
  80 + }
  81 +
  82 + /**
  83 + * 处理 EntityExist
  84 + */
  85 + @ExceptionHandler(value = EntityExistException.class)
  86 + public ResponseEntity<ServerResult> entityExistException(EntityExistException e) {
  87 + // 打印堆栈信息
  88 + log.error(ThrowableUtil.getStackTrace(e));
  89 + return buildResponseEntity(ServerResult.fail(e.getMessage()));
  90 + }
  91 +
  92 + /**
  93 + * 处理 EntityNotFound
  94 + *
  95 + * @param e
  96 + * @return
  97 + */
  98 + @ExceptionHandler(value = EntityNotFoundException.class)
  99 + public ResponseEntity<ServerResult> entityNotFoundException(EntityNotFoundException e) {
  100 + // 打印堆栈信息
  101 + log.error(ThrowableUtil.getStackTrace(e));
  102 + return buildResponseEntity(ServerResult.fail(HttpStatus.NOT_FOUND.value(), e.getMessage()));
  103 + }
  104 +
  105 + /**
  106 + * @param serverResult
  107 + * @return
  108 + */
  109 + private ResponseEntity<ServerResult> buildResponseEntity(ServerResult serverResult) {
  110 + return new ResponseEntity<>(serverResult, HttpStatus.valueOf(200));
  111 + }
  112 +
  113 + /**
  114 + * @param e
  115 + * @return
  116 + * @throws Exception
  117 + */
  118 + private Object translateException(Exception e) throws Exception {
  119 + ServerResult serverResult = null;
  120 + if (e instanceof NullPointerException) {
  121 + serverResult = ServerResult.fail(ServerResultCode.NULL_POINT);
  122 + } else if (e instanceof IllegalArgumentException) {
  123 + serverResult = ServerResult.fail(ServerResultCode.FAIL);
  124 + } else if (e instanceof MaxUploadSizeExceededException) {
  125 + serverResult = ServerResult.fail(ServerResultCode.FIlE_UPLOAD_TOO_LARGE);
  126 + } else if (e instanceof BusinessException) {
  127 + serverResult = ServerResult.fail(((BusinessException) e).getErrorCode(), ((BusinessException) e).getErrorDesc());
  128 + } else {
  129 + serverResult = ServerResult.fail(ServerResultCode.FAIL);
  130 + serverResult.setMessage(serverResult.getMessage() + "|,业务异常:" + e.getMessage());
  131 + }
  132 +
  133 + log.error("业务异常", e);
  134 + return serverResult;
  135 + }
  136 +}
... ...
admin/src/main/java/com/canrd/shop/common/jsr303/ListValueConstraintValidator.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/jsr303/ListValueConstraintValidator.java
  1 +package com.canrd.shop.common.jsr303;
  2 +
  3 +
  4 +import com.canrd.shop.common.jsr303.annotation.ListIntValue;
  5 +
  6 +import javax.validation.ConstraintValidator;
  7 +import javax.validation.ConstraintValidatorContext;
  8 +import java.util.HashSet;
  9 +import java.util.Set;
  10 +
  11 +/**
  12 + * 自定义校验注解 -枚举值校验
  13 + *
  14 + * @author fanzhenyu
  15 + * @date 2023-01-15
  16 + */
  17 +public class ListValueConstraintValidator implements ConstraintValidator<ListIntValue, Integer> {
  18 + private Set<Integer> set = new HashSet<>();
  19 + // 是否必填
  20 + private boolean require;
  21 +
  22 + @Override
  23 + public void initialize(ListIntValue constraintAnnotation) {
  24 + for (int i : constraintAnnotation.enumValue()) {
  25 + set.add(i);
  26 + }
  27 + require = constraintAnnotation.require();
  28 + }
  29 +
  30 + /**
  31 + * 判断是否通过校验
  32 + *
  33 + * @param value 传入的值
  34 + * @param context
  35 + * @return
  36 + */
  37 + @Override
  38 + public boolean isValid(Integer value, ConstraintValidatorContext context) {
  39 + if (!require && value == null) {
  40 + return true;
  41 + }
  42 + return set.contains(value);
  43 + }
  44 +
  45 +}
... ...
admin/src/main/java/com/canrd/shop/common/jsr303/OperateGroup.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/jsr303/OperateGroup.java
  1 +package com.canrd.shop.common.jsr303;
  2 +
  3 +
  4 +public class OperateGroup {
  5 + /**
  6 + * 新增校验
  7 + */
  8 + public interface Save {
  9 + }
  10 +
  11 + /**
  12 + * 删除校验
  13 + */
  14 + public interface Delete {
  15 + }
  16 +
  17 + /**
  18 + * 修改校验
  19 + */
  20 + public interface Update {
  21 + }
  22 +
  23 + /**
  24 + * 查询列表
  25 + */
  26 + public interface List {
  27 + }
  28 +
  29 + /**
  30 + * 分页查询
  31 + */
  32 + public interface Page {
  33 + }
  34 +
  35 + /**
  36 + * 长度校验
  37 + */
  38 + public interface Length {
  39 + }
  40 +
  41 + /**
  42 + * 格式校验
  43 + */
  44 + public interface Format {
  45 + }
  46 +
  47 + /**
  48 + * 详情
  49 + */
  50 + public interface Detail {
  51 + }
  52 +
  53 + /**
  54 + * 单条
  55 + */
  56 + public interface One {
  57 + }
  58 +
  59 +
  60 + public interface Trace {
  61 +
  62 + }
  63 +
  64 + /**
  65 + * 批量查询
  66 + */
  67 + public interface BatchQuery {
  68 + }
  69 +
  70 +
  71 + /**
  72 + * 导出
  73 + */
  74 + public interface Export {
  75 + }
  76 +
  77 +}
... ...
admin/src/main/java/com/canrd/shop/common/jsr303/annotation/ListIntValue.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/jsr303/annotation/ListIntValue.java
  1 +package com.canrd.shop.common.jsr303.annotation;
  2 +
  3 +
  4 +import com.canrd.shop.common.jsr303.ListValueConstraintValidator;
  5 +
  6 +import javax.validation.Constraint;
  7 +import javax.validation.Payload;
  8 +import java.lang.annotation.*;
  9 +
  10 +/**
  11 + * @author fanzhenyu
  12 + * @date 2023-01-15
  13 + */
  14 +@Constraint(validatedBy = {ListValueConstraintValidator.class})
  15 +@Documented
  16 +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +public @interface ListIntValue {
  19 +
  20 +
  21 + // 配置文件中错误提示信息的名称
  22 + String message() default "非法的类型";
  23 +
  24 + Class<?>[] groups() default {};
  25 +
  26 + Class<? extends Payload>[] payload() default {};
  27 +
  28 + // 自定义值的类型
  29 + int[] enumValue() default {};
  30 +
  31 + // 是否必填,默认允许为空
  32 + boolean require() default false;
  33 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/EncryptUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/EncryptUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import javax.crypto.Cipher;
  4 +import javax.crypto.SecretKey;
  5 +import javax.crypto.SecretKeyFactory;
  6 +import javax.crypto.spec.DESKeySpec;
  7 +import javax.crypto.spec.IvParameterSpec;
  8 +import java.nio.charset.StandardCharsets;
  9 +
  10 +/**
  11 + * 加密
  12 + *
  13 + * @date 2018-11-23
  14 + */
  15 +public class EncryptUtils {
  16 +
  17 + private static String strParam = "Passw0rd";
  18 +
  19 + private static Cipher cipher;
  20 +
  21 + private static IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
  22 +
  23 + private static DESKeySpec getDesKeySpec(String source) throws Exception {
  24 + if (source == null || source.length() == 0) {
  25 + return null;
  26 + }
  27 + cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
  28 + String strKey = "Passw0rd";
  29 + return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
  30 + }
  31 +
  32 + /**
  33 + * 对称加密
  34 + */
  35 + public static String desEncrypt(String source) throws Exception {
  36 + DESKeySpec desKeySpec = getDesKeySpec(source);
  37 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  38 + SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
  39 + cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
  40 + return byte2hex(
  41 + cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
  42 + }
  43 +
  44 + /**
  45 + * 对称解密
  46 + */
  47 + public static String desDecrypt(String source) throws Exception {
  48 + byte[] src = hex2byte(source.getBytes());
  49 + DESKeySpec desKeySpec = getDesKeySpec(source);
  50 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  51 + SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
  52 + cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
  53 + byte[] retByte = cipher.doFinal(src);
  54 + return new String(retByte);
  55 + }
  56 +
  57 + private static String byte2hex(byte[] inStr) {
  58 + String stmp;
  59 + StringBuilder out = new StringBuilder(inStr.length * 2);
  60 + for (byte b : inStr) {
  61 + stmp = Integer.toHexString(b & 0xFF);
  62 + if (stmp.length() == 1) {
  63 + // 如果是0至F的单位字符串,则添加0
  64 + out.append("0").append(stmp);
  65 + } else {
  66 + out.append(stmp);
  67 + }
  68 + }
  69 + return out.toString();
  70 + }
  71 +
  72 + private static byte[] hex2byte(byte[] b) {
  73 + int size = 2;
  74 + if ((b.length % size) != 0) {
  75 + throw new IllegalArgumentException("长度不是偶数");
  76 + }
  77 + byte[] b2 = new byte[b.length / 2];
  78 + for (int n = 0; n < b.length; n += size) {
  79 + String item = new String(b, n, 2);
  80 + b2[n / 2] = (byte) Integer.parseInt(item, 16);
  81 + }
  82 + return b2;
  83 + }
  84 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/FileUtil.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/FileUtil.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import cn.hutool.core.codec.Base64;
  4 +import cn.hutool.core.io.IoUtil;
  5 +import cn.hutool.core.util.IdUtil;
  6 +import cn.hutool.poi.excel.BigExcelWriter;
  7 +import cn.hutool.poi.excel.ExcelUtil;
  8 +import org.apache.poi.util.IOUtils;
  9 +import org.springframework.web.multipart.MultipartFile;
  10 +
  11 +import javax.activation.MimetypesFileTypeMap;
  12 +import javax.servlet.ServletOutputStream;
  13 +import javax.servlet.http.HttpServletRequest;
  14 +import javax.servlet.http.HttpServletResponse;
  15 +import java.io.*;
  16 +import java.security.MessageDigest;
  17 +import java.text.DecimalFormat;
  18 +import java.text.SimpleDateFormat;
  19 +import java.util.Date;
  20 +import java.util.List;
  21 +import java.util.Map;
  22 +
  23 +/**
  24 + * File工具类,扩展 hutool 工具包
  25 + *
  26 + * @date 2018-12-27
  27 + */
  28 +public class FileUtil extends cn.hutool.core.io.FileUtil {
  29 +
  30 + /**
  31 + * 定义GB的计算常量
  32 + */
  33 + private static final int GB = 1024 * 1024 * 1024;
  34 + /**
  35 + * 定义MB的计算常量
  36 + */
  37 + private static final int MB = 1024 * 1024;
  38 + /**
  39 + * 定义KB的计算常量
  40 + */
  41 + private static final int KB = 1024;
  42 +
  43 + /**
  44 + * 格式化小数
  45 + */
  46 + private static final DecimalFormat DF = new DecimalFormat("0.00");
  47 +
  48 + /**
  49 + * MultipartFile转File
  50 + */
  51 + public static File toFile(MultipartFile multipartFile) {
  52 + // 获取文件名
  53 + String fileName = multipartFile.getOriginalFilename();
  54 + // 获取文件后缀
  55 + String prefix = "." + getExtensionName(fileName);
  56 + File file = null;
  57 + try {
  58 + // 用uuid作为文件名,防止生成的临时文件重复
  59 + file = File.createTempFile(IdUtil.simpleUUID(), prefix);
  60 + // MultipartFile to File
  61 + multipartFile.transferTo(file);
  62 + } catch (IOException e) {
  63 + e.printStackTrace();
  64 + }
  65 + return file;
  66 + }
  67 +
  68 + /**
  69 + * 获取文件扩展名,不带 .
  70 + */
  71 + public static String getExtensionName(String filename) {
  72 + if ((filename != null) && (filename.length() > 0)) {
  73 + int dot = filename.lastIndexOf('.');
  74 + if ((dot > -1) && (dot < (filename.length() - 1))) {
  75 + return filename.substring(dot + 1);
  76 + }
  77 + }
  78 + return filename;
  79 + }
  80 +
  81 + /**
  82 + * Java文件操作 获取不带扩展名的文件名
  83 + */
  84 + public static String getFileNameNoEx(String filename) {
  85 + if ((filename != null) && (filename.length() > 0)) {
  86 + int dot = filename.lastIndexOf('.');
  87 + if ((dot > -1) && (dot < (filename.length()))) {
  88 + return filename.substring(0, dot);
  89 + }
  90 + }
  91 + return filename;
  92 + }
  93 +
  94 + /**
  95 + * 文件大小转换
  96 + */
  97 + public static String getSize(long size) {
  98 + String resultSize;
  99 + if (size / GB >= 1) {
  100 + //如果当前Byte的值大于等于1GB
  101 + resultSize = DF.format(size / (float) GB) + "GB ";
  102 + } else if (size / MB >= 1) {
  103 + //如果当前Byte的值大于等于1MB
  104 + resultSize = DF.format(size / (float) MB) + "MB ";
  105 + } else if (size / KB >= 1) {
  106 + //如果当前Byte的值大于等于1KB
  107 + resultSize = DF.format(size / (float) KB) + "KB ";
  108 + } else {
  109 + resultSize = size + "B ";
  110 + }
  111 + return resultSize;
  112 + }
  113 +
  114 + /**
  115 + * inputStream 转 File
  116 + */
  117 + static File inputStreamToFile(InputStream ins, String name) throws Exception {
  118 + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
  119 + if (file.exists()) {
  120 + return file;
  121 + }
  122 + OutputStream os = new FileOutputStream(file);
  123 + int bytesRead;
  124 + int len = 8192;
  125 + byte[] buffer = new byte[len];
  126 + while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
  127 + os.write(buffer, 0, bytesRead);
  128 + }
  129 + os.close();
  130 + ins.close();
  131 + return file;
  132 + }
  133 +
  134 + /**
  135 + * 将文件名解析成文件的上传路径
  136 + */
  137 + public static File upload(MultipartFile file, String filePath) {
  138 + Date date = new Date();
  139 + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
  140 + String name = getFileNameNoEx(file.getOriginalFilename());
  141 + String suffix = getExtensionName(file.getOriginalFilename());
  142 + String nowStr = "-" + format.format(date);
  143 + try {
  144 + String fileName = name + nowStr + "." + suffix;
  145 + String path = filePath + fileName;
  146 + // getCanonicalFile 可解析正确各种路径
  147 + File dest = new File(path).getCanonicalFile();
  148 + // 检测是否存在目录
  149 + if (!dest.getParentFile().exists()) {
  150 + dest.getParentFile().mkdirs();
  151 + }
  152 + // 文件写入
  153 + file.transferTo(dest);
  154 + return dest;
  155 + } catch (Exception e) {
  156 + e.printStackTrace();
  157 + }
  158 + return null;
  159 + }
  160 +
  161 + public static String fileToBase64(File file) throws Exception {
  162 + FileInputStream inputFile = new FileInputStream(file);
  163 + String base64;
  164 + byte[] buffer = new byte[(int) file.length()];
  165 + inputFile.read(buffer);
  166 + inputFile.close();
  167 + base64 = Base64.encode(buffer);
  168 + return base64.replaceAll("[\\s*\t\n\r]", "");
  169 + }
  170 +
  171 + /**
  172 + * 导出excel
  173 + */
  174 + public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
  175 + String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
  176 + File file = new File(tempPath);
  177 + BigExcelWriter writer = ExcelUtil.getBigWriter(file);
  178 + // 一次性写出内容,使用默认样式,强制输出标题
  179 + writer.write(list, true);
  180 + //response为HttpServletResponse对象
  181 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
  182 + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
  183 + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
  184 + ServletOutputStream out = response.getOutputStream();
  185 + // 终止后删除临时文件
  186 + file.deleteOnExit();
  187 + writer.flush(out, true);
  188 + //此处记得关闭输出Servlet流
  189 + IoUtil.close(out);
  190 + }
  191 +
  192 + public static String getFileType(String type) {
  193 + String documents = "txt doc pdf ppt pps xlsx xls docx";
  194 + String music = "mp3 wav wma mpa ram ra aac aif m4a";
  195 + String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
  196 + String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
  197 + if (image.contains(type)) {
  198 + return "图片";
  199 + } else if (documents.contains(type)) {
  200 + return "文档";
  201 + } else if (music.contains(type)) {
  202 + return "音乐";
  203 + } else if (video.contains(type)) {
  204 + return "视频";
  205 + } else {
  206 + return "其他";
  207 + }
  208 + }
  209 +
  210 + public static String getFileTypeByMimeType(String type) {
  211 + String mimeType = new MimetypesFileTypeMap().getContentType("." + type);
  212 + return mimeType.split("/")[0];
  213 + }
  214 +
  215 + public static void checkSize(long maxSize, long size) {
  216 + // 1M
  217 + int len = 1024 * 1024;
  218 + if (size > (maxSize * len)) {
  219 + throw new RuntimeException("文件超出规定大小");
  220 + }
  221 + }
  222 +
  223 + /**
  224 + * 判断两个文件是否相同
  225 + */
  226 + public static boolean check(File file1, File file2) {
  227 + String img1Md5 = getMd5(file1);
  228 + String img2Md5 = getMd5(file2);
  229 + return img1Md5.equals(img2Md5);
  230 + }
  231 +
  232 + /**
  233 + * 判断两个文件是否相同
  234 + */
  235 + public static boolean check(String file1Md5, String file2Md5) {
  236 + return file1Md5.equals(file2Md5);
  237 + }
  238 +
  239 + private static byte[] getByte(File file) {
  240 + // 得到文件长度
  241 + byte[] b = new byte[(int) file.length()];
  242 + try {
  243 + InputStream in = new FileInputStream(file);
  244 + try {
  245 + in.read(b);
  246 + } catch (IOException e) {
  247 + e.printStackTrace();
  248 + }
  249 + } catch (FileNotFoundException e) {
  250 + e.printStackTrace();
  251 + return null;
  252 + }
  253 + return b;
  254 + }
  255 +
  256 + private static String getMd5(byte[] bytes) {
  257 + // 16进制字符
  258 + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  259 + try {
  260 + MessageDigest mdTemp = MessageDigest.getInstance("MD5");
  261 + mdTemp.update(bytes);
  262 + byte[] md = mdTemp.digest();
  263 + int j = md.length;
  264 + char[] str = new char[j * 2];
  265 + int k = 0;
  266 + // 移位 输出字符串
  267 + for (byte byte0 : md) {
  268 + str[k++] = hexDigits[byte0 >>> 4 & 0xf];
  269 + str[k++] = hexDigits[byte0 & 0xf];
  270 + }
  271 + return new String(str);
  272 + } catch (Exception e) {
  273 + e.printStackTrace();
  274 + }
  275 + return null;
  276 + }
  277 +
  278 + /**
  279 + * 下载文件
  280 + *
  281 + * @param request /
  282 + * @param response /
  283 + * @param file /
  284 + */
  285 + public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
  286 + response.setCharacterEncoding(request.getCharacterEncoding());
  287 + response.setContentType("application/octet-stream");
  288 + FileInputStream fis = null;
  289 + try {
  290 + fis = new FileInputStream(file);
  291 + response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
  292 + IOUtils.copy(fis, response.getOutputStream());
  293 + response.flushBuffer();
  294 + } catch (Exception e) {
  295 + e.printStackTrace();
  296 + } finally {
  297 + if (fis != null) {
  298 + try {
  299 + fis.close();
  300 + if (deleteOnExit) {
  301 + file.deleteOnExit();
  302 + }
  303 + } catch (IOException e) {
  304 + e.printStackTrace();
  305 + }
  306 + }
  307 + }
  308 + }
  309 +
  310 + public static String getMd5(File file) {
  311 + return getMd5(getByte(file));
  312 + }
  313 +
  314 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/JsonUtil.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/JsonUtil.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +
  4 +import com.alibaba.fastjson.JSONException;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.fasterxml.jackson.annotation.JsonInclude;
  7 +import com.fasterxml.jackson.core.JsonGenerator;
  8 +import com.fasterxml.jackson.core.JsonProcessingException;
  9 +import com.fasterxml.jackson.core.type.TypeReference;
  10 +import com.fasterxml.jackson.databind.*;
  11 +import com.fasterxml.jackson.databind.node.ArrayNode;
  12 +import com.fasterxml.jackson.databind.node.ObjectNode;
  13 +import lombok.extern.slf4j.Slf4j;
  14 +
  15 +import java.io.IOException;
  16 +
  17 +/**
  18 + *
  19 + * @author achims
  20 + * @date 2019/11/4
  21 + * 用于转换成json字符串以及解析成对象
  22 + */
  23 +@Slf4j
  24 +public class JsonUtil {
  25 +
  26 + private static ObjectMapper mapper = new ObjectMapper();
  27 +
  28 + static {
  29 + log.info("注册jackson-datatype-jsr310的java8时间处理模块");
  30 + mapper.findAndRegisterModules();
  31 + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  32 + mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
  33 + @Override
  34 + public void serialize(Object paramT, JsonGenerator paramJsonGenerator,
  35 + SerializerProvider paramSerializerProvider) throws IOException {
  36 + //设置返回null转为 空字符串""
  37 + paramJsonGenerator.writeString("");
  38 + }
  39 + });
  40 + }
  41 +
  42 +
  43 +
  44 +
  45 + /**
  46 + * Create empty json node
  47 + *
  48 + * @return
  49 + */
  50 + public static ObjectNode createJsonNode() {
  51 + return mapper.createObjectNode();
  52 + }
  53 +
  54 + /**
  55 + * Create empty json Array
  56 + *
  57 + * @return
  58 + */
  59 + public static ArrayNode createJsonArray() {
  60 + return mapper.createArrayNode();
  61 +
  62 + }
  63 +
  64 + /**
  65 + * Convert the object to corresponding json string
  66 + *
  67 + * @param obj
  68 + * @return
  69 + */
  70 + public static String toJsonString(Object obj) {
  71 + try {
  72 + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
  73 + return mapper.writeValueAsString(obj);
  74 + } catch (JsonProcessingException e) {
  75 + return null;
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * 转成格式化后的json,便于调试排错
  81 + * @param obj
  82 + * @return
  83 + */
  84 + public static String toJsonStringWithDefaultPretty(Object obj) {
  85 + try {
  86 + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
  87 + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
  88 + } catch (JsonProcessingException e) {
  89 +
  90 + return null;
  91 + }
  92 + }
  93 +
  94 + public static <T> T jsonToEntity(String json, Class<T> clazz) {
  95 + if (StringUtils.isEmpty(json)) return null;
  96 + try {
  97 + return mapper.readValue(json, clazz);
  98 + } catch (IOException e) {
  99 + e.printStackTrace();
  100 + }
  101 + return null;
  102 + }
  103 +
  104 + /**
  105 + * 借助json做中转,实体类转实体类
  106 + * @param obj 实体
  107 + * @param clazz 目标类型
  108 + * @param <T> 目标泛型
  109 + * @return 结果
  110 + */
  111 + public static <T> T entityConvert(Object obj, Class<T> clazz) {
  112 + return jsonToEntity(toJsonString(obj), clazz);
  113 + }
  114 +
  115 + /**
  116 + * 带泛型返回不告警
  117 + * @param json json字符
  118 + * @param typeReference TypeReference
  119 + * @param <R> 返回类型
  120 + * @param <T> 转换的类型
  121 + * @return 转换结果
  122 + * @author 刘迪榕
  123 + * @version Date 2022-08-26
  124 + */
  125 + public static <R, T extends R> R jsonToEntity(String json, TypeReference<T> typeReference) {
  126 + if (StringUtils.isEmpty(json)) return null;
  127 + try {
  128 + return mapper.readValue(json, typeReference);
  129 + } catch (IOException e) {
  130 + e.printStackTrace();
  131 + }
  132 + return null;
  133 + }
  134 +
  135 + public static JsonNode readStringAsJsonNode(String json) {
  136 + try {
  137 + return mapper.readValue(json, JsonNode.class);
  138 + } catch (IOException e) {
  139 + e.printStackTrace();
  140 + }
  141 + return null;
  142 + }
  143 +
  144 + public static JsonNode valueToTree(Object value) {
  145 + return mapper.valueToTree(value);
  146 + }
  147 +
  148 + public static <T> T treeToValue(JsonNode jsonNode, Class<T> clazz) {
  149 + try {
  150 + return mapper.treeToValue(jsonNode, clazz);
  151 + } catch (IOException e) {
  152 + e.printStackTrace();
  153 + }
  154 + return null;
  155 + }
  156 +
  157 + /**
  158 + * 是否爲json格式的數據
  159 + *
  160 + * @param test
  161 + * @return
  162 + */
  163 + public final static boolean isJSONValid(String test) {
  164 + try {
  165 + JSONObject.parseObject(test);
  166 + } catch (JSONException ex) {
  167 + try {
  168 + JSONObject.parseArray(test);
  169 + } catch (JSONException ex1) {
  170 + return false;
  171 + }
  172 + }
  173 + return true;
  174 + }
  175 +
  176 + public <T> T paraseJsonTOClass(String json, Class<T> cla) {
  177 + try {
  178 + return JSONObject.parseObject(json, cla);
  179 + } catch (JSONException ex) {
  180 + return null;
  181 + }
  182 + }
  183 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/LocalDateTimeUtil.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/LocalDateTimeUtil.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.joda.time.DateTime;
  4 +
  5 +import java.time.LocalDateTime;
  6 +
  7 +/**
  8 + * @author: xms
  9 + * @description: TODO
  10 + * @date: 2023/1/16 16:35
  11 + * @version: 1.0
  12 + */
  13 +public class LocalDateTimeUtil {
  14 +
  15 + /**
  16 + * @param dateTime
  17 + * @return
  18 + */
  19 + public static LocalDateTime toLocalDateTime(DateTime dateTime) {
  20 + return LocalDateTime.of(dateTime.getYear(), dateTime.getMonthOfYear(),
  21 + dateTime.getDayOfMonth(), dateTime.getHourOfDay(),
  22 + dateTime.getMinuteOfHour(), dateTime.getSecondOfMinute());
  23 + }
  24 +
  25 + /**
  26 + *
  27 + * @param localDateTime
  28 + * @return
  29 + */
  30 + public static DateTime toDateTime(LocalDateTime localDateTime) {
  31 + return new DateTime().withYear(localDateTime.getYear()).withMonthOfYear(localDateTime.getMonthValue())
  32 + .withDayOfMonth(localDateTime.getDayOfMonth()).withHourOfDay(localDateTime.getHour())
  33 + .withMinuteOfHour(localDateTime.getMinute()).withSecondOfMinute(localDateTime.getSecond());
  34 + }
  35 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/PageUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/PageUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.baomidou.mybatisplus.core.metadata.IPage;
  4 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5 +import com.canrd.shop.domain.vo.BasePageVO;
  6 +import org.springframework.util.CollectionUtils;
  7 +
  8 +import java.io.Serializable;
  9 +import java.util.*;
  10 +
  11 +/**
  12 + * @Author: dengbin
  13 + * @Date: 2020/9/11
  14 + * 分页工具类
  15 + */
  16 +
  17 +public class PageUtils implements Serializable {
  18 + private static final long serialVersionUID = 4359709211352400087L;
  19 + private static final String PAGE_INDEX = "pageNo";
  20 + private static final String PAGE_SIZE = "pageSize";
  21 + private static final String TOTAL_ROWS = "total";
  22 + private static final String TOTAL_PAGES = "pages";
  23 + private static final String RECORDS = "records";
  24 +
  25 + private static final int DEFAULT_PAGE_INDEX = 1;
  26 + private static final int DEFAULT_PAGE_SIZE = 10;
  27 + private static final int DEFAULT_MAP_CAPACITY = 5;
  28 +
  29 + /**
  30 + * 统一分页返回对象
  31 + *
  32 + * @param list
  33 + * @return
  34 + */
  35 + public static Map<String, Object> getUnifiedPageReturn(IPage list) {
  36 + if (list == null) {
  37 + return getUnifiedEmptyPage(DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE);
  38 + }
  39 +
  40 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  41 + resultMap.put(PAGE_INDEX, list.getCurrent());
  42 + resultMap.put(PAGE_SIZE, list.getSize());
  43 + resultMap.put(RECORDS, list.getRecords());
  44 + resultMap.put(TOTAL_PAGES, list.getPages());
  45 + resultMap.put(TOTAL_ROWS, list.getTotal());
  46 +
  47 + return resultMap;
  48 + }
  49 +
  50 + /**
  51 + * 返回空分页信息给前端
  52 + * 返回空或其他字段不满足前端要求,会报错
  53 + *
  54 + * @return
  55 + */
  56 + public static Map<String, Object> getUnifiedEmptyPage(int pageIndex, int pageSize) {
  57 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  58 + resultMap.put(PAGE_INDEX, pageIndex);
  59 + resultMap.put(PAGE_SIZE, pageSize);
  60 + resultMap.put(RECORDS, new ArrayList<>());
  61 + resultMap.put(TOTAL_PAGES, 0);
  62 + resultMap.put(TOTAL_ROWS, 0);
  63 + return resultMap;
  64 + }
  65 +
  66 + public static Map<String, Object> getUnifiedEmptyPage(BasePageVO pageVO) {
  67 + return getUnifiedEmptyPage(pageVO.getPageNo(), pageVO.getPageSize());
  68 + }
  69 +
  70 +
  71 + /**
  72 + * 将旧的分页转换成新的分页对象
  73 + *
  74 + * @param oldPage 旧的分页对象,例如:xxDo的分页对象
  75 + * @param records 新的分页对象,例如:xxVo的分页对象
  76 + * @param <T> 新的分页对象的类型
  77 + * @return 统一的返回的分页对象
  78 + */
  79 + public static <T> Map<String, Object> transferPage(IPage<?> oldPage, List<T> records) {
  80 + Page<T> newPage = new Page<>();
  81 + newPage.setCurrent(oldPage.getCurrent());
  82 + newPage.setSize(oldPage.getSize());
  83 + newPage.setRecords(records);
  84 + newPage.setPages(oldPage.getPages());
  85 + newPage.setTotal(oldPage.getTotal());
  86 + return getUnifiedPageReturn(newPage);
  87 + }
  88 +
  89 + /**
  90 + * 统一分页返回对象
  91 + *
  92 + * @param records 分页数据
  93 + * @param pageVO 分页参数
  94 + * @return
  95 + */
  96 + public static Map<String, Object> getPageReturn(List records, BasePageVO pageVO) {
  97 + if (records == null) {
  98 + return getUnifiedEmptyPage(DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE);
  99 + }
  100 + if (CollectionUtils.isEmpty(records)) {
  101 + return getUnifiedEmptyPage(Math.toIntExact(pageVO.getPageNo()), Math.toIntExact(pageVO.getPageSize()));
  102 + }
  103 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  104 + resultMap.put(PAGE_INDEX, pageVO.getPageNo());
  105 + resultMap.put(PAGE_SIZE, pageVO.getPageSize());
  106 + resultMap.put(RECORDS, records);
  107 + resultMap.put(TOTAL_PAGES, (pageVO.getTotal() + pageVO.getPageSize() - 1) / pageVO.getPageSize());
  108 + resultMap.put(TOTAL_ROWS, pageVO.getTotal());
  109 +
  110 + return resultMap;
  111 + }
  112 +
  113 + public static <T> Page<T> getRAMPageReturn(Integer current, Integer size, List<T> records) {
  114 + if (Objects.isNull(current)) {
  115 + current = 1;
  116 + }
  117 + if (Objects.isNull(size)) {
  118 + size = 10;
  119 + }
  120 + int startIndex = (current - 1) * size;
  121 + int endIndex = Math.min(current * size, records.size());
  122 + if (startIndex > endIndex) {
  123 + startIndex = endIndex;
  124 + }
  125 + Page<T> page = new Page<>();
  126 + page.setCurrent(current);
  127 + page.setSize(size);
  128 + page.setRecords(records.subList(startIndex, endIndex));
  129 + int totalPages = size == 0 ? 0 : records.size() % size == 0 ? (records.size() / size) : (records.size() / size + 1);
  130 + page.setPages(totalPages);
  131 + page.setTotal(records.size());
  132 + return page;
  133 + }
  134 +
  135 +
  136 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/RedisUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/RedisUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.springframework.beans.factory.annotation.Value;
  4 +import org.springframework.data.redis.connection.RedisConnection;
  5 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  6 +import org.springframework.data.redis.core.Cursor;
  7 +import org.springframework.data.redis.core.RedisConnectionUtils;
  8 +import org.springframework.data.redis.core.RedisTemplate;
  9 +import org.springframework.data.redis.core.ScanOptions;
  10 +import org.springframework.stereotype.Component;
  11 +import org.springframework.util.CollectionUtils;
  12 +
  13 +import java.util.*;
  14 +import java.util.concurrent.TimeUnit;
  15 +
  16 +/**
  17 + * @author /
  18 + */
  19 +@Component
  20 +@SuppressWarnings({"unchecked", "all"})
  21 +public class RedisUtils {
  22 +
  23 + private RedisTemplate<Object, Object> redisTemplate;
  24 + @Value("${jwt.online-key}")
  25 + private String onlineKey;
  26 +
  27 + public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
  28 + this.redisTemplate = redisTemplate;
  29 + }
  30 +
  31 + // =============================common============================
  32 +
  33 + /**
  34 + * 指定缓存失效时间
  35 + *
  36 + * @param key 键
  37 + * @param time 时间(秒)
  38 + */
  39 + public boolean expire(String key, long time) {
  40 + try {
  41 + if (time > 0) {
  42 + redisTemplate.expire(key, time, TimeUnit.SECONDS);
  43 + }
  44 + } catch (Exception e) {
  45 + e.printStackTrace();
  46 + return false;
  47 + }
  48 + return true;
  49 + }
  50 +
  51 + /**
  52 + * 根据 key 获取过期时间
  53 + *
  54 + * @param key 键 不能为null
  55 + * @return 时间(秒) 返回0代表为永久有效
  56 + */
  57 + public long getExpire(Object key) {
  58 + return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  59 + }
  60 +
  61 + /**
  62 + * 查找匹配key
  63 + *
  64 + * @param pattern key
  65 + * @return /
  66 + */
  67 + public List<String> scan(String pattern) {
  68 + ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
  69 + RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
  70 + RedisConnection rc = Objects.requireNonNull(factory).getConnection();
  71 + Cursor<byte[]> cursor = rc.scan(options);
  72 + List<String> result = new ArrayList<>();
  73 + while (cursor.hasNext()) {
  74 + result.add(new String(cursor.next()));
  75 + }
  76 + try {
  77 + RedisConnectionUtils.releaseConnection(rc, factory);
  78 + } catch (Exception e) {
  79 + e.printStackTrace();
  80 + }
  81 + return result;
  82 + }
  83 +
  84 + /**
  85 + * 分页查询 key
  86 + *
  87 + * @param patternKey key
  88 + * @param page 页码
  89 + * @param size 每页数目
  90 + * @return /
  91 + */
  92 + public List<String> findKeysForPage(String patternKey, int page, int size) {
  93 + ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
  94 + RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
  95 + RedisConnection rc = Objects.requireNonNull(factory).getConnection();
  96 + Cursor<byte[]> cursor = rc.scan(options);
  97 + List<String> result = new ArrayList<>(size);
  98 + int tmpIndex = 0;
  99 + int fromIndex = page * size;
  100 + int toIndex = page * size + size;
  101 + while (cursor.hasNext()) {
  102 + if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
  103 + result.add(new String(cursor.next()));
  104 + tmpIndex++;
  105 + continue;
  106 + }
  107 + // 获取到满足条件的数据后,就可以退出了
  108 + if (tmpIndex >= toIndex) {
  109 + break;
  110 + }
  111 + tmpIndex++;
  112 + cursor.next();
  113 + }
  114 + try {
  115 + RedisConnectionUtils.releaseConnection(rc, factory);
  116 + } catch (Exception e) {
  117 + e.printStackTrace();
  118 + }
  119 + return result;
  120 + }
  121 +
  122 + /**
  123 + * 判断key是否存在
  124 + *
  125 + * @param key 键
  126 + * @return true 存在 false不存在
  127 + */
  128 + public boolean hasKey(String key) {
  129 + try {
  130 + return redisTemplate.hasKey(key);
  131 + } catch (Exception e) {
  132 + e.printStackTrace();
  133 + return false;
  134 + }
  135 + }
  136 +
  137 + /**
  138 + * 删除缓存
  139 + *
  140 + * @param key 可以传一个值 或多个
  141 + */
  142 + public void del(String... key) {
  143 + if (key != null && key.length > 0) {
  144 + if (key.length == 1) {
  145 + redisTemplate.delete(key[0]);
  146 + } else {
  147 + redisTemplate.delete(CollectionUtils.arrayToList(key));
  148 + }
  149 + }
  150 + }
  151 +
  152 + // ============================String=============================
  153 +
  154 + /**
  155 + * 普通缓存获取
  156 + *
  157 + * @param key 键
  158 + * @return 值
  159 + */
  160 + public Object get(String key) {
  161 + return key == null ? null : redisTemplate.opsForValue().get(key);
  162 + }
  163 +
  164 + /**
  165 + * 批量获取
  166 + *
  167 + * @param keys
  168 + * @return
  169 + */
  170 + public List<Object> multiGet(List<String> keys) {
  171 + Object obj = redisTemplate.opsForValue().multiGet(Collections.singleton(keys));
  172 + return null;
  173 + }
  174 +
  175 + /**
  176 + * 普通缓存放入
  177 + *
  178 + * @param key 键
  179 + * @param value 值
  180 + * @return true成功 false失败
  181 + */
  182 + public boolean set(String key, Object value) {
  183 + try {
  184 + redisTemplate.opsForValue().set(key, value);
  185 + return true;
  186 + } catch (Exception e) {
  187 + e.printStackTrace();
  188 + return false;
  189 + }
  190 + }
  191 +
  192 + /**
  193 + * 普通缓存放入并设置时间
  194 + *
  195 + * @param key 键
  196 + * @param value 值
  197 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  198 + * @return true成功 false 失败
  199 + */
  200 + public boolean set(String key, Object value, long time) {
  201 + try {
  202 + if (time > 0) {
  203 + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  204 + } else {
  205 + set(key, value);
  206 + }
  207 + return true;
  208 + } catch (Exception e) {
  209 + e.printStackTrace();
  210 + return false;
  211 + }
  212 + }
  213 +
  214 + /**
  215 + * 普通缓存放入并设置时间
  216 + *
  217 + * @param key 键
  218 + * @param value 值
  219 + * @param time 时间
  220 + * @param timeUnit 类型
  221 + * @return true成功 false 失败
  222 + */
  223 + public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
  224 + try {
  225 + if (time > 0) {
  226 + redisTemplate.opsForValue().set(key, value, time, timeUnit);
  227 + } else {
  228 + set(key, value);
  229 + }
  230 + return true;
  231 + } catch (Exception e) {
  232 + e.printStackTrace();
  233 + return false;
  234 + }
  235 + }
  236 +
  237 + // ================================Map=================================
  238 +
  239 + /**
  240 + * HashGet
  241 + *
  242 + * @param key 键 不能为null
  243 + * @param item 项 不能为null
  244 + * @return 值
  245 + */
  246 + public Object hget(String key, String item) {
  247 + return redisTemplate.opsForHash().get(key, item);
  248 + }
  249 +
  250 + /**
  251 + * 获取hashKey对应的所有键值
  252 + *
  253 + * @param key 键
  254 + * @return 对应的多个键值
  255 + */
  256 + public Map<Object, Object> hmget(String key) {
  257 + return redisTemplate.opsForHash().entries(key);
  258 +
  259 + }
  260 +
  261 + /**
  262 + * HashSet
  263 + *
  264 + * @param key 键
  265 + * @param map 对应多个键值
  266 + * @return true 成功 false 失败
  267 + */
  268 + public boolean hmset(String key, Map<String, Object> map) {
  269 + try {
  270 + redisTemplate.opsForHash().putAll(key, map);
  271 + return true;
  272 + } catch (Exception e) {
  273 + e.printStackTrace();
  274 + return false;
  275 + }
  276 + }
  277 +
  278 + /**
  279 + * HashSet 并设置时间
  280 + *
  281 + * @param key 键
  282 + * @param map 对应多个键值
  283 + * @param time 时间(秒)
  284 + * @return true成功 false失败
  285 + */
  286 + public boolean hmset(String key, Map<String, Object> map, long time) {
  287 + try {
  288 + redisTemplate.opsForHash().putAll(key, map);
  289 + if (time > 0) {
  290 + expire(key, time);
  291 + }
  292 + return true;
  293 + } catch (Exception e) {
  294 + e.printStackTrace();
  295 + return false;
  296 + }
  297 + }
  298 +
  299 + /**
  300 + * 向一张hash表中放入数据,如果不存在将创建
  301 + *
  302 + * @param key 键
  303 + * @param item 项
  304 + * @param value 值
  305 + * @return true 成功 false失败
  306 + */
  307 + public boolean hset(String key, String item, Object value) {
  308 + try {
  309 + redisTemplate.opsForHash().put(key, item, value);
  310 + return true;
  311 + } catch (Exception e) {
  312 + e.printStackTrace();
  313 + return false;
  314 + }
  315 + }
  316 +
  317 + /**
  318 + * 向一张hash表中放入数据,如果不存在将创建
  319 + *
  320 + * @param key 键
  321 + * @param item 项
  322 + * @param value 值
  323 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  324 + * @return true 成功 false失败
  325 + */
  326 + public boolean hset(String key, String item, Object value, long time) {
  327 + try {
  328 + redisTemplate.opsForHash().put(key, item, value);
  329 + if (time > 0) {
  330 + expire(key, time);
  331 + }
  332 + return true;
  333 + } catch (Exception e) {
  334 + e.printStackTrace();
  335 + return false;
  336 + }
  337 + }
  338 +
  339 + /**
  340 + * 删除hash表中的值
  341 + *
  342 + * @param key 键 不能为null
  343 + * @param item 项 可以使多个 不能为null
  344 + */
  345 + public void hdel(String key, Object... item) {
  346 + redisTemplate.opsForHash().delete(key, item);
  347 + }
  348 +
  349 + /**
  350 + * 判断hash表中是否有该项的值
  351 + *
  352 + * @param key 键 不能为null
  353 + * @param item 项 不能为null
  354 + * @return true 存在 false不存在
  355 + */
  356 + public boolean hHasKey(String key, String item) {
  357 + return redisTemplate.opsForHash().hasKey(key, item);
  358 + }
  359 +
  360 + /**
  361 + * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  362 + *
  363 + * @param key 键
  364 + * @param item 项
  365 + * @param by 要增加几(大于0)
  366 + * @return
  367 + */
  368 + public double hincr(String key, String item, double by) {
  369 + return redisTemplate.opsForHash().increment(key, item, by);
  370 + }
  371 +
  372 + /**
  373 + * hash递减
  374 + *
  375 + * @param key 键
  376 + * @param item 项
  377 + * @param by 要减少记(小于0)
  378 + * @return
  379 + */
  380 + public double hdecr(String key, String item, double by) {
  381 + return redisTemplate.opsForHash().increment(key, item, -by);
  382 + }
  383 +
  384 + // ============================set=============================
  385 +
  386 + /**
  387 + * 根据key获取Set中的所有值
  388 + *
  389 + * @param key 键
  390 + * @return
  391 + */
  392 + public Set<Object> sGet(String key) {
  393 + try {
  394 + return redisTemplate.opsForSet().members(key);
  395 + } catch (Exception e) {
  396 + e.printStackTrace();
  397 + return null;
  398 + }
  399 + }
  400 +
  401 + /**
  402 + * 根据value从一个set中查询,是否存在
  403 + *
  404 + * @param key 键
  405 + * @param value 值
  406 + * @return true 存在 false不存在
  407 + */
  408 + public boolean sHasKey(String key, Object value) {
  409 + try {
  410 + return redisTemplate.opsForSet().isMember(key, value);
  411 + } catch (Exception e) {
  412 + e.printStackTrace();
  413 + return false;
  414 + }
  415 + }
  416 +
  417 + /**
  418 + * 将数据放入set缓存
  419 + *
  420 + * @param key 键
  421 + * @param values 值 可以是多个
  422 + * @return 成功个数
  423 + */
  424 + public long sSet(String key, Object... values) {
  425 + try {
  426 + return redisTemplate.opsForSet().add(key, values);
  427 + } catch (Exception e) {
  428 + e.printStackTrace();
  429 + return 0;
  430 + }
  431 + }
  432 +
  433 + /**
  434 + * 将set数据放入缓存
  435 + *
  436 + * @param key 键
  437 + * @param time 时间(秒)
  438 + * @param values 值 可以是多个
  439 + * @return 成功个数
  440 + */
  441 + public long sSetAndTime(String key, long time, Object... values) {
  442 + try {
  443 + Long count = redisTemplate.opsForSet().add(key, values);
  444 + if (time > 0) {
  445 + expire(key, time);
  446 + }
  447 + return count;
  448 + } catch (Exception e) {
  449 + e.printStackTrace();
  450 + return 0;
  451 + }
  452 + }
  453 +
  454 + /**
  455 + * 获取set缓存的长度
  456 + *
  457 + * @param key 键
  458 + * @return
  459 + */
  460 + public long sGetSetSize(String key) {
  461 + try {
  462 + return redisTemplate.opsForSet().size(key);
  463 + } catch (Exception e) {
  464 + e.printStackTrace();
  465 + return 0;
  466 + }
  467 + }
  468 +
  469 + /**
  470 + * 移除值为value的
  471 + *
  472 + * @param key 键
  473 + * @param values 值 可以是多个
  474 + * @return 移除的个数
  475 + */
  476 + public long setRemove(String key, Object... values) {
  477 + try {
  478 + Long count = redisTemplate.opsForSet().remove(key, values);
  479 + return count;
  480 + } catch (Exception e) {
  481 + e.printStackTrace();
  482 + return 0;
  483 + }
  484 + }
  485 +
  486 + // ===============================list=================================
  487 +
  488 + /**
  489 + * 获取list缓存的内容
  490 + *
  491 + * @param key 键
  492 + * @param start 开始
  493 + * @param end 结束 0 到 -1代表所有值
  494 + * @return
  495 + */
  496 + public List<Object> lGet(String key, long start, long end) {
  497 + try {
  498 + return redisTemplate.opsForList().range(key, start, end);
  499 + } catch (Exception e) {
  500 + e.printStackTrace();
  501 + return null;
  502 + }
  503 + }
  504 +
  505 + /**
  506 + * 获取list缓存的长度
  507 + *
  508 + * @param key 键
  509 + * @return
  510 + */
  511 + public long lGetListSize(String key) {
  512 + try {
  513 + return redisTemplate.opsForList().size(key);
  514 + } catch (Exception e) {
  515 + e.printStackTrace();
  516 + return 0;
  517 + }
  518 + }
  519 +
  520 + /**
  521 + * 通过索引 获取list中的值
  522 + *
  523 + * @param key 键
  524 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  525 + * @return
  526 + */
  527 + public Object lGetIndex(String key, long index) {
  528 + try {
  529 + return redisTemplate.opsForList().index(key, index);
  530 + } catch (Exception e) {
  531 + e.printStackTrace();
  532 + return null;
  533 + }
  534 + }
  535 +
  536 + /**
  537 + * 将list放入缓存
  538 + *
  539 + * @param key 键
  540 + * @param value 值
  541 + * @return
  542 + */
  543 + public boolean lSet(String key, Object value) {
  544 + try {
  545 + redisTemplate.opsForList().rightPush(key, value);
  546 + return true;
  547 + } catch (Exception e) {
  548 + e.printStackTrace();
  549 + return false;
  550 + }
  551 + }
  552 +
  553 + /**
  554 + * 将list放入缓存
  555 + *
  556 + * @param key 键
  557 + * @param value 值
  558 + * @param time 时间(秒)
  559 + * @return
  560 + */
  561 + public boolean lSet(String key, Object value, long time) {
  562 + try {
  563 + redisTemplate.opsForList().rightPush(key, value);
  564 + if (time > 0) {
  565 + expire(key, time);
  566 + }
  567 + return true;
  568 + } catch (Exception e) {
  569 + e.printStackTrace();
  570 + return false;
  571 + }
  572 + }
  573 +
  574 + /**
  575 + * 将list放入缓存
  576 + *
  577 + * @param key 键
  578 + * @param value 值
  579 + * @return
  580 + */
  581 + public boolean lSet(String key, List<Object> value) {
  582 + try {
  583 + redisTemplate.opsForList().rightPushAll(key, value);
  584 + return true;
  585 + } catch (Exception e) {
  586 + e.printStackTrace();
  587 + return false;
  588 + }
  589 + }
  590 +
  591 + /**
  592 + * 将list放入缓存
  593 + *
  594 + * @param key 键
  595 + * @param value 值
  596 + * @param time 时间(秒)
  597 + * @return
  598 + */
  599 + public boolean lSet(String key, List<Object> value, long time) {
  600 + try {
  601 + redisTemplate.opsForList().rightPushAll(key, value);
  602 + if (time > 0) {
  603 + expire(key, time);
  604 + }
  605 + return true;
  606 + } catch (Exception e) {
  607 + e.printStackTrace();
  608 + return false;
  609 + }
  610 + }
  611 +
  612 + /**
  613 + * 根据索引修改list中的某条数据
  614 + *
  615 + * @param key 键
  616 + * @param index 索引
  617 + * @param value 值
  618 + * @return /
  619 + */
  620 + public boolean lUpdateIndex(String key, long index, Object value) {
  621 + try {
  622 + redisTemplate.opsForList().set(key, index, value);
  623 + return true;
  624 + } catch (Exception e) {
  625 + e.printStackTrace();
  626 + return false;
  627 + }
  628 + }
  629 +
  630 + /**
  631 + * 移除N个值为value
  632 + *
  633 + * @param key 键
  634 + * @param count 移除多少个
  635 + * @param value 值
  636 + * @return 移除的个数
  637 + */
  638 + public long lRemove(String key, long count, Object value) {
  639 + try {
  640 + return redisTemplate.opsForList().remove(key, count, value);
  641 + } catch (Exception e) {
  642 + e.printStackTrace();
  643 + return 0;
  644 + }
  645 + }
  646 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/RequestContextUtil.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/RequestContextUtil.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.springframework.web.context.ContextLoader;
  4 +import org.springframework.web.context.request.RequestContextHolder;
  5 +import org.springframework.web.context.request.ServletRequestAttributes;
  6 +
  7 +import javax.servlet.ServletContext;
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletResponse;
  10 +import javax.servlet.http.HttpSession;
  11 +
  12 +
  13 +public class RequestContextUtil {
  14 +
  15 + public static HttpServletRequest getRequest() {
  16 + return getRequestAttributes().getRequest();
  17 + }
  18 +
  19 + public static HttpServletResponse getResponse() {
  20 + return getRequestAttributes().getResponse();
  21 + }
  22 +
  23 + public static HttpSession getSession() {
  24 + return getRequest().getSession();
  25 + }
  26 +
  27 + public static ServletRequestAttributes getRequestAttributes() {
  28 + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
  29 + }
  30 +
  31 + public static ServletContext getServletContext() {
  32 + return ContextLoader.getCurrentWebApplicationContext().getServletContext();
  33 + }
  34 +
  35 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/RequestStringUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/RequestStringUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import cn.hutool.core.io.resource.ClassPathResource;
  4 +import com.canrd.shop.common.constant.ElAdminConstant;
  5 +import eu.bitwalker.useragentutils.Browser;
  6 +import eu.bitwalker.useragentutils.UserAgent;
  7 +import org.lionsoul.ip2region.DataBlock;
  8 +import org.lionsoul.ip2region.DbConfig;
  9 +import org.lionsoul.ip2region.DbSearcher;
  10 +
  11 +import javax.servlet.http.HttpServletRequest;
  12 +import java.io.File;
  13 +import java.io.IOException;
  14 +import java.lang.reflect.Method;
  15 +import java.net.InetAddress;
  16 +import java.net.UnknownHostException;
  17 +import java.util.Calendar;
  18 +import java.util.Date;
  19 +
  20 +/**
  21 + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
  22 + */
  23 +public class RequestStringUtils extends org.apache.commons.lang3.StringUtils {
  24 +
  25 + private static final char SEPARATOR = '_';
  26 +
  27 + private static final String UNKNOWN = "unknown";
  28 +
  29 + /**
  30 + * 驼峰命名法工具
  31 + *
  32 + * @return toCamelCase(" hello_world ") == "helloWorld"
  33 + * toCapitalizeCamelCase("hello_world") == "HelloWorld"
  34 + * toUnderScoreCase("helloWorld") = "hello_world"
  35 + */
  36 + public static String toCamelCase(String s) {
  37 + if (s == null) {
  38 + return null;
  39 + }
  40 +
  41 + s = s.toLowerCase();
  42 +
  43 + StringBuilder sb = new StringBuilder(s.length());
  44 + boolean upperCase = false;
  45 + for (int i = 0; i < s.length(); i++) {
  46 + char c = s.charAt(i);
  47 +
  48 + if (c == SEPARATOR) {
  49 + upperCase = true;
  50 + } else if (upperCase) {
  51 + sb.append(Character.toUpperCase(c));
  52 + upperCase = false;
  53 + } else {
  54 + sb.append(c);
  55 + }
  56 + }
  57 +
  58 + return sb.toString();
  59 + }
  60 +
  61 + /**
  62 + * 驼峰命名法工具
  63 + *
  64 + * @return toCamelCase(" hello_world ") == "helloWorld"
  65 + * toCapitalizeCamelCase("hello_world") == "HelloWorld"
  66 + * toUnderScoreCase("helloWorld") = "hello_world"
  67 + */
  68 + public static String toCapitalizeCamelCase(String s) {
  69 + if (s == null) {
  70 + return null;
  71 + }
  72 + s = toCamelCase(s);
  73 + return s.substring(0, 1).toUpperCase() + s.substring(1);
  74 + }
  75 +
  76 + /**
  77 + * 驼峰命名法工具
  78 + *
  79 + * @return toCamelCase(" hello_world ") == "helloWorld"
  80 + * toCapitalizeCamelCase("hello_world") == "HelloWorld"
  81 + * toUnderScoreCase("helloWorld") = "hello_world"
  82 + */
  83 + static String toUnderScoreCase(String s) {
  84 + if (s == null) {
  85 + return null;
  86 + }
  87 +
  88 + StringBuilder sb = new StringBuilder();
  89 + boolean upperCase = false;
  90 + for (int i = 0; i < s.length(); i++) {
  91 + char c = s.charAt(i);
  92 +
  93 + boolean nextUpperCase = true;
  94 +
  95 + if (i < (s.length() - 1)) {
  96 + nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
  97 + }
  98 +
  99 + if ((i > 0) && Character.isUpperCase(c)) {
  100 + if (!upperCase || !nextUpperCase) {
  101 + sb.append(SEPARATOR);
  102 + }
  103 + upperCase = true;
  104 + } else {
  105 + upperCase = false;
  106 + }
  107 +
  108 + sb.append(Character.toLowerCase(c));
  109 + }
  110 +
  111 + return sb.toString();
  112 + }
  113 +
  114 + /**
  115 + * 获取ip地址
  116 + */
  117 + public static String getIp(HttpServletRequest request) {
  118 + String ip = request.getHeader("x-forwarded-for");
  119 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
  120 + ip = request.getHeader("Proxy-Client-IP");
  121 + }
  122 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
  123 + ip = request.getHeader("WL-Proxy-Client-IP");
  124 + }
  125 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
  126 + ip = request.getRemoteAddr();
  127 + }
  128 + String comma = ",";
  129 + String localhost = "127.0.0.1";
  130 + if (ip.contains(comma)) {
  131 + ip = ip.split(",")[0];
  132 + }
  133 + if (localhost.equals(ip)) {
  134 + // 获取本机真正的ip地址
  135 + try {
  136 + ip = InetAddress.getLocalHost().getHostAddress();
  137 + } catch (UnknownHostException e) {
  138 + e.printStackTrace();
  139 + }
  140 + }
  141 + return ip;
  142 + }
  143 +
  144 + /**
  145 + * 根据ip获取详细地址
  146 + */
  147 + public static String getCityInfo(String ip) {
  148 + DbSearcher searcher = null;
  149 + try {
  150 + String path = "ip2region/ip2region.db";
  151 + String name = "ip2region.db";
  152 + DbConfig config = new DbConfig();
  153 + File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name);
  154 + searcher = new DbSearcher(config, file.getPath());
  155 + Method method;
  156 + method = searcher.getClass().getMethod("btreeSearch", String.class);
  157 + DataBlock dataBlock;
  158 + dataBlock = (DataBlock) method.invoke(searcher, ip);
  159 + String address = dataBlock.getRegion().replace("0|", "");
  160 + char symbol = '|';
  161 + if (address.charAt(address.length() - 1) == symbol) {
  162 + address = address.substring(0, address.length() - 1);
  163 + }
  164 + return address.equals(ElAdminConstant.REGION) ? "内网IP" : address;
  165 + } catch (Exception e) {
  166 + e.printStackTrace();
  167 + } finally {
  168 + if (searcher != null) {
  169 + try {
  170 + searcher.close();
  171 + } catch (IOException ignored) {
  172 + }
  173 + }
  174 +
  175 + }
  176 + return "";
  177 + }
  178 +
  179 + public static String getBrowser(HttpServletRequest request) {
  180 + UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
  181 + Browser browser = userAgent.getBrowser();
  182 + return browser.getName();
  183 + }
  184 +
  185 + /**
  186 + * 获得当天是周几
  187 + */
  188 + public static String getWeekDay() {
  189 + String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  190 + Calendar cal = Calendar.getInstance();
  191 + cal.setTime(new Date());
  192 +
  193 + int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
  194 + if (w < 0) {
  195 + w = 0;
  196 + }
  197 + return weekDays[w];
  198 + }
  199 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/ServletUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/ServletUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.http.HttpStatus;
  6 +
  7 +import javax.servlet.http.HttpServletResponse;
  8 +import java.io.IOException;
  9 +
  10 +/**
  11 + * @date 2023-02-02
  12 + */
  13 +@Slf4j
  14 +public class ServletUtils {
  15 +
  16 +
  17 + public static void renderServerResult(HttpServletResponse response, ServerResult serverResult, HttpStatus httpStatus)
  18 + {
  19 + try
  20 + {
  21 + response.setStatus(httpStatus.value());
  22 + response.setContentType("application/json");
  23 + response.setCharacterEncoding("utf-8");
  24 + response.getWriter().print(JsonUtil.toJsonString(serverResult));
  25 + }
  26 + catch (IOException e)
  27 + {
  28 + log.error("ServletUtils#renderServerResult:",e);
  29 + }
  30 + }
  31 +
  32 +
  33 + public static void renderExcelFileNotFound(HttpServletResponse response){
  34 + try {
  35 + response.setStatus(404);
  36 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
  37 + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
  38 + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
  39 + response.sendError(HttpStatus.NOT_FOUND.value(),"下载失败,资源不存在");
  40 + }catch (IOException e){
  41 + log.error("ServletUtils#renderWithResourceNotFound:",e);
  42 + }
  43 + }
  44 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/SpringContextHolder.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/SpringContextHolder.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.beans.BeansException;
  5 +import org.springframework.beans.factory.DisposableBean;
  6 +import org.springframework.context.ApplicationContext;
  7 +import org.springframework.context.ApplicationContextAware;
  8 +
  9 +/**
  10 + * @author Jie
  11 + * @date 2019-01-07
  12 + */
  13 +@Slf4j
  14 +public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
  15 +
  16 + private static ApplicationContext applicationContext = null;
  17 +
  18 + /**
  19 + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
  20 + */
  21 + @SuppressWarnings("unchecked")
  22 + public static <T> T getBean(String name) {
  23 + assertContextInjected();
  24 + return (T) applicationContext.getBean(name);
  25 + }
  26 +
  27 + /**
  28 + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
  29 + */
  30 + public static <T> T getBean(Class<T> requiredType) {
  31 + assertContextInjected();
  32 + return applicationContext.getBean(requiredType);
  33 + }
  34 +
  35 + /**
  36 + * 检查ApplicationContext不为空.
  37 + */
  38 + private static void assertContextInjected() {
  39 + if (applicationContext == null) {
  40 + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
  41 + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
  42 + }
  43 + }
  44 +
  45 + /**
  46 + * 清除SpringContextHolder中的ApplicationContext为Null.
  47 + */
  48 + private static void clearHolder() {
  49 + log.debug("清除SpringContextHolder中的ApplicationContext:"
  50 + + applicationContext);
  51 + applicationContext = null;
  52 + }
  53 +
  54 + @Override
  55 + public void destroy() {
  56 + SpringContextHolder.clearHolder();
  57 + }
  58 +
  59 + @Override
  60 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  61 + if (SpringContextHolder.applicationContext != null) {
  62 + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
  63 + }
  64 + SpringContextHolder.applicationContext = applicationContext;
  65 + }
  66 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/StringUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/StringUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.canrd.shop.common.constant.Constant;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.util.CollectionUtils;
  6 +
  7 +import java.io.ByteArrayInputStream;
  8 +import java.io.ByteArrayOutputStream;
  9 +import java.io.IOException;
  10 +import java.math.BigDecimal;
  11 +import java.nio.charset.StandardCharsets;
  12 +import java.util.*;
  13 +import java.util.regex.Matcher;
  14 +import java.util.regex.Pattern;
  15 +import java.util.regex.PatternSyntaxException;
  16 +import java.util.stream.Collectors;
  17 +import java.util.stream.Stream;
  18 +import java.util.zip.GZIPInputStream;
  19 +import java.util.zip.GZIPOutputStream;
  20 +
  21 +/**
  22 + * @param
  23 + * @author 邓彬
  24 + * @version 0.1.0
  25 + * @Description
  26 + * @return
  27 + * @date 2021/4/16 17:44
  28 + * @since 0.1.0
  29 + */
  30 +@Slf4j
  31 +public class StringUtils {
  32 + /**
  33 + * 首字母变小写
  34 + *
  35 + * @param str
  36 + * @return
  37 + */
  38 + public static String firstCharToLowerCase(String str) {
  39 + char firstChar = str.charAt(0);
  40 + if (firstChar >= 'A' && firstChar <= 'Z') {
  41 + char[] arr = str.toCharArray();
  42 + arr[0] += ('a' - 'A');
  43 + return new String(arr);
  44 + }
  45 + return str;
  46 + }
  47 +
  48 + /**
  49 + * 首字母变大写
  50 + *
  51 + * @param str
  52 + * @return
  53 + */
  54 + public static String firstCharToUpperCase(String str) {
  55 + char firstChar = str.charAt(0);
  56 + if (firstChar >= 'a' && firstChar <= 'z') {
  57 + char[] arr = str.toCharArray();
  58 + arr[0] -= ('a' - 'A');
  59 + return new String(arr);
  60 + }
  61 + return str;
  62 + }
  63 +
  64 + /**
  65 + * 判断是否为空
  66 + *
  67 + * @param str
  68 + * @return
  69 + */
  70 + public static boolean isEmpty(final String str) {
  71 + return (str == null) || (str.length() == 0);
  72 + }
  73 +
  74 + /**
  75 + * 判断是否不为空
  76 + *
  77 + * @param str
  78 + * @return
  79 + */
  80 + public static boolean isNotEmpty(final String str) {
  81 + return !isEmpty(str);
  82 + }
  83 +
  84 + /**
  85 + * 判断是否空白
  86 + *
  87 + * @param str
  88 + * @return
  89 + */
  90 + public static boolean isBlank(final String str) {
  91 + int strLen;
  92 + if ((str == null) || ((strLen = str.length()) == 0)) {
  93 + return true;
  94 + }
  95 + for (int i = 0; i < strLen; i++) {
  96 + if (!Character.isWhitespace(str.charAt(i))) {
  97 + return false;
  98 + }
  99 + }
  100 + return true;
  101 + }
  102 +
  103 + /**
  104 + * 判断是否不是空白
  105 + *
  106 + * @param str
  107 + * @return
  108 + */
  109 + public static boolean isNotBlank(final String str) {
  110 + return !isBlank(str);
  111 + }
  112 +
  113 + /**
  114 + * 判断多个字符串全部是否为空
  115 + *
  116 + * @param strings
  117 + * @return
  118 + */
  119 + public static boolean isAllEmpty(String... strings) {
  120 + if (strings == null) {
  121 + return true;
  122 + }
  123 + for (String str : strings) {
  124 + if (isNotEmpty(str)) {
  125 + return false;
  126 + }
  127 + }
  128 + return true;
  129 + }
  130 +
  131 + /**
  132 + * 判断多个字符串其中任意一个是否为空
  133 + *
  134 + * @param strings
  135 + * @return
  136 + */
  137 + public static boolean isHasEmpty(String... strings) {
  138 + if (strings == null) {
  139 + return true;
  140 + }
  141 + for (String str : strings) {
  142 + if (isEmpty(str)) {
  143 + return true;
  144 + }
  145 + }
  146 + return false;
  147 + }
  148 +
  149 + /**
  150 + * 判断多个字符串是否都为blank
  151 + *
  152 + * @param strings
  153 + * @return
  154 + */
  155 + public static boolean isAllBlank(String... strings) {
  156 + if (strings == null) {
  157 + return true;
  158 + }
  159 + for (String str : strings) {
  160 + if (isNotBlank(str)) {
  161 + return false;
  162 + }
  163 + }
  164 + return true;
  165 + }
  166 +
  167 + /**
  168 + * checkValue为 null 或者为 "" 时返回 defaultValue
  169 + *
  170 + * @param checkValue
  171 + * @param defaultValue
  172 + * @return
  173 + */
  174 + public static String isEmpty(String checkValue, String defaultValue) {
  175 + return isEmpty(checkValue) ? defaultValue : checkValue;
  176 + }
  177 +
  178 + /**
  179 + * 字符串不为 null 而且不为 "" 并且等于other
  180 + *
  181 + * @param str
  182 + * @param other
  183 + * @return
  184 + */
  185 + public static boolean isNotEmptyAndEqualsOther(String str, String other) {
  186 + return !isEmpty(str) && str.equals(other);
  187 + }
  188 +
  189 + /**
  190 + * 字符串不为 null 而且不为 "" 并且不等于other
  191 + *
  192 + * @param str
  193 + * @param other
  194 + * @return
  195 + */
  196 + public static boolean isNotEmptyAndNotEqualsOther(String str, String... other) {
  197 + if (isEmpty(str)) {
  198 + return false;
  199 + }
  200 + for (String s : other) {
  201 + if (str.equals(s)) {
  202 + return false;
  203 + }
  204 + }
  205 + return true;
  206 + }
  207 +
  208 + /**
  209 + * 字符串不等于other
  210 + *
  211 + * @param str
  212 + * @param other
  213 + * @return
  214 + */
  215 + public static boolean isNotEqualsOther(String str, String... other) {
  216 + for (String s : other) {
  217 + if (s.equals(str)) {
  218 + return false;
  219 + }
  220 + }
  221 + return true;
  222 + }
  223 +
  224 + /**
  225 + * 判断字符串不为空
  226 + *
  227 + * @param strings
  228 + * @return
  229 + */
  230 + public static boolean isNotEmpty(String... strings) {
  231 + if (strings == null || strings.length == 0) {
  232 + return false;
  233 + }
  234 + for (String str : strings) {
  235 + if (str == null || "".equals(str.trim())) {
  236 + return false;
  237 + }
  238 + }
  239 + return true;
  240 + }
  241 +
  242 + /**
  243 + * 比较字符相等
  244 + *
  245 + * @param value
  246 + * @param equals
  247 + * @return
  248 + */
  249 + public static boolean equals(String value, String equals) {
  250 + if (isAllEmpty(value, equals)) {
  251 + return true;
  252 + }
  253 + //进一步判断value是不是空,如果是空,要直接equals会报NPE异常
  254 + if (value == null) {
  255 + return false;
  256 + }
  257 + return value.equals(equals);
  258 + }
  259 +
  260 + /**
  261 + * @description 将字符串转换为数字数组
  262 + * @author 黄楷涵
  263 + * @date 2020/9/15
  264 + */
  265 + public static int[] stringParseToInt(String str, String regex) {
  266 + return stringParseToInt(str.split(regex));
  267 + }
  268 +
  269 + /**
  270 + * @description 将字符串数组转换为数字数组
  271 + * @author dengbin
  272 + * @date 2020/9/15
  273 + */
  274 + public static int[] stringParseToInt(String[] str) {
  275 + int[] num = new int[str.length];
  276 + for (int i = 0; i < str.length; i++) {
  277 + num[i] = Integer.parseInt(str[i]);
  278 + }
  279 + return num;
  280 + }
  281 +
  282 + /**
  283 + * 比较字符串不相等
  284 + *
  285 + * @param value
  286 + * @param equals
  287 + * @return
  288 + */
  289 + public static boolean isNotEquals(String value, String equals) {
  290 + return !equals(value, equals);
  291 + }
  292 +
  293 + public static String[] split(String content, String separatorChars) {
  294 + return splitWorker(content, separatorChars, -1, false);
  295 + }
  296 +
  297 + public static String[] split(String str, String separatorChars, int max) {
  298 + return splitWorker(str, separatorChars, max, false);
  299 + }
  300 +
  301 + public static final String[] EMPTY_STRING_ARRAY = new String[0];
  302 +
  303 + private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
  304 + if (str == null) {
  305 + return null;
  306 + }
  307 + int len = str.length();
  308 + if (len == 0) {
  309 + return EMPTY_STRING_ARRAY;
  310 + }
  311 + List<String> list = new ArrayList<String>();
  312 + int sizePlus1 = 1;
  313 + int i = 0, start = 0;
  314 + boolean match = false;
  315 + boolean lastMatch = false;
  316 + if (separatorChars == null) {
  317 + while (i < len) {
  318 + if (Character.isWhitespace(str.charAt(i))) {
  319 + if (match || preserveAllTokens) {
  320 + lastMatch = true;
  321 + if (sizePlus1++ == max) {
  322 + i = len;
  323 + lastMatch = false;
  324 + }
  325 + list.add(str.substring(start, i));
  326 + match = false;
  327 + }
  328 + start = ++i;
  329 + continue;
  330 + }
  331 + lastMatch = false;
  332 + match = true;
  333 + i++;
  334 + }
  335 + } else if (separatorChars.length() == 1) {
  336 + char sep = separatorChars.charAt(0);
  337 + while (i < len) {
  338 + if (str.charAt(i) == sep) {
  339 + if (match || preserveAllTokens) {
  340 + lastMatch = true;
  341 + if (sizePlus1++ == max) {
  342 + i = len;
  343 + lastMatch = false;
  344 + }
  345 + list.add(str.substring(start, i));
  346 + match = false;
  347 + }
  348 + start = ++i;
  349 + continue;
  350 + }
  351 + lastMatch = false;
  352 + match = true;
  353 + i++;
  354 + }
  355 + } else {
  356 + while (i < len) {
  357 + if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  358 + if (match || preserveAllTokens) {
  359 + lastMatch = true;
  360 + if (sizePlus1++ == max) {
  361 + i = len;
  362 + lastMatch = false;
  363 + }
  364 + list.add(str.substring(start, i));
  365 + match = false;
  366 + }
  367 + start = ++i;
  368 + continue;
  369 + }
  370 + lastMatch = false;
  371 + match = true;
  372 + i++;
  373 + }
  374 + }
  375 + if (match || (preserveAllTokens && lastMatch)) {
  376 + list.add(str.substring(start, i));
  377 + }
  378 + return list.toArray(EMPTY_STRING_ARRAY);
  379 + }
  380 +
  381 + /**
  382 + * 消除转义字符
  383 + *
  384 + * @param str
  385 + * @return
  386 + */
  387 + public static String escapeXml(String str) {
  388 + if (str == null) {
  389 + return "";
  390 + }
  391 + StringBuilder sb = new StringBuilder();
  392 + for (int i = 0; i < str.length(); ++i) {
  393 + char c = str.charAt(i);
  394 + switch (c) {
  395 + case '\u00FF':
  396 + case '\u0024':
  397 + break;
  398 + case '&':
  399 + sb.append("&amp;");
  400 + break;
  401 + case '<':
  402 + sb.append("&lt;");
  403 + break;
  404 + case '>':
  405 + sb.append("&gt;");
  406 + break;
  407 + case '\"':
  408 + sb.append("&quot;");
  409 + break;
  410 + case '\'':
  411 + sb.append("&apos;");
  412 + break;
  413 + default:
  414 + if (c <= '\u001F') {
  415 + break;
  416 + }
  417 + if (c >= '\uE000' && c <= '\uF8FF') {
  418 + break;
  419 + }
  420 + if (c >= '\uFFF0') {
  421 + break;
  422 + }
  423 + sb.append(c);
  424 + break;
  425 + }
  426 + }
  427 + return sb.toString();
  428 + }
  429 +
  430 + /**
  431 + * 将字符串中特定模式的字符转换成map中对应的值
  432 + *
  433 + * @param s 需要转换的字符串
  434 + * @param map 转换所需的键值对集合
  435 + * @return 转换后的字符串
  436 + */
  437 + public static String replace(String s, Map<String, Object> map) {
  438 + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
  439 + int cursor = 0;
  440 + for (int start, end; (start = s.indexOf("${", cursor)) != -1 && (end = s.indexOf("}", start)) != -1; ) {
  441 + ret.append(s.substring(cursor, start)).append(map.get(s.substring(start + 2, end)));
  442 + cursor = end + 1;
  443 + }
  444 + ret.append(s.substring(cursor, s.length()));
  445 + return ret.toString();
  446 + }
  447 +
  448 + public static String replace(String s, Object... objs) {
  449 + if (objs == null || objs.length == 0) {
  450 + return s;
  451 + }
  452 + if (!s.contains("{}")) {
  453 + return s;
  454 + }
  455 + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
  456 + int cursor = 0;
  457 + int index = 0;
  458 + for (int start; (start = s.indexOf("{}", cursor)) != -1; ) {
  459 + ret.append(s.substring(cursor, start));
  460 + if (index < objs.length) {
  461 + ret.append(objs[index]);
  462 + } else {
  463 + ret.append("{}");
  464 + }
  465 + cursor = start + 2;
  466 + index++;
  467 + }
  468 + ret.append(s.substring(cursor, s.length()));
  469 + return ret.toString();
  470 + }
  471 +
  472 +
  473 + /**
  474 + * 转换为字节数组
  475 + *
  476 + * @param bytes
  477 + * @return
  478 + */
  479 + public static String toString(byte[] bytes) {
  480 + return new String(bytes, StandardCharsets.UTF_8);
  481 + }
  482 +
  483 + /**
  484 + * 转换为字节数组
  485 + *
  486 + * @param str
  487 + * @return
  488 + */
  489 + public static byte[] getBytes(String str) {
  490 + return str != null ? str.getBytes(StandardCharsets.UTF_8) : null;
  491 + }
  492 +
  493 + public static boolean isNumeric(String cs) {
  494 + if (isEmpty(cs)) {
  495 + return false;
  496 + }
  497 + for (int i = 0, sz = cs.length(); i < sz; ++i) {
  498 + if (!Character.isDigit(cs.charAt(i))) {
  499 + return false;
  500 + }
  501 + }
  502 + return true;
  503 +
  504 + }
  505 +
  506 + /**
  507 + * 手机号脱敏
  508 + *
  509 + * @param phoneNumber
  510 + * @return
  511 + */
  512 + public static String desensitizedPhoneNumber(String phoneNumber) {
  513 + if (StringUtils.isNotEmpty(phoneNumber)) {
  514 + phoneNumber = phoneNumber.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
  515 + }
  516 + return phoneNumber;
  517 + }
  518 +
  519 + /**
  520 + * 校验3位小数
  521 + *
  522 + * @param str
  523 + * @return
  524 + */
  525 + public static boolean checkDecimal(String str) {
  526 + return Pattern.compile(Constant.DICMAL_REGEXP).matcher(str).find();
  527 + }
  528 +
  529 + /**
  530 + * 校验11位国内手机号
  531 + * <p>规则: 11位数,首位必须为1,第二位可以是3-9;其他位数不限制
  532 + *
  533 + * @param phone 手机号
  534 + * @return 格式正确则返回false; 反之为true
  535 + * @author A80080
  536 + * @createDate 2020/12/19
  537 + */
  538 + public static boolean checkPhoneNum(String phone) {
  539 + return StringUtils.isEmpty(phone) || !Pattern.compile("^1([3-9])[0-9]{9}$").matcher(phone).find();
  540 + }
  541 +
  542 + /**
  543 + * @param str
  544 + * @return boolean
  545 + * @Description 判断字符串是否含有空格
  546 + * @version 0.1.0
  547 + * @author 邓彬
  548 + * @date 2021/1/13 18:10
  549 + * @since 0.1.0
  550 + */
  551 + public static boolean checkStringContainEmpty(String str) {
  552 + return !StringUtils.isEmpty(str) && str.contains(" ");
  553 + }
  554 +
  555 + /**
  556 + * 字符串切分
  557 + *
  558 + * @param splitStr
  559 + * @param splitFlag
  560 + * @return
  561 + */
  562 + public static List<String> splitTag(String splitStr, String splitFlag) {
  563 + return StringUtils.isBlank(splitStr) || StringUtils.isBlank(splitFlag) ?
  564 + new ArrayList<>() :
  565 + Arrays.stream(splitStr.split(splitFlag)).collect(Collectors.toList());
  566 + }
  567 +
  568 + /**
  569 + * @param name
  570 + * @return true代表全是汉字
  571 + * @Description 校验String是否全是中文
  572 + * @version 0.1.0
  573 + * @author 邓彬
  574 + * @date 2021/1/18 19:54
  575 + * @since 0.1.0
  576 + */
  577 + public static boolean checkNameChina(String name) {
  578 + boolean res = true;
  579 + char[] cTemp = name.toCharArray();
  580 + for (int i = 0; i < name.length(); i++) {
  581 + if (!isChinese(cTemp[i])) {
  582 + res = false;
  583 + break;
  584 + }
  585 + }
  586 + return res;
  587 + }
  588 +
  589 + /**
  590 + * @param c
  591 + * @return true代表是汉字
  592 + * @Description 判定输入的是否是汉字
  593 + * @version 0.1.0
  594 + * @author 邓彬
  595 + * @date 2021/1/18 19:53
  596 + * @since 0.1.0
  597 + */
  598 + public static boolean isChinese(char c) {
  599 + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
  600 + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
  601 + || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
  602 + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
  603 + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
  604 + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
  605 + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
  606 + return true;
  607 + }
  608 + return false;
  609 + }
  610 +
  611 + /**
  612 + * @param c
  613 + * @return true代表符合条件
  614 + * @Description 校验某个字符是否是a-z、A-Z、_、0-9
  615 + * @version 0.1.0
  616 + * @author 邓彬
  617 + * @date 2021/1/18 19:56
  618 + * @since 0.1.0
  619 + */
  620 + public static boolean isWord(char c) {
  621 + return Pattern.compile("[\\w]").matcher("" + c).matches();
  622 + }
  623 +
  624 + /**
  625 + * @param str
  626 + * @return boolean
  627 + * @Description 字符串是否仅包含数字和字母
  628 + * @version 0.1.0
  629 + * @author 邓彬
  630 + * @date 2021/1/18 20:00
  631 + * @since 0.1.0
  632 + */
  633 + public static boolean isLetterDigit(String str) {
  634 + return str.matches("^[a-z0-9A-Z]+$");
  635 + }
  636 +
  637 + /**
  638 + * @param str
  639 + * @return boolean
  640 + * @Description 判断是否是纯数字
  641 + * @version 0.1.0
  642 + * @author 邓彬
  643 + * @date 2021/1/23 16:33
  644 + * @since 0.1.0
  645 + */
  646 + public static boolean isDigit(String str) {
  647 + return str.matches("^[0-9]+$");
  648 + }
  649 +
  650 + /**
  651 + * 是否合法手机号
  652 + *
  653 + * @param phone
  654 + * @return
  655 + */
  656 + public static boolean isMobilePhone(String phone) {
  657 + return Pattern.compile(Constant.PHONE_REGEXP).matcher(phone).matches();
  658 + }
  659 +
  660 + /**
  661 + * 是否脱敏手机号
  662 + *
  663 + * @param phone
  664 + * @return
  665 + */
  666 + public static boolean isDesensitizationMobilePhone(String phone) {
  667 + return Pattern.compile(Constant.PHONE_DESENSITIZATION_REGEXP).matcher(phone).matches();
  668 + }
  669 +
  670 + /**
  671 + * 判断String是否是整数<br>
  672 + * 支持10进制
  673 + *
  674 + * @param s String
  675 + * @return 是否为整数
  676 + */
  677 + public static boolean isInteger(String s) {
  678 + try {
  679 + Integer.parseInt(s);
  680 + } catch (NumberFormatException e) {
  681 + return false;
  682 + }
  683 + return true;
  684 + }
  685 +
  686 + /**
  687 + * 判断对象能否转
  688 + *
  689 + * @param o Object
  690 + * @return 是否为Integer
  691 + */
  692 + public static boolean isInteger(Object o) {
  693 + try {
  694 + Integer.parseInt(String.valueOf(o));
  695 + return true;
  696 + } catch (NumberFormatException e) {
  697 + return false;
  698 + }
  699 + }
  700 +
  701 + public static String escapeCharacter(String str) {
  702 + if (!isEmpty(str)) {
  703 + if (str.contains("\\")) {
  704 + str = str.replaceAll("\\\\", "\\\\\\\\");
  705 + }
  706 + }
  707 + return str;
  708 + }
  709 +
  710 + /**
  711 + * @param str
  712 + * @return boolean
  713 + * @Description 匹配字符串是,数字、26个英文字母、下划线组成的8-16位的字符串组合
  714 + * @version 0.1.0
  715 + * @author A80077-刘始达
  716 + * @date 2021/04/06
  717 + * @since 0.1.0
  718 + */
  719 + public static boolean checkPWD(String str) {
  720 + return str.matches("^(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-_]{8,16}+$");
  721 + }
  722 +
  723 + /**
  724 + * 判断是否包含特殊字符
  725 + *
  726 + * @param str
  727 + * @return
  728 + */
  729 + public static boolean checkSpecificSymbol(String str) {
  730 + String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t";
  731 + Pattern p = Pattern.compile(regEx);
  732 + Matcher m = p.matcher(str);
  733 + return m.find();
  734 + }
  735 +
  736 + /**
  737 + * 拼接图片标签url
  738 + *
  739 + * @param str
  740 + * @param ossDomain
  741 + * @return
  742 + */
  743 + public static String replaceHtmlTag(String str, String ossDomain) {
  744 + if (StringUtils.isEmpty(str)) {
  745 + return "";
  746 + }
  747 + if (StringUtils.isEmpty(ossDomain)) {
  748 + return str;
  749 + }
  750 + return replaceHtmlTag(str, "img", "src", "src=\"" + ossDomain, "\"");
  751 + }
  752 +
  753 + /**
  754 + * html格式处理:替换指定标签的属性和值
  755 + *
  756 + * @param str 需要处理的字符串
  757 + * @param tag 标签名称
  758 + * @param tagAttrib 要替换的标签属性值
  759 + * @param startTag 新标签开始标记
  760 + * @param endTag 新标签结束标记
  761 + * @return
  762 + */
  763 + public static String replaceHtmlTag(String str, String tag, String tagAttrib, String startTag, String endTag) {
  764 + String regxpForTag = "<\\s*" + tag + "\\s+([^>]*)\\s*";
  765 + String regxpForTagAttrib = tagAttrib + "=\\s*\"([^\"]+)\"";
  766 + Pattern patternForTag = Pattern.compile(regxpForTag, Pattern.CASE_INSENSITIVE);
  767 + Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib, Pattern.CASE_INSENSITIVE);
  768 + Matcher matcherForTag = patternForTag.matcher(str);
  769 + StringBuffer sb = new StringBuffer();
  770 + boolean result = matcherForTag.find();
  771 + while (result) {
  772 + StringBuffer stringBuffer = new StringBuffer("<" + tag + " ");
  773 + Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag.group(1));
  774 + if (matcherForAttrib.find()) {
  775 + String attributeStr = matcherForAttrib.group(1);
  776 + if (!attributeStr.contains("https") && !attributeStr.contains("http")) {
  777 + matcherForAttrib.appendReplacement(stringBuffer, startTag + attributeStr + endTag);
  778 + }
  779 + }
  780 + matcherForAttrib.appendTail(stringBuffer);
  781 + matcherForTag.appendReplacement(sb, stringBuffer.toString());
  782 + result = matcherForTag.find();
  783 + }
  784 + matcherForTag.appendTail(sb);
  785 + return sb.toString();
  786 + }
  787 +
  788 + /**
  789 + * @param str
  790 + * @return java.util.Map<String, List < String>>
  791 + * @Description 字符串的连续切割 返回中文词组 数字和字母的集合
  792 + * @version 0.1.0
  793 + * @author 邓彬
  794 + * @date 2021/4/15 13:53
  795 + * @since 0.1.0
  796 + */
  797 + public static Map<String, List<String>> convertStrToChineseList(String str) {
  798 + if (StringUtils.isEmpty(str)) {
  799 + return null;
  800 + }
  801 + Map<String, List<String>> resultMap = new HashMap<>();
  802 + List<String> chineseList;
  803 + List<String> charList;
  804 + char[] list = str.toCharArray();
  805 + StringBuilder chineseStr = new StringBuilder();
  806 + StringBuilder charStr = new StringBuilder();
  807 + for (char c : list) {
  808 + if (StringUtils.isChinese(c)) {
  809 + chineseStr.append(c);
  810 + charStr.append(Constant.SLASH_MARK_CHARACTER);
  811 + } else if (Character.isLetterOrDigit(c)) {
  812 + charStr.append(c);
  813 + chineseStr.append(Constant.SLASH_MARK_CHARACTER);
  814 + } else {
  815 + charStr.append(Constant.SLASH_MARK_CHARACTER);
  816 + chineseStr.append(Constant.SLASH_MARK_CHARACTER);
  817 + }
  818 +
  819 + }
  820 + chineseList = Arrays.stream(chineseStr.toString()
  821 + .split(Constant.SLASH_MARK_CHARACTER))
  822 + .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
  823 + charList = Arrays.stream(charStr.toString()
  824 + .split(Constant.SLASH_MARK_CHARACTER))
  825 + .filter(StringUtils::isNotEmpty).map(String::toLowerCase).collect(Collectors.toList());
  826 +
  827 + resultMap.put("chineseKey", chineseList);
  828 + resultMap.put("charKey", charList);
  829 + return resultMap;
  830 + }
  831 +
  832 + /**
  833 + * 单个字符转换为小写
  834 + *
  835 + * @param c
  836 + * @return
  837 + */
  838 + public static char singleCharToLowerCase(char c) {
  839 + if (c >= 'A' && c <= 'Z') {
  840 + c += ('a' - 'A');
  841 + return c;
  842 + }
  843 + return c;
  844 + }
  845 +
  846 + public static boolean isLong(String shopId) {
  847 + try {
  848 + Long.parseLong(shopId);
  849 + } catch (NumberFormatException e) {
  850 + return false;
  851 + }
  852 + return true;
  853 + }
  854 +
  855 + public static String priceFormatting(String price) {
  856 + if (StringUtils.isEmpty(price)) {
  857 + return Constant.EMPTY_STRING;
  858 + }
  859 +
  860 + String newPrice = "";
  861 + // 价格不存在小数点,则直接返回,无需处理
  862 + if (!price.contains(Constant.POINT_BAR_CHARACTER)) {
  863 + newPrice = price;
  864 + return newPrice;
  865 + }
  866 +
  867 + // 有小数点,则分割字符串
  868 + String[] s = price.split("\\.");
  869 +
  870 + // 小数位数大于0 且小于2 且存在非0字符
  871 + if (s[1].length() > 0 && s[1].length() <= 2 && !judgeIsNumeric(s[1])) {
  872 + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
  873 + newPrice = bigDecimal.toPlainString();
  874 + }
  875 + // 【保留这个else if】小数位数大于0 且大于2 且存在非0字符,理论上不会存在,因为新增商品时已经限定最多输入2个小数点
  876 + else if (s[1].length() > 0 && s[1].length() > 2 && !judgeIsNumeric(s[1])) {
  877 + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
  878 + String[] split = bigDecimal.toPlainString().split("\\.");
  879 + if (split[1].length() > 0 && judgeIsNumeric(split[1])) {
  880 + newPrice = new BigDecimal(bigDecimal.toPlainString()).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
  881 + } else {
  882 + newPrice = bigDecimal.toPlainString();
  883 + }
  884 + } else {
  885 + // 小数位数大于0 且小于2 且小数点都是0
  886 + newPrice = new BigDecimal(price).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
  887 + }
  888 + return newPrice;
  889 + }
  890 +
  891 + /**
  892 + * 判断字符串是否只包含0
  893 + *
  894 + * @param str
  895 + * @return
  896 + */
  897 + private static boolean judgeIsNumeric(String str) {
  898 + return Pattern.compile("[0]*").matcher(str).matches();
  899 + }
  900 +
  901 + /**
  902 + * 字符串以","分隔后转为String[]
  903 + *
  904 + * @param s
  905 + * @return
  906 + */
  907 + public static String[] string2ArraySplitByComma(String s) {
  908 + if (s == null || s.length() == 0) {
  909 + return new String[]{};
  910 + }
  911 + return s.split(Constant.COMMA_CHARACTER);
  912 + }
  913 +
  914 + public static boolean isStringArrayContainsSpecifiedValue(String[] strings, String value) {
  915 + if (null == strings || strings.length <= 0 || value == null || value.length() == 0) {
  916 + return false;
  917 + }
  918 + boolean isContainsSpecifiedValue = false;
  919 + for (String s : strings) {
  920 + if (s.equals(value)) {
  921 + isContainsSpecifiedValue = true;
  922 + break;
  923 + }
  924 + }
  925 + return isContainsSpecifiedValue;
  926 + }
  927 +
  928 + /**
  929 + * 字符串以","分隔后转为list
  930 + *
  931 + * @param s
  932 + * @return
  933 + */
  934 + public static List<String> string2ListSplitByComma(String s) {
  935 + List<String> stringList = new ArrayList<>();
  936 + if (s == null || s.length() == 0) {
  937 + return stringList;
  938 + }
  939 + String[] strArray = string2ArraySplitByComma(s);
  940 +
  941 + for (String st : strArray) {
  942 + if (null != st && st.trim() != null || st.trim().length() != 0) {
  943 + stringList.add(st.trim());
  944 + }
  945 + }
  946 +
  947 + return stringList;
  948 + }
  949 +
  950 + /**
  951 + * 字符串按照特殊符号
  952 + * ".*[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\\\\]+.*"
  953 + * 截取转成字符串集合
  954 + *
  955 + * @param str
  956 + * @return
  957 + */
  958 + public static List<String> splitStringBySpecificSymbol(String str) throws PatternSyntaxException {
  959 + String regEx = "[`~!@#$%^&*()\\-+=|{}':;,\\[\\].<>/?!¥…()—【】‘;:”“’。,、?\\\\]";
  960 + Pattern p = Pattern.compile(regEx);
  961 + Matcher m = p.matcher(str);
  962 + return Stream.of(m.replaceAll("_").split("_")).map(String::trim).filter(StringUtils::isNotBlank).collect(Collectors.toList());
  963 + }
  964 +
  965 + /**
  966 + * 使用gzip压缩字符串
  967 + *
  968 + * @param str 要压缩的字符串
  969 + * @return 压缩后的字符串
  970 + */
  971 + public static String compressByGZip(String str) {
  972 + if (str == null || str.length() == 0) {
  973 + return str;
  974 + }
  975 + ByteArrayOutputStream out = new ByteArrayOutputStream();
  976 + GZIPOutputStream gzip = null;
  977 + try {
  978 + gzip = new GZIPOutputStream(out);
  979 + gzip.write(str.getBytes(StandardCharsets.UTF_8));
  980 + } catch (IOException e) {
  981 + log.error("compressByGZip error: {}", e);
  982 + } finally {
  983 + if (gzip != null) {
  984 + try {
  985 + gzip.close();
  986 + } catch (IOException e) {
  987 + log.error("compressByGZip gzip close error: {}", e);
  988 + }
  989 + }
  990 + }
  991 + // 必须在关闭gzip流之后再读取
  992 + try {
  993 + return new sun.misc.BASE64Encoder().encode(out.toByteArray());
  994 + } catch (Exception e) {
  995 + log.error("compressByGZip BASE64Encoder error:{}", e);
  996 + }
  997 + return str;
  998 + }
  999 +
  1000 + /**
  1001 + * 使用gzip解压缩
  1002 + *
  1003 + * @param compressedStr 已压缩的字符串
  1004 + * @return 解压之后的字符串
  1005 + */
  1006 + public static String uncompressByGZip(String compressedStr) {
  1007 + if (compressedStr == null || compressedStr.length() == 0) {
  1008 + return compressedStr;
  1009 + }
  1010 +
  1011 + String decompressed;
  1012 + try (
  1013 + ByteArrayOutputStream out = new ByteArrayOutputStream();
  1014 + ByteArrayInputStream in = new ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer(compressedStr));
  1015 + GZIPInputStream ginzip = new GZIPInputStream(in);
  1016 + ) {
  1017 + byte[] buffer = new byte[1024];
  1018 + int offset;
  1019 + while ((offset = ginzip.read(buffer)) != -1) {
  1020 + out.write(buffer, 0, offset);
  1021 + }
  1022 + decompressed = out.toString();
  1023 + } catch (IOException e) {
  1024 + log.error("uncompressByGZip error:{}", e);
  1025 + return compressedStr;
  1026 + }
  1027 + return decompressed;
  1028 + }
  1029 +
  1030 + /**
  1031 + * 将list转为字符串,用逗号隔开
  1032 + *
  1033 + * @param list
  1034 + * @return
  1035 + */
  1036 + public static String listTransToStr(List<String> list) {
  1037 + if (CollectionUtils.isEmpty(list)) return null;
  1038 + StringBuilder sb = new StringBuilder();
  1039 + list.forEach(x -> {
  1040 + sb.append(x);
  1041 + sb.append(",");
  1042 + });
  1043 + String str = sb.toString();
  1044 + return str.substring(0, str.length() - 1);
  1045 + }
  1046 +
  1047 + /**
  1048 + * 是否包含中英文
  1049 + *
  1050 + * @param str
  1051 + * @return
  1052 + */
  1053 + public static boolean checkCnAndEn(String str) {
  1054 + String regEx = Constant.CHI_EN_REGEXP;
  1055 + Pattern p = Pattern.compile(regEx);
  1056 + Matcher m = p.matcher(str);
  1057 + return m.find();
  1058 + }
  1059 +
  1060 +
  1061 + /**
  1062 + * @param code 要隐藏显示的字符串
  1063 + * @param head 前面保留的位数
  1064 + * @param tail 后面保留的位数
  1065 + * @return 处理后的字符串
  1066 + */
  1067 + public static String getEncryptCode(String code, int head, int tail) {
  1068 + int body = code.length() - head - tail;
  1069 + String regexVar = "(\\w{%d})(\\w{%d})(\\w{%d})";
  1070 + String regex = String.format(regexVar, head, body, tail);
  1071 + String bodyPart = code.replaceAll(regex, "$2");
  1072 + String bodyEncrypt = bodyPart.replaceAll("\\w", "*");
  1073 + String replacement = String.format("$1%s$3", bodyEncrypt);
  1074 + return code.replaceAll(regex, replacement);
  1075 + }
  1076 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/TemplateFormatUtils.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/TemplateFormatUtils.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import java.util.Map;
  4 +import java.util.regex.Matcher;
  5 +import java.util.regex.Pattern;
  6 +
  7 +/**
  8 + *
  9 + * 消息模板占位符替换工具
  10 + *
  11 + * @author fanzhenyu
  12 + * @date 2022-04-20
  13 + */
  14 +public class TemplateFormatUtils {
  15 +
  16 +
  17 + /**
  18 + * 正则 匹配 { + "多个任意字符" + }
  19 + */
  20 + private static final String DEFAULT_REG = "\\{[\\w]+\\}";
  21 +
  22 + /**
  23 + *
  24 + * @param text 原模板 占位符格式必须为:{fieldName}
  25 + * @param map 模板参数
  26 + * @return
  27 + */
  28 + public static String replaceTemplateContent(String text, Map<String, String> map){
  29 + return replaceTemplateContent(text,map,DEFAULT_REG);
  30 + }
  31 +
  32 + /**
  33 + *
  34 + * @param text 原模板 占位符格式必须为:{fieldName}
  35 + * @param map 模板参数
  36 + * @param reg 自定义占位符样式 - 正则匹配
  37 + * @return
  38 + */
  39 + public static String replaceTemplateContent(String text,Map<String,String> map,String reg){
  40 +
  41 + if(StringUtils.isBlank(reg)){
  42 + reg = DEFAULT_REG;
  43 + }
  44 +
  45 + Pattern pattern = Pattern.compile(reg);
  46 + Matcher m = pattern.matcher(text);
  47 + while(m.find()){
  48 + String currentGroup = m.group();
  49 + String currentPattern = currentGroup.replaceAll("^\\{", "").replaceAll("\\}$", "").trim();
  50 + String mapValue = map.get(currentPattern);
  51 + if (mapValue != null){
  52 + text = text.replace(currentGroup, mapValue);
  53 + }
  54 + }
  55 + return text;
  56 + }
  57 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/ThrowableUtil.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/ThrowableUtil.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +
  4 +import com.canrd.shop.common.exception.BadRequestException;
  5 +
  6 +import javax.validation.ConstraintViolationException;
  7 +import java.io.PrintWriter;
  8 +import java.io.StringWriter;
  9 +
  10 +/**
  11 + * 异常工具 2019-01-06
  12 + */
  13 +public class ThrowableUtil {
  14 +
  15 + /**
  16 + * 获取堆栈信息
  17 + */
  18 + public static String getStackTrace(Throwable throwable) {
  19 + StringWriter sw = new StringWriter();
  20 + try (PrintWriter pw = new PrintWriter(sw)) {
  21 + throwable.printStackTrace(pw);
  22 + return sw.toString();
  23 + }
  24 + }
  25 +
  26 + public static void throwForeignKeyException(Throwable e, String msg) {
  27 + Throwable t = e.getCause();
  28 + while ((t != null) && !(t instanceof ConstraintViolationException)) {
  29 + t = t.getCause();
  30 + }
  31 + if (t != null) {
  32 + throw new BadRequestException(msg);
  33 + }
  34 + assert false;
  35 + throw new BadRequestException("删除失败:" + t.getMessage());
  36 + }
  37 +}
... ...
admin/src/main/java/com/canrd/shop/common/utils/TransactionHelper.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/common/utils/TransactionHelper.java
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.springframework.stereotype.Component;
  4 +import org.springframework.transaction.annotation.Propagation;
  5 +import org.springframework.transaction.annotation.Transactional;
  6 +
  7 +import java.util.function.Supplier;
  8 +
  9 +/**
  10 + * @author:
  11 + * @date: 2021/12/21
  12 + */
  13 +@Component
  14 +public class TransactionHelper {
  15 +
  16 + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  17 + public <T> T run(Supplier<T> command) {
  18 + return command.get();
  19 + }
  20 +
  21 + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  22 + public void run(Runnable command) {
  23 + command.run();
  24 + }
  25 +
  26 +
  27 +}
... ...
admin/src/main/java/com/canrd/shop/config/AdminMetaObjectHandler.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/config/AdminMetaObjectHandler.java
  1 +package com.canrd.shop.config;
  2 +
  3 +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.ibatis.reflection.MetaObject;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +
  11 +@Slf4j
  12 +@Component
  13 +public class AdminMetaObjectHandler implements MetaObjectHandler {
  14 +
  15 +
  16 + private static final String CREATE_TIME = "createTime";
  17 + private static final String MODIFY_TIME = "modifyTime";
  18 + private static final String CREATE_BY = "createBy";
  19 + private static final String MODIFY_BY = "modifyBy";
  20 + private static final String ENABLE_FLAG = "enableFlag";
  21 + private static final String STRING_CLASS_NAME = "java.lang.String";
  22 + private static final String LONG_CLASS_NAME = "java.lang.Long";
  23 +
  24 + @Override
  25 + public void insertFill(MetaObject metaObject) {
  26 + LocalDateTime now = LocalDateTime.now();
  27 + this.strictInsertFill(metaObject, CREATE_TIME, LocalDateTime.class, now);
  28 + this.strictInsertFill(metaObject, MODIFY_TIME, LocalDateTime.class, now);
  29 +// this.strictInsertFill(metaObject, ENABLE_FLAG, Integer.class, Constant.ENABLE_TEN);
  30 +// LoginUserDetail loginUser = UserUtils.getLoginUser();
  31 +// if (null == loginUser) {
  32 +// return;
  33 +// }
  34 +//
  35 +// this.strictInsertFill(metaObject, CREATE_BY, String.class, loginUser.getRealName());
  36 +//
  37 +// this.strictInsertFill(metaObject, MODIFY_BY, String.class, loginUser.getRealName());
  38 +
  39 + }
  40 +
  41 + @Override
  42 + public void updateFill(MetaObject metaObject) {
  43 +
  44 + this.strictInsertFill(metaObject, MODIFY_TIME, LocalDateTime.class, LocalDateTime.now());
  45 +
  46 +// LoginUserDetail loginUser = UserUtils.getLoginUser();
  47 +// if (null == loginUser) {
  48 +// return;
  49 +// }
  50 +// this.strictInsertFill(metaObject, MODIFY_BY, String.class, loginUser.getRealName());
  51 + }
  52 +}
... ...
admin/src/main/java/com/canrd/shop/config/MybatisPlusConfig.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/config/MybatisPlusConfig.java
  1 +package com.canrd.shop.config;
  2 +
  3 +import org.springframework.context.annotation.Configuration;
  4 +
  5 +
  6 +@Configuration
  7 +public class MybatisPlusConfig {
  8 +
  9 +}
... ...
admin/src/main/java/com/canrd/shop/config/RedisConfig.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/config/RedisConfig.java
  1 +package com.canrd.shop.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  5 +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  6 +import org.springframework.data.redis.core.RedisTemplate;
  7 +import org.springframework.data.redis.core.StringRedisTemplate;
  8 +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
  9 +import org.springframework.data.redis.serializer.StringRedisSerializer;
  10 +
  11 +import javax.annotation.Resource;
  12 +
  13 +
  14 +public class RedisConfig {
  15 +
  16 +
  17 + @Resource
  18 + private LettuceConnectionFactory lqlcfactory;
  19 +
  20 + /**
  21 + * @param connectionFactory
  22 + * @return
  23 + */
  24 + @Bean
  25 + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
  26 + RedisTemplate template = new RedisTemplate();
  27 + template.setConnectionFactory(connectionFactory);
  28 + return template;
  29 + }
  30 +
  31 + /**
  32 + * 配置该bean是为了获取logistics 1.0存入redis的数据
  33 + * 序列化方式保持跟logistics 1.0统一
  34 + *
  35 + * @param factory
  36 + * @return
  37 + */
  38 + @Bean(name = "logisticsRedisTemplate")
  39 + public RedisTemplate<String, Object> logisticsRedisTemplate(RedisConnectionFactory factory) {
  40 + RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  41 + redisTemplate.setConnectionFactory(lqlcfactory);
  42 + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
  43 + redisTemplate.setKeySerializer(new StringRedisSerializer());
  44 + return redisTemplate;
  45 + }
  46 +
  47 + @Bean
  48 + public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
  49 + StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
  50 + // lqlcfactory.setShareNativeConnection(true);
  51 + stringRedisTemplate.setConnectionFactory(lqlcfactory);
  52 + return stringRedisTemplate;
  53 +
  54 + }
  55 +}
... ...
admin/src/main/java/com/canrd/shop/config/RestTemplateConfig.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/config/RestTemplateConfig.java
  1 +package com.canrd.shop.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.http.client.ClientHttpRequestFactory;
  6 +import org.springframework.http.client.SimpleClientHttpRequestFactory;
  7 +import org.springframework.web.client.RestTemplate;
  8 +
  9 +
  10 +@Configuration
  11 +public class RestTemplateConfig {
  12 +
  13 + @Bean
  14 + public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
  15 + return new RestTemplate(factory);
  16 + }
  17 +
  18 + @Bean
  19 + public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
  20 + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
  21 + factory.setReadTimeout(3000);
  22 + factory.setConnectTimeout(5000);
  23 + return factory;
  24 + }
  25 +
  26 +}
... ...
admin/src/main/java/com/canrd/shop/config/WebConfig.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/config/WebConfig.java
  1 +package com.canrd.shop.config;
  2 +
  3 +import com.alibaba.fastjson.support.config.FastJsonConfig;
  4 +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.http.MediaType;
  8 +import org.springframework.http.converter.HttpMessageConverter;
  9 +import org.springframework.http.converter.StringHttpMessageConverter;
  10 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  11 +
  12 +import java.nio.charset.StandardCharsets;
  13 +import java.util.ArrayList;
  14 +import java.util.Collections;
  15 +import java.util.List;
  16 +import java.util.stream.Collectors;
  17 +
  18 +
  19 +@Slf4j
  20 +@Configuration
  21 +public class WebConfig implements WebMvcConfigurer {
  22 +
  23 +
  24 + @Override
  25 + public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  26 + FastJsonHttpMessageConverter fastConverter = getFastJsonHttpMessageConverter();
  27 +
  28 + StringHttpMessageConverter stringHttpMessageConverter = getStringHttpMessageConverter();
  29 +
  30 + /**
  31 + * 添加StringHttpMessageConverter ,让其转化String。注意顺序,StringHttpMessageConverter 要在FastJsonHttpMessageConverter 之前。
  32 + *
  33 + * https://www.cnblogs.com/slankka/p/11437034.html
  34 + */
  35 + converters.add(0, fastConverter);
  36 + converters.add(0, stringHttpMessageConverter);
  37 + log.info("HttpMessageConverter顺序\n{}", converters.stream().map(c -> c.getClass().getName()).collect(Collectors.joining("\n")));
  38 + }
  39 +
  40 + private static StringHttpMessageConverter getStringHttpMessageConverter() {
  41 + StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
  42 + stringHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN));
  43 + return stringHttpMessageConverter;
  44 + }
  45 +
  46 + private static FastJsonHttpMessageConverter getFastJsonHttpMessageConverter() {
  47 + FastJsonConfig fastJsonConfig = new FastJsonConfig();
  48 + //解决空值序列化的问题,改为不序列化
  49 + /*fastJsonConfig.setSerializeFilters(new PropertyFilter() {
  50 + @Override
  51 + public boolean apply(Object source,String name, Object value) {
  52 + //if(value.getClass().isPrimitive() == null){
  53 + if(value == null){
  54 + return false;
  55 + }
  56 + return true;
  57 + }
  58 + });*/
  59 + fastJsonConfig.setCharset(StandardCharsets.UTF_8);
  60 + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
  61 + List<MediaType> supportedMediaTypes = new ArrayList<>();
  62 + supportedMediaTypes.add(MediaType.APPLICATION_JSON);
  63 + supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
  64 + supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
  65 +// supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
  66 + supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
  67 + supportedMediaTypes.add(MediaType.APPLICATION_PDF);
  68 + supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
  69 + supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
  70 +// supportedMediaTypes.add(MediaType.APPLICATION_XML);
  71 + supportedMediaTypes.add(MediaType.IMAGE_GIF);
  72 + supportedMediaTypes.add(MediaType.IMAGE_JPEG);
  73 + supportedMediaTypes.add(MediaType.IMAGE_PNG);
  74 + supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
  75 + supportedMediaTypes.add(MediaType.TEXT_HTML);
  76 + supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
  77 + supportedMediaTypes.add(MediaType.TEXT_PLAIN);
  78 +// supportedMediaTypes.add(MediaType.TEXT_XML);
  79 + fastConverter.setSupportedMediaTypes(supportedMediaTypes);
  80 + fastConverter.setFastJsonConfig(fastJsonConfig);
  81 + fastConverter.setDefaultCharset(StandardCharsets.UTF_8);
  82 + return fastConverter;
  83 + }
  84 +}
... ...
admin/src/main/java/com/canrd/shop/controller/TestController.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/controller/TestController.java
  1 +package com.canrd.shop.controller;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.domain.vo.TestQueryVO;
  5 +import com.canrd.shop.domain.vo.TestVO;
  6 +import com.canrd.shop.service.TestService;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.web.bind.annotation.PostMapping;
  9 +import org.springframework.web.bind.annotation.RequestBody;
  10 +import org.springframework.web.bind.annotation.RequestMapping;
  11 +import org.springframework.web.bind.annotation.RestController;
  12 +
  13 +import javax.annotation.Resource;
  14 +
  15 +/**
  16 + * @projectName: canrd-services
  17 + * @package: com.canrd.shop.controller
  18 + * @className: TestController
  19 + * @author: xms
  20 + * @description: TODO
  21 + * @date: 2023/3/29 18:53
  22 + * @version: 1.0
  23 + */
  24 +
  25 +@RestController
  26 +@RequestMapping("/admin/shop/test")
  27 +@Slf4j
  28 +public class TestController {
  29 +
  30 + @Resource
  31 + private TestService testService;
  32 +
  33 + /**
  34 + * @param queryVO
  35 + * @return
  36 + */
  37 + @PostMapping("/demo")
  38 + public ServerResult demo(@RequestBody TestQueryVO queryVO) {
  39 + log.info("查询用户列表:{}", queryVO);
  40 + return ServerResult.success(testService.pageList(queryVO));
  41 + }
  42 +
  43 +
  44 + /**
  45 + * @param testVO
  46 + * @return
  47 + */
  48 + @PostMapping("/add")
  49 + public ServerResult add(@RequestBody TestVO testVO) {
  50 + log.info("新增用户列表:{}", testVO);
  51 + testService.add(testVO);
  52 + return ServerResult.success();
  53 + }
  54 +}
... ...
admin/src/main/java/com/canrd/shop/domain/dto/BaseDO.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/domain/dto/BaseDO.java
  1 +package com.canrd.shop.domain.dto;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableLogic;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +import lombok.experimental.SuperBuilder;
  10 +import org.apache.ibatis.type.LocalDateTimeTypeHandler;
  11 +
  12 +import java.io.Serializable;
  13 +import java.time.LocalDateTime;
  14 +
  15 +
  16 +@Data
  17 +@SuperBuilder(toBuilder = true)
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
  20 +public class BaseDO implements Serializable {
  21 + private static final long serialVersionUID = -2584005549195792084L;
  22 +
  23 + /**
  24 + * 创建时间
  25 + */
  26 + @TableField(fill = FieldFill.INSERT, typeHandler = LocalDateTimeTypeHandler.class)
  27 + private LocalDateTime createTime;
  28 +
  29 + /**
  30 + * 创建人
  31 + */
  32 + @TableField(fill = FieldFill.INSERT)
  33 + private String createBy;
  34 +
  35 + /**
  36 + * 修改时间
  37 + */
  38 + @TableField(fill = FieldFill.INSERT_UPDATE, typeHandler = LocalDateTimeTypeHandler.class)
  39 + private LocalDateTime modifyTime;
  40 +
  41 + /**
  42 + * 修改人
  43 + */
  44 + @TableField(fill = FieldFill.INSERT_UPDATE)
  45 + private String modifyBy;
  46 +
  47 + /**
  48 + * 是否可用 10-可用 20-删除 30-禁用
  49 + */
  50 + @TableLogic
  51 + @TableField(fill = FieldFill.INSERT)
  52 + private Integer enableFlag;
  53 +
  54 + /**
  55 + * 版本号--乐观锁预留字段
  56 + */
  57 + private Integer version;
  58 +}
... ...
admin/src/main/java/com/canrd/shop/domain/dto/CompanyDO.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/domain/dto/CompanyDO.java
  1 +package com.canrd.shop.domain.dto;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.NoArgsConstructor;
  8 +import lombok.experimental.SuperBuilder;
  9 +
  10 +import java.io.Serializable;
  11 +
  12 +/**
  13 + * @author: xms
  14 + * @description: 公司
  15 + * @date: 2023/3/30 15:36
  16 + * @version: 1.0
  17 + */
  18 +
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@SuperBuilder(toBuilder = true)
  22 +@AllArgsConstructor
  23 +@NoArgsConstructor
  24 +@TableName("company")
  25 +public class CompanyDO extends BaseDO implements Serializable {
  26 +
  27 + private Long id;
  28 +
  29 + /**
  30 + * 公司编码
  31 + */
  32 + private String code;
  33 +
  34 + /**
  35 + * 公司名称
  36 + */
  37 + private String name;
  38 +}
... ...
admin/src/main/java/com/canrd/shop/domain/dto/DeptDO.java 0 → 100644
  1 +++ a/admin/src/main/java/com/canrd/shop/domain/dto/DeptDO.java
  1 +package com.canrd.shop.domain.dto;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.fasterxml.jackson.annotation.JsonIgnore;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.NoArgsConstructor;
  10 +import lombok.experimental.SuperBuilder;
  11 +
  12 +import javax.validation.constraints.NotBlank;
  13 +import javax.validation.constraints.NotNull;
  14 +import java.io.Serializable;
  15 +import java.util.Set;
  16 +
  17 +/**
  18 + * @author: xms
  19 + * @description: 部门
  20 + * @date: 2023/3/30 15:41
  21 + * @version: 1.0
  22 + */
  23 +
  24 +@Data
  25 +@EqualsAndHashCode(callSuper = true)
  26 +@SuperBuilder(toBuilder = true)
  27 +@AllArgsConstructor
  28 +@NoArgsConstructor
  29 +@TableName("dept")
  30 +public class DeptDO extends BaseDO implements Serializable {
  31 +
  32 + /**
  33 + * 自增id
  34 + */
  35 + private Long id;
  36 +
  37 + @NotBlank
  38 + private String name;
  39 +
  40 + @NotNull
  41 + private Long pid;
  42 +
  43 + @JsonIgnore
  44 + @TableField(exist = false)
  45 + private Set<RoleDO> roles;
  46 +}
... ...