17358629955 преди 2 години
родител
ревизия
7a5f949e34
променени са 100 файла, в които са добавени 7812 реда и са изтрити 2 реда
  1. 3 0
      .idea/.gitignore
  2. 97 2
      README.md
  3. BIN
      framework.png
  4. 147 0
      pom.xml
  5. 63 0
      sckw-auth/pom.xml
  6. 27 0
      sckw-auth/src/main/java/com/sckw/auth/AuthApplication.java
  7. 32 0
      sckw-auth/src/main/java/com/sckw/auth/controller/IndexController.java
  8. 5 0
      sckw-auth/src/main/resources/banner.txt
  9. 36 0
      sckw-auth/src/main/resources/bootstrap-dev.yml
  10. 14 0
      sckw-auth/src/main/resources/bootstrap.yml
  11. 154 0
      sckw-auth/src/main/resources/log4j2.xml
  12. 34 0
      sckw-common/pom.xml
  13. 92 0
      sckw-common/sckw-common-core/pom.xml
  14. 18 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/annotation/SckwCloudApplication.java
  15. 23 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/annotation/Sensitive.java
  16. 131 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/aspect/DaoAspect.java
  17. 69 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/AbstractLoginUser.java
  18. 47 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginBase.java
  19. 52 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginEnterpriseInfo.java
  20. 74 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginUserInfo.java
  21. 27 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/AbstractLoginContext.java
  22. 95 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/LoginEnterpriseHolder.java
  23. 140 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/LoginUserHolder.java
  24. 38 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/SignBase.java
  25. 69 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/base/BaseModel.java
  26. 40 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/constant/AopSortConstants.java
  27. 217 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/constant/Global.java
  28. 47 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/SensitiveStrategy.java
  29. 76 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageHelperUtil.java
  30. 30 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageRequest.java
  31. 125 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageResult.java
  32. 17 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/service/SensitiveService.java
  33. 219 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/BeanUtils.java
  34. 314 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/CollectionUtils.java
  35. 147 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/Digests.java
  36. 153 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/Encodes.java
  37. 123 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/EncryptionUtil.java
  38. 113 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/IdWorker.java
  39. 57 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/LocUtils.java
  40. 114 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/PasswordUtils.java
  41. 170 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/ReflectionUtils.java
  42. 52 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/SensitiveJsonSerializer.java
  43. 70 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/SpringUtils.java
  44. 701 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/StringUtils.java
  45. 171 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/workerUtils.java
  46. 83 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/constant/HttpStatus.java
  47. 17 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/constant/RequestConstant.java
  48. 95 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/LoginEntHolder.java
  49. 140 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/LoginUserHolder.java
  50. 37 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/SignBase.java
  51. 47 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginBase.java
  52. 52 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginEntInfo.java
  53. 74 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginUserInfo.java
  54. 63 0
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/response/HttpResult.java
  55. 58 0
      sckw-common/sckw-common-datasource/pom.xml
  56. 28 0
      sckw-common/sckw-common-elasticsearch/pom.xml
  57. 80 0
      sckw-common/sckw-common-excel/pom.xml
  58. 24 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/ExcelContext.java
  59. 30 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/ExcelSelected.java
  60. 39 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/Translate.java
  61. 21 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/Translates.java
  62. 82 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/common/FileType.java
  63. 66 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/common/NumberConstant.java
  64. 31 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/CustomCellWriteHandler.java
  65. 46 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelImportListener.java
  66. 64 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelListener.java
  67. 46 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelSelectedResolve.java
  68. 30 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/LocalDateTimeConverter.java
  69. 21 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/RequestHolder.java
  70. 36 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/RowWriteHandlerImpl.java
  71. 60 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/SelectedSheetWriteHandler.java
  72. 24 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/SheetExcelData.java
  73. 404 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/DateUtil.java
  74. 151 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/EasyExcelUtil.java
  75. 201 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/ExcelUtil.java
  76. 42 0
      sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/ValidDataUtil.java
  77. BIN
      sckw-common/sckw-common-excel/src/main/resources/excel/商品主档信息导入模板.xlsx
  78. 154 0
      sckw-common/sckw-common-excel/src/main/resources/log4j2.xml
  79. 47 0
      sckw-common/sckw-common-redis/pom.xml
  80. 92 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/RedisLockUtil.java
  81. 80 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/RedissonConfig.java
  82. 49 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/serializer/FastJson2JsonRedisSerializer.java
  83. 50 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/configure/RedissonConfiguration.java
  84. 64 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/utils/RedissonUtils.java
  85. 37 0
      sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/utils/TestService.java
  86. 4 0
      sckw-common/sckw-common-redis/src/main/resources/META-INF/spring.factories
  87. 1 0
      sckw-common/sckw-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  88. 54 0
      sckw-common/sckw-common-remote/pom.xml
  89. 19 0
      sckw-common/sckw-common-remote/src/main/java/com/sckw/remote/annotation/SckwCloudApplication.java
  90. 51 0
      sckw-common/sckw-common-stream/pom.xml
  91. 9 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/constant/Destination.java
  92. 125 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/enums/MessageEnum.java
  93. 49 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/enums/SmsCodeEnum.java
  94. 30 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/Person.java
  95. 61 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/SckwMessage.java
  96. 44 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/SckwSms.java
  97. 76 0
      sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/utils/SmsUtil.java
  98. 57 0
      sckw-gateway/pom.xml
  99. 19 0
      sckw-gateway/src/main/java/com/sckw/gateway/GatewayApplication.java
  100. 5 0
      sckw-gateway/src/main/resources/banner.txt

+ 3 - 0
.idea/.gitignore

@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml

+ 97 - 2
README.md

@@ -1,3 +1,98 @@
-# sckw-service-platform
+## 平台简介
 
-开物供应链服务平台
+开物供应链服务平台。
+
+* 采用前后端分离的模式,微服务版本。
+* 后端采用Spring Boot、Spring Cloud & Alibaba。
+* 注册中心、配置中心选型Nacos,权限认证使用Redis。
+* 流量控制框架选型Sentinel,分布式事务选型Seata。
+* 服务之间调用支持openfeign和dubbo。
+* 服务调用链路使用ZipKin,分布式任务调度quartz。
+* 多语言微服务异构使用sidecar,消息驱动服务使用stream。
+* 
+
+## 架构图
+
+![framework.png](framework.png)
+
+## 技术栈
+
+| 功能          | 本框架                                                                                                     |
+|-------------|---------------------------------------------------------------------------------------------------------|
+| 前端项目        | 基于vue3 + Element UI                                                                                     
+| 后端项目结构      | 采用插件化 + 扩展包形式 结构解耦 易于扩展                                                                                 |
+| *后端代码风格     | 严格遵守Alibaba规范与项目统一配置的代码格式化                                                                              |
+| *分布式注册/配置中心 | 采用 Alibaba Nacos 源码集成便于调试扩展与二次开发 框架还为其增加了各种监控                                                           |
+| *服务网关       | 采用 SpringCloud Gateway 框架扩展了多种功能例如:内网鉴权、请求体缓存、跨域配置、请求响应日志等                                              |
+| *负载均衡       | 采用 SpringCloud Loadbalancer 扩展支持了开发团队路由 便于多团队开发调试                                                       |
+| *RPC远程调用    | 采用 全新 Apache Dubbo 3.X + OpenFeign                                                                      |
+| 分布式限流熔断     | 采用 Alibaba Sentinel 源码集成便于调试扩展与二次开发 框架还为其增加了各种监控                                                        |
+| 分布式事务       | 采用 Alibaba Seata 源码集成对接了Nacos与各种监控 简化了搭建部署流程                                                            |                                                                        |
+| 权限认证        | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展                                                                        |
+| 权限注解        | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验角色与权限校验支持多种条件 如 `AND` `OR` 或 `权限 OR 角色` 等复杂表达式   |
+| *关系数据库      | 使用 MySQL                                                                                                |                                    
+| *缓存数据库      | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列                                                                   |                                      
+| *Redis客户端   | 采用 Redisson Redis官方推荐 基于Netty的客户端工具支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan支持单机、哨兵、单主集群、多主集群等模式 |                       |
+| *ORM框架      | 采用 Mybatis-Plus 基于对象几乎不用写SQL全java操作 功能强大插件众多例如多租户插件 分页插件 乐观锁插件等等                                        |
+| *数据分页       | 采用 Mybatis-Plus 分页插件框架对其进行了扩展 对象化分页对象 支持多种方式传参 支持前端多排序 复杂排序                                             |
+| 数据权限        | 采用 Mybatis-Plus 插件 自行分析拼接SQL 无感式过滤只需为Mapper设置好注解条件 支持多种自定义 不限于部门角色                                      |
+| *数据脱敏       | 采用 注解 + jackson 序列化期间脱敏 支持不同模块不同的脱敏条件支持多种策略 如身份证、手机号、地址、邮箱、银行卡等 可自行扩展                                   |
+| 数据加解密       | 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密支持多种策略 如BASE64、AES、RSA、SM2、SM4等                                         |         |
+| *多数据源框架     | 采用 dynamic-datasource 支持世面大部分数据库通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源支持spel表达式从请求头参数等条件切换数据源            |
+| *多数据源事务     | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚                                                                |
+| 数据库连接池      | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下/Druid                                                        |
+| *数据库主键      | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁                                                        |
+| 服务端与前端消息通信  | 援用现有mqtt                                                                                                |
+| *序列化         | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                          |
+| 分布式任务调度     | 采用 Xxl-Job 天生支持分布式 统一的管理中心                                                                              |
+| 分布式日志中心     | 采用 ELK 业界成熟解决方案 实时收集所有服务的运行日志 快速发现定位问题                                                                  |
+| 分布式搜索引擎     | 采用 ElasticSearch以 Mybatis-Plus 方式操作 ElasticSearch                                                       |
+| *分布式消息队列    | 采用 SpringCloud-Stream + RabbitMQ                                                                        |
+| 文件存储        | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储支持权限管理 安全可靠 文件可加密存储                                                |
+| *短信         | 使用 spring-cloud-alicloud-sms                                                                            |
+| 短链接         | 购买现成产品                                                                                                  |
+| 接口文档        | 援用现有接口文档系统                                                                                              |
+| 校验框架        | 采用 Validation 支持注解与工具类校验 注解支持国际化                                                                        |
+| *Excel框架     | 采用 Alibaba EasyExcel 基于插件化框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等                                          |
+| *工具类框架       | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码                                             |
+| 服务监控框架      | 采用 SpringBoot-Admin 基于SpringBoot官方 actuator 探针机制实时监控服务状态 框架还为其扩展了在线日志查看监控                               |
+| 全方位监控报警     | 采用 Prometheus、Grafana 多样化采集 多模板大屏展示 实时报警监控 提供详细的搭建文档                                                    |
+| 链路追踪        | 采用 Apache SkyWalking 还在为请求不知道去哪了 到哪出了问题而烦恼吗用了它即可实时查看请求经过的每一处每一个节点                                       |
+| 部署方式        | 支持 Docker 编排 一键搭建所有环境 让开发人员从此不再为搭建环境而烦恼                                                                 |
+| 国际化         | 基于请求头动态返回不同语种的文本内容 开发难度低 有对应的工具类 支持大部分注解内容国际化                                                           |
+
+## 系统模块
+
+~~~
+sckw-service-platform     
+├── sckw-gateway         				// 网关服务 [10010]
+├── sckw-auth            				// 登录认证中心 [10020]
+├── sckw-modules                                // 业务模块
+│       └── sckw-system                         // 系统基础服务模块 [10030]
+│       └── sckw-message                        // 消息服务 [10040]
+│       └── sckw-file                           // 文件服务 [10050]
+│       └── sckw-manage                         // 企业管理服务 [10060]
+│       └── sckw-product                        // 产品服务 [10070]
+│       └── sckw-fleet                          // 车队服务 [10080]
+│       └── sckw-order                          // 订单服务 [10090]
+│       └── sckw-transport                      // 运输服务 [10100]
+│       └── sckw-contract                       // 合同服务 [10110]
+│       └── sckw-payment                        // 支付服务 [10120]
+│       └── sckw-operation                      // 运营服务 [10130]
+│       └── sckw-report                         // 报表服务 [10140]
+│       └── sckw-task                           // 定时任务服务 [10150]
+│       └── sckw-xxx                            // xxxx服务 [10040]
+├── sckw-modules-api                    // 接口模块
+│       └── sckw-system-api                     // 系统基础服务接口
+├── sckw-ops          				    // 运维中心
+├── sckw-common          				// 通用模块
+│       └── sckw-common-core                    // 核心模块
+│       └── sckw-common-datascope               // 权限范围
+│       └── sckw-common-datasource              // 多数据源
+│       └── sckw-common-log                     // 日志记录
+│       └── sckw-common-redis                   // 缓存服务
+│       └── sckw-common-message                 // 消息推送服务
+│       └── sckw-common-resource                // 资源包
+│       └── sckw-common-sidecar                 // 多语言微服务异构
+│       └── sckw-common-stream                  // 消息驱动服务
+~~~

BIN
framework.png


+ 147 - 0
pom.xml

@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>sckw-service-platform</artifactId>
+    <groupId>com.sckw</groupId>
+    <version>1.0.0</version>
+
+    <description>微服务</description>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>sckw-auth</module>
+        <module>sckw-common</module>
+        <module>sckw-gateway</module>
+        <module>sckw-modules</module>
+        <module>sckw-modules-api</module>
+    </modules>
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <spring-boot.version>3.0.5</spring-boot.version>
+        <spring-cloud.version>2022.0.0</spring-cloud.version>
+        <spring-cloud-alibaba.version>2022.0.0.0-RC1</spring-cloud-alibaba.version>
+        <!--不能使用3.2.0版本,会导致redisson里面的kryo版本降低值4.2.0-->
+        <dubbo.version>3.2.2</dubbo.version>
+        <nacos-client.version>2.2.1</nacos-client.version>
+        <snakeyaml.version>2.0</snakeyaml.version>
+        <slf4j-log4j12.version>2.0.7</slf4j-log4j12.version>
+        <springdoc.version>2.1.0</springdoc.version>
+        <redisson.version>3.21.3</redisson.version>
+        <fastjson.version>2.0.32</fastjson.version>
+        <hutool.version>5.8.18</hutool.version>
+        <pagehelper.version>5.3.2</pagehelper.version>
+
+    </properties>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- spring-cloud -->
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>${spring-cloud.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- spring-cloud-alibaba -->
+            <dependency>
+                <groupId>com.alibaba.cloud</groupId>
+                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
+                <version>${spring-cloud-alibaba.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+                <exclusions>
+                    <exclusion>
+                        <groupId>com.alibaba.nacos</groupId>
+                        <artifactId>nacos-client</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <!-- apache dubbo -->
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-bom</artifactId>
+                <version>${dubbo.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <!--redisson-->
+            <dependency>
+                <groupId>org.redisson</groupId>
+                <artifactId>redisson-spring-boot-starter</artifactId>
+                <version>${redisson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!--hutool-->
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-bom</artifactId>
+                <version>${hutool.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper</artifactId>
+                <version>${pagehelper.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-loadbalancer</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+<!--                <version>3.5.2</version>-->
+                <configuration>
+                    <source>17</source>
+                    <target>17</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 63 - 0
sckw-auth/pom.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-service-platform</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-auth</artifactId>
+    <version>1.0.0</version>
+    <description>登录认证中心</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-remote</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-system-api</artifactId>
+            <version>1.0.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <!--web-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!--注册中心客户端-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!--配置中心客户端-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 27 - 0
sckw-auth/src/main/java/com/sckw/auth/AuthApplication.java

@@ -0,0 +1,27 @@
+package com.sckw.auth;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @Author xucaiqin
+ * @date 2023-06-01 15:02:02
+ */
+@EnableDubbo
+@EnableFeignClients({"com.sckw.*.api.feign"})
+@EnableDiscoveryClient
+@SpringBootApplication
+public class AuthApplication {
+    public static void main(String[] args) {
+        // 关闭nacos日志
+        System.setProperty("nacos.logging.default.config.enabled", "false");
+        try {
+            SpringApplication.run(AuthApplication.class, args);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 32 - 0
sckw-auth/src/main/java/com/sckw/auth/controller/IndexController.java

@@ -0,0 +1,32 @@
+package com.sckw.auth.controller;
+
+import com.sckw.system.api.RemoteUserService;
+import com.sckw.system.api.feign.RemoteUserFService;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+//@Slf4j
+@RestController
+@RequestMapping("/")
+public class IndexController {
+    @Autowired
+    private RemoteUserFService remoteUserFService;
+
+    @DubboReference(version = "2.0.0", group = "design", check = false)
+    private RemoteUserService remoteUserService;
+
+    @GetMapping("index")
+    public String index() {
+        //auth 服务 调用 system服务提供的feign接口
+        return remoteUserFService.getUserInfo("312");
+    }
+
+    @GetMapping("getUserInfo")
+    public String getUserInfo(String account) {
+        //auth 服务 调用example实现的dubbo接口
+        return remoteUserService.getUserInfoV1(account);
+    }
+}

+ 5 - 0
sckw-auth/src/main/resources/banner.txt

@@ -0,0 +1,5 @@
+====================================================================================================================
+
+                    欢迎使用 [sckw-auth] 开物供应链服务平台-登陆授权服务 - Powered By https://www.xxxx.com
+
+====================================================================================================================

+ 36 - 0
sckw-auth/src/main/resources/bootstrap-dev.yml

@@ -0,0 +1,36 @@
+spring:
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: 127.0.0.1:8848
+        # 命名空间
+        namespace: sckw-service-platform-dev
+        # 共享配置
+        group: sckw-service-platform
+      config:
+        # 配置中心地址
+        server-addr: 127.0.0.1:8848
+        # 配置文件格式
+        file-extension: yaml
+        # 命名空间
+        namespace: sckw-service-platform-dev
+        # 共享配置
+        group: sckw-service-platform
+
+dubbo:
+  application:
+    name: auth-dubbo-server
+    # 该配置在producer-server中是没有的,但是在consumer这里要配置一下
+    # 如果不配置这个QOS的端口,它会延用dubbo自动生成的端口,在启动的时候,QOS注册就会提示该端口已经被使用的错误
+    # 虽然启动时有打印端口已经被使用的错误,但是依旧可以正常启动服务,并且dubbo也可以正常调用,但是为了解决启动报错还是加上这个端口
+    # 这个也是apache官方给出的解决方案,这个端口不能给-1,它不会自动找到一个可用的端口,给-1会报错,端口1-65535自己选择一个
+    qos-port: 3334
+  protocol:
+    name: dubbo
+    # port为-1表示自动找一个可用的端口
+    port: -1
+  registry:
+    address: nacos://${spring.cloud.nacos.discovery.server-addr}
+    group: ${spring.cloud.nacos.config.group}
+    protocol: nacos

+ 14 - 0
sckw-auth/src/main/resources/bootstrap.yml

@@ -0,0 +1,14 @@
+server:
+  port: 10020
+
+spring:
+  application:
+    name: sckw-auth
+  profiles:
+    active: ${DEPLOY_MODE:dev}
+  main:
+    allow-bean-definition-overriding: true
+
+logging:
+  level:
+    root: info

+ 154 - 0
sckw-auth/src/main/resources/log4j2.xml

@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="info" monitorInterval="30">
+    <properties>
+        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符 -->
+        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
+        <property name="LOG_PATTERN"
+                  value="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%t]}{faint} %clr{%c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx"/>
+        <property name="LOG_WITHOUT_COLOR_PATTERN"
+                  value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${sys:PID}--- [%t] %c{1.} : %m%n%xwEx"/>
+        <property name="LOG_PATH" value="logs/sckw-auth"/>
+    </properties>
+    <!--DEBUG<INFO<WARNING<ERROR<CRITICAL-->
+    <!-- 先定义所有的appender(附加器)-->
+    <appenders>
+        <!-- 输出控制台的配置 -->
+        <Console name="Console" target="SYSTEM_OUT">
+            <!-- 输出日志的格式 -->
+            <PatternLayout pattern="${LOG_PATTERN}"/>
+        </Console>
+
+        <!--all级别日志-->
+        <RollingFile name="allFileAppender"
+                     fileName="${LOG_PATH}/all.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log.gz">
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--debug级别日志-->
+        <RollingFile name="debugFileAppender"
+                     fileName="${LOG_PATH}/debug.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉info及更高级别日志-->
+                <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--info级别日志-->
+        <RollingFile name="infoFileAppender"
+                     fileName="${LOG_PATH}/info.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉warn及更高级别日志-->
+                <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <!--<DefaultRolloverStrategy max="100"/>-->
+        </RollingFile>
+
+        <!--warn级别日志-->
+        <RollingFile name="warnFileAppender"
+                     fileName="${LOG_PATH}/warn.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉error及更高级别日志-->
+                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--error及更高级别日志-->
+        <RollingFile name="errorFileAppender"
+                     fileName="${LOG_PATH}/error.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--json格式error级别日志-->
+        <RollingFile name="errorJsonAppender"
+                     fileName="${LOG_PATH}/error-json.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/error-json-%d{yyyy-MM-dd}-%i.log.gz">
+            <JSONLayout compact="true" eventEol="true" locationInfo="true"/>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
+            </Policies>
+        </RollingFile>
+
+    </appenders>
+
+    <loggers>
+        <root level="debug">
+            <AppenderRef ref="allFileAppender" level="all"/>
+            <AppenderRef ref="debugFileAppender" level="debug"/>
+            <AppenderRef ref="infoFileAppender" level="info"/>
+            <AppenderRef ref="warnFileAppender" level="warn"/>
+            <AppenderRef ref="errorFileAppender" level="error"/>
+            <AppenderRef ref="errorJsonAppender" level="error"/>
+            <appender-ref ref="Console" level="info"/>
+        </root>
+        <Logger name="org.springframework" level="info"/>
+        <Logger name="com.alibaba" level="info"/>
+        <Logger name="com.baomidou" level="info"/>
+    </loggers>
+
+</configuration>

+ 34 - 0
sckw-common/pom.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-service-platform</artifactId>
+        <version>1.0.0</version>
+    </parent>
+    <packaging>pom</packaging>
+
+    <artifactId>sckw-common</artifactId>
+    <version>1.0.0</version>
+    <description>通用模块</description>
+    <modules>
+        <module>sckw-common-core</module>
+        <module>sckw-common-datasource</module>
+        <module>sckw-common-redis</module>
+        <module>sckw-common-stream</module>
+        <module>sckw-common-elasticsearch</module>
+        <module>sckw-common-excel</module>
+        <module>sckw-common-remote</module>
+    </modules>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+
+</project>

+ 92 - 0
sckw-common/sckw-common-core/pom.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-core</artifactId>
+    <version>1.0.0</version>
+    <description>核心模块</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-commons</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!--log4j2日志-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-http</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-extra</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-remote</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 18 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/annotation/SckwCloudApplication.java

@@ -0,0 +1,18 @@
+package com.sckw.core.annotation;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+//@EnableDubbo
+//@EnableFeignClients({"com.sckw.*.api.feign"})
+@EnableDiscoveryClient
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+public @interface SckwCloudApplication {
+}

+ 23 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/annotation/Sensitive.java

@@ -0,0 +1,23 @@
+package com.sckw.core.annotation;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.sckw.core.model.enums.SensitiveStrategy;
+import com.sckw.core.utils.SensitiveJsonSerializer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 数据脱敏注解
+ * @author zk
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = SensitiveJsonSerializer.class)
+public @interface Sensitive {
+    SensitiveStrategy strategy();
+}

+ 131 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/aspect/DaoAspect.java

@@ -0,0 +1,131 @@
+package com.sckw.core.aspect;
+
+import com.sckw.core.model.auth.context.LoginUserHolder;
+import com.sckw.core.model.constant.Global;
+import com.sckw.core.utils.BeanUtils;
+import com.sckw.core.utils.IdWorker;
+import com.sckw.core.utils.StringUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import java.util.Date;
+
+/**
+ * DAO切面,插入创建人,创建时间,修改人,修改时间
+ * @author zk
+ * @date Oct 29, 2018
+ */
+@Aspect
+@Component
+@Configuration
+public class DaoAspect {
+    private static final String ID = "id";
+    private static final String STATUS = "status";
+    private static final String CREATE_BY = "createBy";
+    private static final String CREATE_BY_NAME = "createByName";
+    private static final String CREATE_TIME = "createTime";
+    private static final String UPDATE_BY = "updateBy";
+    private static final String UPDATE_BY_NAME = "updateByName";
+    private static final String UPDATE_TIME = "updateTime";
+    private static final String DEL_FLAG = "delFlag";
+
+    @Pointcut("execution(* com.sckw.*.dao.*.update*(..))")
+    public void daoUpdate() {
+    }
+
+    @Pointcut("execution(* com.sckw.*.dao.*.insert*(..))")
+    public void daoCreate() {
+    }
+
+    @Around("daoUpdate()")
+    public Object doAroundUpdate(ProceedingJoinPoint point) throws Throwable {
+        /*ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (attributes == null) {
+            return point.proceed();
+        }
+        HttpServletRequest request = attributes.getRequest();*/
+        Object[] objects = point.getArgs();
+        if (objects != null && objects.length > 0) {
+            for (Object arg : objects) {
+                Long userId = LoginUserHolder.getUserId();
+                String userName = LoginUserHolder.getUserName();
+                if (isProperty(arg, UPDATE_BY) && BeanUtils.getProperty(arg, UPDATE_BY) == null && userId != null) {
+                    BeanUtils.setProperty(arg, UPDATE_BY, userId);
+                }
+                if (isProperty(arg, UPDATE_BY_NAME) && StringUtils.isBlank(BeanUtils.getProperty(arg, UPDATE_BY_NAME)) && userName != null) {
+                    BeanUtils.setProperty(arg, UPDATE_BY_NAME, userName);
+                }
+                if (isProperty(arg, UPDATE_TIME) && BeanUtils.getProperty(arg, UPDATE_TIME) != null) {
+                    BeanUtils.setProperty(arg, UPDATE_TIME, new Date());
+                }
+            }
+        }
+        Object object = point.proceed();
+        return object;
+    }
+
+    @Around("daoCreate()")
+    public Object doAroundCreate(ProceedingJoinPoint point) throws Throwable {
+        /*ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (attributes == null) {
+            return point.proceed();
+        }
+        HttpServletRequest request = attributes.getRequest();*/
+        Object[] objects = point.getArgs();
+        if (objects != null && objects.length > 0) {
+            for (Object arg : objects) {
+                Long userId = LoginUserHolder.getUserId();
+                String userName = LoginUserHolder.getUserName();
+                Date date = new Date();
+                if (userId != null) {
+                    if (isProperty(arg, CREATE_BY) && BeanUtils.getProperty(arg, CREATE_BY) == null) {
+                        BeanUtils.setProperty(arg, CREATE_BY, userId);
+                    }
+                    if (isProperty(arg, UPDATE_BY) && BeanUtils.getProperty(arg, UPDATE_BY) == null) {
+                        BeanUtils.setProperty(arg, UPDATE_BY, userId);
+                    }
+                }
+
+                if (userName != null){
+                    if (isProperty(arg, CREATE_BY_NAME) && StringUtils.isBlank(BeanUtils.getProperty(arg, CREATE_BY_NAME))) {
+                        BeanUtils.setProperty(arg, CREATE_BY_NAME, userName);
+                    }
+                    if (isProperty(arg, UPDATE_BY_NAME) && StringUtils.isBlank(BeanUtils.getProperty(arg, UPDATE_BY_NAME))) {
+                        BeanUtils.setProperty(arg, UPDATE_BY_NAME, userName);
+                    }
+                }
+
+                if (isProperty(arg, CREATE_TIME) && StringUtils.isBlank(BeanUtils.getProperty(arg, CREATE_TIME))) {
+                    BeanUtils.setProperty(arg, CREATE_TIME, date);
+                }
+
+                if (isProperty(arg, UPDATE_TIME) && StringUtils.isBlank(BeanUtils.getProperty(arg, UPDATE_TIME))) {
+                    BeanUtils.setProperty(arg, UPDATE_TIME, date);
+                }
+
+                if (isProperty(arg, ID) && BeanUtils.getProperty(arg, ID) == null) {
+                    BeanUtils.setProperty(arg, ID, new IdWorker(1).nextId());
+                }
+
+                if (isProperty(arg, STATUS) && StringUtils.isBlank(BeanUtils.getProperty(arg, STATUS))) {
+                    BeanUtils.setProperty(arg, STATUS, Global.NO);
+                }
+
+                if (isProperty(arg, DEL_FLAG) && StringUtils.isBlank(BeanUtils.getProperty(arg, DEL_FLAG))) {
+                    BeanUtils.setProperty(arg, DEL_FLAG, Global.NO);
+                }
+            }
+        }
+        Object object = point.proceed();
+        return object;
+    }
+
+    public static boolean isProperty(Object bean, String field){
+        return BeanUtils.isProperty(bean, field);
+    }
+}

+ 69 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/AbstractLoginUser.java

@@ -0,0 +1,69 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sckw.core.model.auth;
+
+import java.util.Set;
+
+/**
+ * 登录中的用户信息
+ * <p>
+ * 为何类型是泛型,因为具体的项目不知道类型是什么
+ * @author fengshuonan
+ * @date 2017-11-09-下午5:47
+ */
+public interface AbstractLoginUser {
+
+    /**
+     * @description 获取用户唯一id
+     * @author fengshuonan
+     * @Date 2018/8/10 9:49
+     * @return
+     **/
+    <T> T getUserUniqueId();
+
+    /**
+     * @description 获取用户唯一id
+     * @author fengshuonan
+     * @Date 2018/8/10 9:49
+     * @return
+     **/
+    <T> T getAppId();
+
+    /**
+     * @description 获取角色id的集合
+     * @author fengshuonan
+     * @Date 2018/8/10 9:49
+     * @return
+     **/
+    <T> Set<T> getRoleIds();
+
+    /**
+     * @description 角色编码集合
+     * @author fengshuonan
+     * @Date 2018/8/10 9:49
+     * @return
+     **/
+    <T> Set<T> getRoleCodes();
+
+    /**
+     * @description 包含的资源权限url
+     * @author fengshuonan
+     * @Date 2018/8/10 9:49
+     * @return
+     **/
+    <T> Set<T> getResourceUrls();
+
+}

+ 47 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginBase.java

@@ -0,0 +1,47 @@
+package com.sckw.core.model.auth;
+
+import lombok.Data;
+
+/**
+ * @author zk
+ * @description 登录信息
+ * @date 2020/06/12 09:06:14
+ */
+@Data
+public class LoginBase {
+
+    /**
+     * 账号
+     */
+    private String account;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 验证码
+     */
+    private String captcha;
+
+    /**
+     * 系统类型(1 运营管理中心/2 运营管理中心/3 官网/4 司机应用)
+     */
+    private String systemType;
+
+    /**
+     * 客户端类型(ios 苹果设备/android 安卓设备/pc 浏览器/pc-background 管理系统)
+     */
+    private String clientType;
+
+    /**
+     * 登录方式1 账号密码登录/2账号短信登录/3单账号登录
+     */
+    private int loginMethod;
+
+    /**
+     * 用户类型(1 表示官网 )
+     */
+    private String userType;
+}

+ 52 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginEnterpriseInfo.java

@@ -0,0 +1,52 @@
+package com.sckw.core.model.auth;
+
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 登录中的用户企业信息
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+@Data
+public class LoginEnterpriseInfo {
+    /**
+     * 用户所属企业id
+     */
+    private Long id;
+    /**
+     * 用户所属企业名称
+     */
+    private String firmName;
+    /**
+     * 用户类型
+     */
+    private int userType;
+    /**
+     * 用户分支类型(1承运商企业、2车主)
+     */
+    private int branchType;
+    /**
+     * 资料审批状态(0未审批、1通过、2未通过、3审批中)
+     */
+    private int approval;
+    /**
+     * 用户状态(-1删除、0正常、1已锁)
+     */
+    private int status;
+
+    /**
+     * 交通安培账号状态
+     */
+    private int jtaqStatus;
+
+    /**
+     * 交通安培账号删除标识
+     */
+    private int jtaqDelFlag;
+
+    /**
+     * 企业注册时间
+     */
+    private Date regTime;
+}

+ 74 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/LoginUserInfo.java

@@ -0,0 +1,74 @@
+package com.sckw.core.model.auth;
+
+import lombok.Data;
+
+/**
+ * 登录中的用户信息
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+@Data
+public class LoginUserInfo {
+    /**
+     * 用户id
+     */
+    private Long id;
+    /**
+     * 用户所属系统
+     */
+    private Integer systemType;
+    /**
+     * 用户账号
+     */
+    private String account;
+    /**
+     * 用户姓名
+     */
+    private String userName;
+    /**
+     * 用户电话
+     */
+    private String telephone;
+    /**
+     *是否主账号(0是/1否)
+     */
+    private int isMain;
+    /**
+     *用户账号状态(0正常/1锁定)
+     */
+    private int status;
+    /**
+     * 用户所属企业id
+     */
+    private Long entId;
+    /**
+     * 用户登录终端
+     */
+    private String clientType;
+    /**
+     * 用户所属机构id
+     */
+    private Long deptId;
+    /**
+     * (司机)
+     */
+    private String userIds;
+
+
+    public LoginUserInfo() {
+    }
+
+    public LoginUserInfo(Long id, Integer systemType, String account, String userName, String telephone,
+                         int isMain, int status, Long entId, String clientType, Long deptId) {
+        this.id = id;
+        this.systemType = systemType;
+        this.account = account;
+        this.userName = userName;
+        this.telephone = telephone;
+        this.isMain = isMain;
+        this.status = status;
+        this.entId = entId;
+        this.clientType = clientType;
+        this.deptId = deptId;
+    }
+}

+ 27 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/AbstractLoginContext.java

@@ -0,0 +1,27 @@
+package com.sckw.core.model.auth.context;
+
+import com.sckw.core.model.auth.AbstractLoginUser;
+
+/**
+ * 快速获取登录信息上下文
+ * @author fengshuonan
+ * @date 2018-02-05 16:58
+ */
+public interface AbstractLoginContext {
+
+    /**
+     * @description 获取当前用户的token
+     * @author fengshuonan
+     * @dae 018-02-05 9:49
+     * @return token
+     **/
+    String getCurrentUserToken();
+
+    /**
+     * @description 获取当前用户
+     * @author fengshuonan
+     * @dae 2018-02-05 9:49
+     * @return
+     **/
+    <T extends AbstractLoginUser> T getLoginUser();
+}

+ 95 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/LoginEnterpriseHolder.java

@@ -0,0 +1,95 @@
+package com.sckw.core.model.auth.context;
+
+import com.sckw.core.model.auth.LoginEnterpriseInfo;
+
+/**
+ * 当前登录用户企业的临时保存容器
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+public class LoginEnterpriseHolder {
+    private static final ThreadLocal<LoginEnterpriseInfo> LONGIN_ENTERPRISE_HOLDER = new ThreadLocal<LoginEnterpriseInfo>();
+
+    /**
+     * 赋值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void set(LoginEnterpriseInfo loginEnterpriseInfo) {
+        LONGIN_ENTERPRISE_HOLDER.set(loginEnterpriseInfo);
+    }
+
+    /**
+     * 取值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static LoginEnterpriseInfo get() {
+        return LONGIN_ENTERPRISE_HOLDER == null ? null : LONGIN_ENTERPRISE_HOLDER.get();
+    }
+
+    /**
+     * 删除保存的用户
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void remove() {
+        LONGIN_ENTERPRISE_HOLDER.remove();
+    }
+
+    /**
+     * 用户所属企业id
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getEntId(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getId();
+    }
+
+    /**
+     * 用户所属企业名称
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getFirmName(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getFirmName();
+    }
+
+    /**
+     * 用户类型
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getUserType(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getUserType();
+    }
+
+    /**
+     * 资料审批状态(1通过、0未审批、2未通过、3审批中)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getApproval(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getApproval();
+    }
+
+    /**
+     * 用户状态(-1删除、0正常、1已锁)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getStatus(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getStatus();
+    }
+
+    /**
+     * 用户分支类型
+     * @author zk
+     * @date 2021/3/16 11:24
+     **/
+    public static Integer getBranchType(){
+        return LONGIN_ENTERPRISE_HOLDER.get() == null ? null : LONGIN_ENTERPRISE_HOLDER.get().getBranchType();
+    }
+
+
+}

+ 140 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/LoginUserHolder.java

@@ -0,0 +1,140 @@
+package com.sckw.core.model.auth.context;
+
+import com.sckw.core.model.auth.LoginUserInfo;
+
+/**
+ * 当前登录用户的临时保存容器
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+public class LoginUserHolder {
+
+    private static final ThreadLocal<LoginUserInfo> LONGIN_USER_HOLDER = new ThreadLocal<LoginUserInfo>();
+
+    /**
+     * 赋值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void set(LoginUserInfo loginUserInfo) {
+        LONGIN_USER_HOLDER.set(loginUserInfo);
+    }
+
+    /**
+     * 取值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static LoginUserInfo get() {
+        return LONGIN_USER_HOLDER == null ? null : LONGIN_USER_HOLDER.get();
+    }
+
+    /**
+     * 删除保存的用户
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void remove() {
+        LONGIN_USER_HOLDER.remove();
+    }
+
+    /**
+     * 用户id
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getUserId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getId();
+    }
+
+    /**
+     * 用户所属系统
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getSystemType(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getSystemType();
+    }
+
+    /**
+     * 用户账号
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getAccount(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getAccount();
+    }
+
+    /**
+     * 用户姓名
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getUserName(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getUserName();
+    }
+
+    /**
+     * 用户电话
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getTelephone(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getTelephone();
+    }
+
+    /**
+     * 是否主账号(0是/1否)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getIsMain(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getIsMain();
+    }
+
+    /**
+     * 用户账号状态(0正常/1锁定)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getStatus(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getStatus();
+    }
+
+    /**
+     * 用户所属企业
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getEntId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getEntId();
+    }
+
+    /**
+     * 用户登录终端
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getClientType(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getClientType();
+    }
+
+    /**
+     * 用户机构
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getDeptId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getDeptId();
+    }
+
+    /**
+     * (司机)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getUserIds(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getUserIds();
+    }
+
+}

+ 38 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/auth/context/SignBase.java

@@ -0,0 +1,38 @@
+package com.sckw.core.model.auth.context;
+
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * @author zk
+ * @description 获取铭文请求参数
+ * @date 2020/08/15 16:11:10
+ */
+@Data
+public class SignBase {
+    /**
+     * 铭文
+     */
+    private String sign;
+
+    /**
+     * 公钥
+     */
+    private String accessKey;
+
+    /**
+     * 私钥
+     */
+    private String accessSecret;
+
+    /**
+     * 时间戳
+     */
+    private Long timeStamp;
+
+    /**
+     * 请求参数
+     */
+    private Map<String, Object> params;
+}

+ 69 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/base/BaseModel.java

@@ -0,0 +1,69 @@
+package com.sckw.core.model.base;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 基础模型
+ * @author zk
+ * @date Nov 24, 2018
+ */
+@Data
+public class BaseModel implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键
+	 */
+	private Long id;
+
+	/**
+	 * 备注
+	 */
+	private String remark;
+
+	/**
+	 * 状态:0正常/1锁定
+	 */
+	private Integer status;
+
+	/**
+	 * 创建人
+	 */
+	private Long createBy;
+
+	/**
+	 * 创建人姓名
+	 */
+	private String createByName;
+
+	/**
+	 * 创建时间
+	 */
+	//@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+	private Date createTime;
+
+	/**
+	 * 更新人
+	 */
+	private Long updateBy;
+
+	/**
+	 * 跟新人姓名
+	 */
+	private String updateByName;
+
+	/**
+	 * 更新时间
+	 */
+	//@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+	private Date updateTime;
+
+	/**
+	 * 删除标识(0正常/-1删除)
+	 */
+	private Integer delFlag;
+
+}

+ 40 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/constant/AopSortConstants.java

@@ -0,0 +1,40 @@
+package com.sckw.core.model.constant;
+
+/**
+ * Roses中所有AOP的顺序排序(数字越低越靠前)
+ * @author zk
+ * @date 2018年07月23日 15:25:32
+ */
+public interface AopSortConstants {
+
+    /**
+     * 默认的ExceptionHandler的aop顺序
+     */
+    int DEFAULT_EXCEPTION_HANDLER_SORT = 200;
+
+    /**
+     * 临时保存RequestData的aop
+     */
+    int REQUEST_DATA_AOP_SORT = 500;
+
+    /**
+     * 参数校验为空的aop
+     */
+    int PARAM_VALIDATE_AOP_SORT = 510;
+
+    /**
+     * 控制器调用链的aop
+     */
+    int CHAIN_ON_CONTROLLER_SORT = 1;
+
+    /**
+     * provider的调用链aop
+     */
+    int CHAIN_ON_PROVIDER_SORT = 2;
+
+    /**
+     * consumer的调用链aop
+     */
+    int CHAIN_ON_CONSUMMER_SORT = 3;
+
+}

+ 217 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/constant/Global.java

@@ -0,0 +1,217 @@
+package com.sckw.core.model.constant;
+
+/**
+ * All rights Reserved, Designed By www.51wph.com
+ *
+ * @version V1.0
+ * @ProjectName: wph-platform
+ * @Package com.wph.common.consts
+ * @Description:全局配置类/系统常用常量
+ * @author: zk
+ * @date: 2019-05-28 17:31
+ * @Copyright: 2019 www.51wph.com Inc. All rights reserved.
+ * 注意:本内容仅限于汇链科技有限公司内部传阅,禁止外泄以及用于其他的商业目的
+ */
+public class Global {
+
+    /**pc-background token有效期为2小时*/
+    public static final int PC_BACKGROUND_TOKEN_EXPIRE = 60 * 60 * 2;
+
+    /**app token有效期为30天*/
+    public static final int APP_TOKEN_EXPIRE = 30 * 24 * 60 * 60;
+
+    /**pc token有效期为2小时*/
+    public static final int PC_TOKEN_EXPIRE = 2 * 60 * 60;
+
+    /**通用有效期为2小时*/
+    public static final int COMMON_EXPIRE = 2 * 60 * 60;
+
+    /**API调用token有效时间*/
+    public static final int API_EXPIRE = 120 * 60;
+
+    /**保存全局属性值*/
+//    private static Map<String, String> map = Maps.newHashMap();
+
+    /**显示/隐藏*/
+    public static final int SHOW = 1;
+    public static final int HIDE = 0;
+    public static final int MINUS_ONE = -1;
+
+    /**是/否*/
+    public static final int YES = 1;
+    public static final int NO = 0;
+    public static final String BE = "是";
+    public static final String NAY = "否";
+
+    /**对/错*/
+    public static final boolean TRUE = true;
+    public static final boolean FALSE = false;
+
+    /**字符*/
+    public static final String CODING_GBK = "GBK";
+    public static final String CODING_UTF8 = "UTF-8";
+
+    /**消息强弱提醒 强提醒:Y,否则:N*/
+    public static final String Y = "Y";
+    public static final String N = "N";
+
+    /**初始金额*/
+    public static final Double AMOUNT = 0.0;
+
+    /**初始数值*/
+    public static final int NUMERICAL_ZERO = 0;
+    public static final int NUMERICAL_ONE = 1;
+    public static final int NUMERICAL_TWO = 2;
+    public static final int NUMERICAL_THREE = 3;
+
+    /**pid等于0的*/
+    public static final String PID = "0";
+
+    /**or*/
+    public static final String OR = "OR";
+
+    /**and*/
+    public static final String AND = "AND";
+
+    /**ok*/
+    public static final String OK = "OK";
+
+    /**redis用户信息前缀*/
+    public static final String REDIS_USER_PREFIX = "userInfo:";
+
+    /**redis企业信息前缀*/
+    public static final String REDIS_ENTERPRISE_PREFIX = "enterpriseInfo:";
+
+    /**redis用户信息前缀*/
+    public static final String REDIS_SYS_MENU_PREFIX = "sysMenu:";
+
+    /**redis用户车辆gps信息*/
+    public static final String REDIS_CACHE_GPS_CAR_PREFIX = "cacheGpsCar:";
+
+    /**redis运营活动奖品前缀*/
+    public static final String REDIS_ACTIVITY_PRIZE_PREFIX = "activityPrize:";
+
+    /**redis用户运营活动抽奖信息前缀*/
+    public static final String ACTIVITY_JOIN = "activityJoin:";
+
+    /**redis用户运营活动信息前缀*/
+    public static final String ACTIVITY = "activity:";
+
+    /**汇链用户专场编号*/
+    public static final String PHONE = "400-030-5677";
+
+    /**系统初始密码*/
+    public static final String PASSWORD = "123456";
+
+    /**逗号*/
+    public static final String COMMA = ",";
+
+    /**点*/
+    public static final String DOT = ".";
+
+    /**冒号*/
+    public static final String COLON = ":";
+
+    /**下划线拼接*/
+    public static final char UNDERLINE = '_';
+
+    /**空字符串*/
+    public static final String EMPTY_STRING = "";
+
+    /**等号**/
+    public static final String EQUAL_SIGN = "=";
+
+    /**美元符号**/
+    public static final String DOLLAR = "$";
+
+    /**+符号**/
+    public static final String PLUS = "+";
+
+    /**下划线拼接*/
+    public static final String BRACKET = "()";
+    public static final String BRACKET_LEFT = "(";
+    public static final String BRACKET_RIGHT = ")";
+
+    /**大括号*/
+    public static final String BIG_BRACKETS = "{}";
+    public static final String BIG_BRACKETS_LEFT = "{";
+    public static final String BIG_BRACKETS_RIGHT = "}";
+
+    /**星号拼接*/
+    public static final String ASTERISK1 = "*";
+    public static final String ASTERISK2 = "**";
+
+    /**括号*/
+    public static final String BRACKETS = "[]";
+    public static final String BRACKETS_LEFT = "[";
+    public static final String BRACKETS_RIGHT = "]";
+
+    /**排序*/
+    public static final String ASC = "asc";
+    public static final String DESC = "desc";
+
+    /**请求成功值*/
+    public static final int SUCCEED = 200;
+
+    /**短信请求返回参数名*/
+    public static final String SUCCESS = "success";
+
+    /**pageNum当前页数/pageSize每页显示条数*/
+    public static final String PAGE_NUM = "pageNum";
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**可调用EncryUtil.generatorPriKey()方法生成*/
+    public static final String PRI_KEY = "127f0400ff8a8b7a20d91dfc60a39725";
+
+    /**APP*/
+    public static final String APP = "APP";
+
+    /**API*/
+    public static final String API = "API";
+
+    /**请求头token*/
+    public static final String ACCESS_TOKEN = "Access-Token";
+
+    /**客户终端类型*/
+    public static final String CLIENT_TYPE = "Client-Type";
+
+    /**系统类型*/
+    public static final String SYSTEM_TYPE = "System-Type";
+
+    /**请求代理*/
+    public static final String USER_AGENT = "user-agent";
+
+    /**请求格式*/
+    public static final String CONTENT_TYPE_AJ = "application/json";
+
+    /**请求方法*/
+    public static final String METHOD_POST = "POST";
+    public static final String METHOD_GET = "GET";
+
+    /**错误图片*/
+    public static final String WRONG_USER_HEAD = "data:,";
+
+    /**运输订单号前缀*/
+    public static final String TRAN_NUM_PREFIX = "LTO";
+
+    /**委托单单号前缀*/
+    public static final String ENTR_NUM_PREFIX = "LD";
+
+    /**车辆运单单号前缀*/
+    public static final String TASK_NUM_PREFIX = "LTL";
+
+    /**装货地点*/
+    public static final Integer ADDRESS_LOAD = 1;
+
+    /**卸货地点*/
+    public static final Integer ADDRESS_UNLOAD = 2;
+
+    /**时间周期-天/周/月/年*/
+    public static final String CYCLE_DAY = "天";
+    public static final String CYCLE_WEEK = "周";
+    public static final String CYCLE_MONTH = "月";
+    public static final String CYCLE_YEAR = "年";
+
+
+
+}

+ 47 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/enums/SensitiveStrategy.java

@@ -0,0 +1,47 @@
+package com.sckw.core.model.enums;
+
+import cn.hutool.core.util.DesensitizedUtil;
+import lombok.AllArgsConstructor;
+
+import java.util.function.Function;
+
+/**
+ * 脱敏策略
+ * @author zk
+ */
+@AllArgsConstructor
+public enum SensitiveStrategy {
+
+    /**
+     * 身份证脱敏
+     */
+    ID_CARD(s -> DesensitizedUtil.idCardNum(s, 3, 4)),
+
+    /**
+     * 手机号脱敏
+     */
+    PHONE(DesensitizedUtil::mobilePhone),
+
+    /**
+     * 地址脱敏
+     */
+    ADDRESS(s -> DesensitizedUtil.address(s, 8)),
+
+    /**
+     * 邮箱脱敏
+     */
+    EMAIL(DesensitizedUtil::email),
+
+    /**
+     * 银行卡
+     */
+    BANK_CARD(DesensitizedUtil::bankCard);
+
+    //可自行添加其他脱敏策略
+
+    private final Function<String, String> desensitizer;
+
+    public Function<String, String> desensitizer() {
+        return desensitizer;
+    }
+}

+ 76 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageHelperUtil.java

@@ -0,0 +1,76 @@
+package com.sckw.core.model.page;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.sckw.core.utils.ReflectionUtils;
+
+import java.util.List;
+
+/**
+ * MyBatis 分页查询助手
+ * @author zk
+ * @date Nov 24, 2018
+ */
+public class PageHelperUtil {
+
+    public static final String FIND_PAGE = "findPage";
+
+    /**
+     * 分页查询, 约定查询方法名为 “findPage”
+     * @param pageRequest 分页请求
+     * @param mapper Dao对象,MyBatis的 Mapper
+     * @return
+     */
+    public static PageResult findPage(PageRequest pageRequest, Object mapper) {
+        return findPage(pageRequest, mapper, FIND_PAGE);
+    }
+
+    /**
+     * 调用分页插件进行分页查询
+     * @param pageRequest 分页请求
+     * @param mapper Dao对象,MyBatis的 Mapper
+     * @param queryMethodName 要分页的查询方法名
+     * @param args 方法参数
+     * @return
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static PageResult findPage(PageRequest pageRequest, Object mapper, String queryMethodName, Object... args) {
+        // 设置分页参数
+        int pageNum = pageRequest.getPageNum();
+        int pageSize = pageRequest.getPageSize();
+        PageHelper.startPage(pageNum, pageSize);
+        // 利用反射调用查询方法
+        Object result = ReflectionUtils.invoke(mapper, queryMethodName, args);
+        return getPageResult(pageRequest, new PageInfo((List) result));
+    }
+
+    /**
+     * 将分页信息封装到统一的接口
+     * @param pageRequest
+     * @param pageInfo
+     * @return
+     */
+    private static PageResult getPageResult(PageRequest pageRequest, PageInfo<?> pageInfo) {
+        return setPageResult(pageInfo);
+    }
+
+    /**
+     * 将分页信息封装到统一的接口
+     * @param pageInfo
+     * @return PageResult
+     */
+    public static PageResult getPageResult(PageInfo<?> pageInfo) {
+        return setPageResult(pageInfo);
+    }
+
+    public static PageResult setPageResult(PageInfo<?> pageInfo){
+        PageResult pageResult = new PageResult();
+        pageResult.setPageNum(pageInfo.getPageNum());
+        pageResult.setPageSize(pageInfo.getPageSize());
+        pageResult.setSize(pageInfo.getTotal());
+        pageResult.setPages(pageInfo.getPages());
+        pageResult.setList(pageInfo.getList());
+        return pageResult;
+    }
+
+}

+ 30 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageRequest.java

@@ -0,0 +1,30 @@
+package com.sckw.core.model.page;
+
+/**
+ * 分页请求
+ * @author zk
+ * @date Nov 24, 2018
+ */
+public class PageRequest {
+	/**
+	 * 当前页码
+	 */
+	private int pageNum = 1;
+	/**
+	 * 每页数量
+	 */
+	private int pageSize = 10;
+
+	public int getPageNum() {
+		return pageNum;
+	}
+	public void setPageNum(int pageNum) {
+		this.pageNum = pageNum;
+	}
+	public int getPageSize() {
+		return pageSize;
+	}
+	public void setPageSize(int pageSize) {
+		this.pageSize = pageSize;
+	}
+}

+ 125 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/page/PageResult.java

@@ -0,0 +1,125 @@
+package com.sckw.core.model.page;
+
+import com.github.pagehelper.PageInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description 分页结果相关
+ * @Author zk
+ * @Date 2019/5/14
+ */
+public class PageResult {
+
+    /**
+     * 当前页数
+     */
+    protected int pageNum;
+    /**
+     * 每页显示条数
+     */
+    protected int pageSize;
+    /**
+     * 总条数
+     */
+    protected long size;
+    /**
+     * 总页数
+     */
+    protected int pages;
+    protected List list;
+
+    public PageResult(){
+
+    }
+
+    public PageResult(int pageNum, int pageSize, List list){
+        this.pageNum = pageNum;
+        this.pageSize = pageSize;
+        if(list == null){
+            this.size = 0;
+            this.list = null;
+        }else{
+            this.size = list.size();
+            this.list = list.subList(pageSize * (pageNum - 1),pageSize * pageNum > size ? (int) size : pageSize * pageNum);
+        }
+    }
+
+    public PageResult(int pageNum, int pageSize, List list, int size){
+        this.pageNum = pageNum;
+        this.pageSize = pageSize;
+        if(list == null){
+            this.size = 0;
+            this.list = null;
+        }else{
+            this.size = size;
+            this.list = list;
+        }
+    }
+
+    public PageResult(PageInfo pageInfo){
+        this.pageNum = pageInfo.getPageNum();
+        this.pageSize = pageInfo.getPageSize();
+        this.size = pageInfo.getTotal();
+        this.pages = pageInfo.getPages();
+        this.list = pageInfo.getList();
+    }
+
+    public void setPageInfo(PageInfo pageInfo){
+        this.pageNum = pageInfo.getPageNum();
+        this.pageSize = pageInfo.getPageSize();
+        this.size = pageInfo.getTotal();
+        this.pages = pageInfo.getPages();
+        this.list = pageInfo.getList();
+    }
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+
+    public int getPages() {
+        return pages;
+    }
+
+    public void setPages(int pages) {
+        this.pages = pages;
+    }
+
+    public List getList() {
+        return list;
+    }
+
+    public void setList(List list) {
+        this.list = list;
+    }
+
+    public static int getPageNum(Map record) {
+        return record != null && record.get("pageNum") != null ? Integer.parseInt(record.get("pageNum").toString()) : 1;
+    }
+
+    public static int getPageSize(Map record) {
+        return record != null && record.get("pageSize") != null ? Integer.parseInt(record.get("pageSize").toString()) : 10;
+    }
+
+}

+ 17 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/service/SensitiveService.java

@@ -0,0 +1,17 @@
+package com.sckw.core.service;
+
+/**
+ * 脱敏服务
+ * 默认管理员不过滤
+ * 需自行根据业务重写实现
+ * @author
+ * @version
+ */
+public interface SensitiveService {
+
+    /**
+     * 是否脱敏
+     */
+    boolean isSensitive();
+
+}

+ 219 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/BeanUtils.java

@@ -0,0 +1,219 @@
+package com.sckw.core.utils;
+
+import cn.hutool.core.bean.BeanUtil;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * @author zk
+ * @version V1.0
+ * @Title: SupplyMapper
+ * @Package com.wph.modules.supply.mapper
+ * @Description: ()
+ * @date 2019/5/15 001510:37
+ */
+public class BeanUtils extends BeanUtil {
+
+    /**
+     * 下划线拼接
+     */
+    public static final char UNDERLINE = '_';
+
+    public static boolean checkFieldValueNull(Object bean) {
+        boolean result = true;
+        if (bean == null) {
+            return true;
+        }
+        Class<?> cls = bean.getClass();
+        Method[] methods = cls.getDeclaredMethods();
+        Field[] fields = cls.getDeclaredFields();
+        for (Field field : fields) {
+            try {
+                String fieldGetName = parGetName(field.getName());
+                if (!checkGetMet(methods, fieldGetName)) {
+                    continue;
+                }
+                Method fieldGetMet = cls.getMethod(fieldGetName, new Class[]{});
+                Object fieldVal = fieldGetMet.invoke(bean, new Object[]{});
+                if (fieldVal != null) {
+                    if ("".equals(fieldVal)) {
+                        result = true;
+                    } else {
+                        result = false;
+                    }
+                }
+            } catch (Exception e) {
+                continue;
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * 拼接某属性的 get方法
+     *
+     * @param fieldName
+     * @return String
+     */
+    public static String parGetName(String fieldName) {
+        if (null == fieldName || "".equals(fieldName)) {
+            return null;
+        }
+        int startIndex = 0;
+        if (fieldName.charAt(0) == UNDERLINE){
+            startIndex = 1;}
+        return "get"
+                + fieldName.substring(startIndex, startIndex + 1).toUpperCase()
+                + fieldName.substring(startIndex + 1);
+    }
+
+    /**
+     * 判断是否存在某属性的 get方法
+     *
+     * @param methods
+     * @param fieldGetMet
+     * @return boolean
+     */
+    public static boolean checkGetMet(Method[] methods, String fieldGetMet) {
+        for (Method met : methods) {
+            if (fieldGetMet.equals(met.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     *
+     * @Title: isProperty
+     * @Description: 判断对象是否存在某属性
+     * @param bean 对象
+     * @param propertyName 属性
+     * @return
+     * @return: boolean 有则反之true 反之false
+     *
+    public static boolean isProperty(Object bean, String propertyName){
+        if (bean == null) {
+            return false;
+        }
+        Class<?> cls = bean.getClass();
+        PropertyDescriptor[] propertys = org.springframework.beans.BeanUtils.getPropertyDescriptors(cls);
+        for (PropertyDescriptor property : propertys){
+            String fieldName = property.getName();
+            if(fieldName != null && propertyName != null && fieldName.equals(propertyName)){
+                return true;
+            }
+        }
+        return false;
+    }*/
+
+
+    /**
+     * @description 判断当前对象是否为空
+     * @author jiangwei
+     * @date 2020/9/18 14:40
+     * @param object
+     * @return boolean
+     **/
+    public static boolean objCheckIsNull(Object object){
+        return objCheckIsNull(object,null,null);
+    }
+
+    /**
+     * @description 判断当前对象是否为空(包括所有属性为空)
+     * 可选则在判断规则中剔除某一字段,或者某一值
+     * @author jiangwei
+     * @date 2020/5/22 10:14
+     * @param object 入参对象
+     * @param excludeNameList 要剔除的属性名称,没有就传空集合或者null
+     * @param excludeValueList 要剔除的数值,没有就传空集合或者null
+     * @return boolean
+     **/
+    public static boolean objCheckIsNull(Object object, List<String> excludeNameList, List<Object> excludeValueList) {
+
+        if (object == null) {
+            return true;
+        }
+        // 得到类对象
+        Class clazz = object.getClass();
+        // 得到所有属性
+        Field[] fields = clazz.getDeclaredFields();
+        //判断入参
+        boolean excludeNameListFlag = false;
+        if (excludeNameList != null && excludeNameList.size() > 0) {
+            excludeNameListFlag = true;
+        }
+        boolean excludeValueListFlag = false;
+        if (excludeValueList != null && excludeValueList.size() > 0) {
+            excludeValueListFlag = true;
+        }
+        //定义返回结果,默认为true
+        boolean flag = true;
+        for (Field field : fields) {
+            field.setAccessible(true);
+            Object fieldValue = null;
+            String fieldName = null;
+            try {
+                //得到属性值
+                fieldValue = field.get(object);
+                //得到属性类型
+                Type fieldType = field.getGenericType();
+                //得到属性名
+                fieldName = field.getName();
+                //剔除指定属性名的属性值
+                if (excludeNameListFlag) {
+                    for (String s : excludeNameList) {
+                        if (fieldName.equals(s)) {
+                            fieldValue = null;
+                        }
+                    }
+                }
+                //剔除指定属性值
+                if (excludeValueListFlag) {
+                    for (Object obj : excludeValueList) {
+                        if (fieldValue == obj) {
+                            fieldValue = null;
+                        }
+                    }
+                }
+            } catch (IllegalArgumentException | IllegalAccessException e) {
+                e.printStackTrace();
+            }
+            //只要有一个属性值不为null 就返回false 表示对象不为null 忽略序列化
+            if (fieldValue != null && !"serialVersionUID".equals(fieldName)) {
+                flag = false;
+                break;
+            }
+        }
+        return flag;
+    }
+
+    /**
+     *
+     * @Title: isProperty
+     * @Description: 判断对象是否存在某属性
+     * @param bean 对象
+     * @param propertyName 属性
+     * @return
+     * @return: boolean 有则反之true 反之false
+     * */
+    public static boolean isProperty(Object bean, String propertyName){
+        if (bean == null) {
+            return false;
+        }
+        Class<?> cls = bean.getClass();
+        PropertyDescriptor[] propertys = org.springframework.beans.BeanUtils.getPropertyDescriptors(cls);
+        for (PropertyDescriptor property : propertys){
+            String fieldName = property.getName();
+            if(fieldName != null && propertyName != null && fieldName.equals(propertyName)){
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 314 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/CollectionUtils.java

@@ -0,0 +1,314 @@
+package com.sckw.core.utils;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONObject;
+import java.util.*;
+
+/**
+ * @author zk
+ * @description 集合框架处理类
+ * @date 2020/06/06 09:03:53
+ */
+public class CollectionUtils extends CollectionUtil {
+    private static final int DEFAULT_INITIAL_CAPACITY = 16;
+
+    public CollectionUtils() {
+    }
+
+    /**
+     * @Description 创建HashMap
+     * @Author dengyinghui
+     * @Date 2019/5/12
+     * @return
+     */
+    public static synchronized Map<String, Object> createHashMap(){
+	  return new HashMap<>(DEFAULT_INITIAL_CAPACITY);
+    }
+
+    /**
+     * @Description 从Map中获取String值
+     * @param map map集合
+     * @param key key值
+     * @Author dengyinghui
+     * @Date 2019/5/14
+     * @return
+     */
+    public static String getString(Map<String, Object> map, String key){
+	  if(map == null){
+		return null;
+	  }
+	  return StringUtils.valueOf(map.get(key));
+    }
+
+    /**
+     * @Description 从Map中获取Integer值
+     * @param map map集合
+     * @param key key值
+     * @Author dengyinghui
+     * @Date 2019/5/14
+     * @return
+     */
+    public static Integer getInteger(Map<String, Object> map, String key){
+	  if(map == null){
+		return null;
+	  }
+	  return (Integer)map.get(key);
+    }
+
+    /**
+     * @Description 从Map中获取Date值
+     * @param map map集合
+     * @param key key值
+     * @Author dengyinghui
+     * @Date 2019/5/14
+     * @return
+     */
+    public static Date getDate(Map<String, Object> map, String key){
+	  if(map == null){
+		return null;
+	  }
+	  return (Date)map.get(key);
+    }
+
+    /**
+     * @Description JSONObject转MAP<String,String>
+     * @param object JSONObject对象
+     * @Author bernie
+     * @Date 2019/08/02
+     * @return HashMap<String, String> map结果
+     */
+    public static HashMap<String, String> toHashMap(JSONObject object)
+    {
+	  HashMap<String, String> data = new HashMap<>(16);
+	  Set<String> keys =  object.keySet();
+	  Iterator it = keys.iterator();
+	  // 遍历jsonObject数据,添加到Map对象
+	  while (it.hasNext())
+	  {
+		String key = String.valueOf(it.next());
+		String value = (String) object.get(key);
+		data.put(key, value);
+	  }
+	  return data;
+    }
+
+    public static boolean isEmpty(Collection<?> list) {
+	  return list == null || list.size() == 0;
+    }
+
+    public static Set<String> valueOfSet(String str) {
+	  return valueOfSet(str, ",");
+    }
+
+    public static Set<String> valueOfSet(String str, String split) {
+	  Set<String> set = new HashSet();
+	  str = StringUtils.trimNull(str);
+	  if (!StringUtils.isEmpty(str)) {
+		String[] strs = str.split(split);
+		if (!StringUtils.isEmpty(strs)) {
+		    String[] var7 = strs;
+		    int var6 = strs.length;
+
+		    for(int var5 = 0; var5 < var6; ++var5) {
+			  String string = var7[var5];
+			  string = StringUtils.trimNull(string);
+			  if (!StringUtils.isEmpty(string)) {
+				set.add(string);
+			  }
+		    }
+		}
+	  }
+
+	  return set;
+    }
+
+    public static List<String> valueOfList(String str) {
+	  return valueOfList(str, ",");
+    }
+
+    public static List<String> valueOfList(String str, String split) {
+	  List<String> list = new ArrayList();
+	  str = StringUtils.trimNull(str);
+	  if (!StringUtils.isEmpty(str)) {
+		String[] strs = str.split(split);
+		if (!StringUtils.isEmpty(strs)) {
+		    String[] var7 = strs;
+		    int var6 = strs.length;
+
+		    for(int var5 = 0; var5 < var6; ++var5) {
+			  String string = var7[var5];
+			  string = StringUtils.trimNull(string);
+			  if (!StringUtils.isEmpty(string)) {
+				list.add(string);
+			  }
+		    }
+		}
+	  }
+
+	  return list;
+    }
+
+    /**
+          * 按照List<Map<String,Object>>里面map的某个value重新封装成多个不同的list, 原始数据类型List<Map
+          * <String,Object>>, 转换后数据类型Map<String,List<Map<String,Object>>>
+          * @param list
+          * @param oneMapKey
+          * @return
+          */
+    public static Map<String, Object> change(List<Map<String, Object>> list, String oneMapKey) {
+	  Map<String, Object> resultMap = CollectionUtils.createHashMap();
+	  Set<Object> setTmp = new HashSet<Object>();
+	  for (Map<String, Object> tmp : list) {
+		setTmp.add(tmp.get(oneMapKey));
+	  }
+	  Iterator<Object> it = setTmp.iterator();
+	  while (it.hasNext()) {
+		String oneSetTmpStr = (String) it.next();
+		List<Map<String, Object>> oneSetTmpList = new ArrayList<Map<String, Object>>();
+		for (Map<String, Object> tmp : list) {
+		    String oneMapValueStr = (String) tmp.get(oneMapKey);
+		    if (oneMapValueStr.equals(oneSetTmpStr)) {
+			  oneSetTmpList.add(tmp);
+		    }
+		}
+		resultMap.put(oneSetTmpStr, oneSetTmpList);
+	  }
+	  return resultMap;
+    }
+
+    /**
+          * 按照List<Map<String,Object>>里面map的某个value重新封装成多个不同的list, 原始数据类型List<Map
+          * <String,Object>>, 转换后数据类型Map<String,List<Map<String,Object>>>
+          * @param list
+          * @param oneMapKey
+          * @return
+          */
+    public static List<Map<String, Object>> change2(List<Map<String, Object>> inList, String oneMapKey,
+								    List<Map<String, Object>> outList) {
+	  // 1.将某个key的值存在set中
+	  Set<Object> setTmp = new HashSet<Object>();
+	  for (Map<String, Object> tmp : inList) {
+		setTmp.add(tmp.get(oneMapKey));
+	  }
+	  // 2.遍历set
+	  Iterator<Object> it = setTmp.iterator();
+	  while (it.hasNext()) {
+		String oneMapValueStr = "";
+		String oneSetTmpStr = (String) it.next();
+		Map<String, Object> oneSetTmpMap = CollectionUtils.createHashMap();
+		List<Map<String, Object>> oneSetTmpList = new ArrayList<Map<String, Object>>();
+
+		for (Map<String, Object> tmp : inList) {
+		    oneMapValueStr = (String) tmp.get(oneMapKey);
+		    if (oneSetTmpStr.equals(oneMapValueStr)) {
+			  oneSetTmpMap.put("key", oneSetTmpStr);
+			  oneSetTmpList.add(tmp);
+		    }
+		}
+		oneSetTmpMap.put("children", oneSetTmpList);
+		outList.add(oneSetTmpMap);
+	  }
+	  return outList;
+    }
+
+	/**
+	 * 开始分页
+	 * @param list
+	 * @param pageNum 页码
+	 * @param pageSize 每页多少条数据
+	 * @return
+	 */
+	public static List startPage(List list, Integer pageNum,
+								 Integer pageSize) {
+		if (list == null) {
+			return null;
+		}
+		if (list.size() == 0) {
+			return null;
+		}
+		Integer count = list.size(); // 记录总数
+		int fromIndex = Math.min((pageNum - 1) * pageSize,count);
+		int toIndex = Math.min(fromIndex + pageSize,count);
+
+		List pageList = list.subList(fromIndex, toIndex);
+		return pageList;
+	}
+
+	/**
+	 * Map 按值排序
+	 * @param params
+	 * @return
+	 */
+	public static Set<Map.Entry<String, Integer>> valueSort(Map<String, Integer> params){
+		Set<Map.Entry<String, Integer>> treeSet = new TreeSet<Map.Entry<String, Integer>>(
+				new Comparator<Map.Entry<String, Integer>>() {
+					public int compare(Map.Entry<String, Integer> o1,
+									   Map.Entry<String, Integer> o2) {
+						Integer d1 = o1.getValue();
+						Integer d2 = o2.getValue();
+						int r = d2.compareTo(d1);
+
+						if (r != 0)
+							return r;
+						else
+							return o2.getKey().compareTo(o1.getKey());
+					}
+				});
+		treeSet.addAll(params.entrySet());
+		return treeSet;
+	}
+
+    public static void main(String[] args) {
+	  Map<String, Object> map1 = CollectionUtils.createHashMap();
+	  Map<String, Object> map2 = CollectionUtils.createHashMap();
+	  Map<String, Object> map3 = CollectionUtils.createHashMap();
+	  Map<String, Object> map4 = CollectionUtils.createHashMap();
+	  Map<String, Object> map5 = CollectionUtils.createHashMap();
+
+	  List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+	  map1.put("id", "111");
+	  map1.put("name", "tom");
+	  map1.put("sex", "male");
+
+	  map2.put("id", "222");
+	  map2.put("name", "jack");
+	  map2.put("sex", "male");
+
+	  map3.put("id", "333");
+	  map3.put("name", "lucy");
+	  map3.put("sex", "female");
+
+	  map4.put("id", "444");
+	  map4.put("name", "lucy");
+	  map4.put("sex", "female");
+
+	  inList.add(map1);
+	  inList.add(map2);
+	  inList.add(map3);
+	  inList.add(map4);
+	  System.out.println("原始inList:" + inList);
+
+
+	  map5.put("一类(爆炸品)", map4);
+	  map5.put("二类(压缩,液化气体)", null);
+	  map5.put("三类(易燃液体)", null);
+	  map5.put("四类(易燃固体,自燃物品和遇湿易燃)", map3);
+	  map5.put("五类(氧化剂,有机过氧化物)", null);
+	  map5.put("六类(毒害品,感染类物品)", null);
+	  map5.put("七类(放射性物质)", null);
+	  map5.put("八类(腐蚀品)", null);
+	  map5.put("九类(危险废弃物)", map2);
+	  map5.put("普货", null);
+	  map5.put("其他", map2);
+
+	  Map<String, Object> resultMap = CollectionUtils.createHashMap();
+	  // resultMap = change(list, "sex");
+	  resultMap = change(inList, "name");
+	  System.out.println("按照map中的某个值重新封装后的resultMap:" + JSONObject.toJSONString(resultMap));
+
+	  List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+	  System.out.println("retList==1==:" + outList);
+	  outList = change2(inList, "name", outList);
+	  System.out.println("retList==2==:" + JSONObject.toJSONString(outList));
+    }
+}

+ 147 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/Digests.java

@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2005-2012 springside.org.cn
+ */
+package com.sckw.core.utils;
+
+import org.apache.commons.lang3.Validate;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+
+/**
+ * 支持SHA-1/MD5消息摘要的工具类.
+ * 返回ByteSource,可进一步被编码为Hex, Base64或UrlSafeBase64
+ * @author calvin
+ */
+public class Digests {
+
+	private static final String SHA1 = "SHA-1";
+	private static final String MD5 = "MD5";
+
+	private static SecureRandom random = new SecureRandom();
+
+	/**
+	 * 对输入字符串进行md5散列.
+	 */
+	public static byte[] md5(byte[] input) {
+		return digest(input, MD5, null, 1);
+	}
+	public static byte[] md5(byte[] input, int iterations) {
+		return digest(input, MD5, null, iterations);
+	}
+	
+	/**
+	 * 对输入字符串进行sha1散列.
+	 */
+	public static byte[] sha1(byte[] input) {
+		return digest(input, SHA1, null, 1);
+	}
+
+	public static byte[] sha1(byte[] input, byte[] salt) {
+		return digest(input, SHA1, salt, 1);
+	}
+
+	public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
+		return digest(input, SHA1, salt, iterations);
+	}
+
+	/**
+	 * 对字符串进行散列, 支持md5与sha1算法.
+	 */
+	private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
+		try {
+			MessageDigest digest = MessageDigest.getInstance(algorithm);
+
+			if (salt != null) {
+				digest.update(salt);
+			}
+
+			byte[] result = digest.digest(input);
+
+			for (int i = 1; i < iterations; i++) {
+				digest.reset();
+				result = digest.digest(result);
+			}
+			return result;
+		} catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            return null;
+		}
+	}
+
+	/**
+	 * 生成随机的Byte[]作为salt.
+	 * 
+	 * @param numBytes byte数组的大小
+	 */
+	public static byte[] generateSalt(int numBytes) {
+		Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
+
+		byte[] bytes = new byte[numBytes];
+		random.nextBytes(bytes);
+		return bytes;
+	}
+
+	/**
+	 * 对文件进行md5散列.
+	 */
+	public static byte[] md5(InputStream input) throws IOException {
+		return digest(input, MD5);
+	}
+
+	/**
+	 * 对文件进行sha1散列.
+	 */
+	public static byte[] sha1(InputStream input) throws IOException {
+		return digest(input, SHA1);
+	}
+
+	private static byte[] digest(InputStream input, String algorithm) throws IOException {
+		try {
+			MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+			int bufferLength = 8 * 1024;
+			byte[] buffer = new byte[bufferLength];
+			int read = input.read(buffer, 0, bufferLength);
+
+			while (read > -1) {
+				messageDigest.update(buffer, 0, read);
+				read = input.read(buffer, 0, bufferLength);
+			}
+
+			return messageDigest.digest();
+		} catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            return null;
+		}
+	}
+	
+	public static String string2MD5(String inStr){  
+        MessageDigest md5 = null;  
+        try{  
+            md5 = MessageDigest.getInstance("MD5");  
+        }catch (Exception e){  
+            System.out.println(e.toString());  
+            e.printStackTrace();  
+            return "";  
+        }  
+        char[] charArray = inStr.toCharArray();  
+        byte[] byteArray = new byte[charArray.length];  
+  
+        for (int i = 0; i < charArray.length; i++) {
+            byteArray[i] = (byte) charArray[i];
+        }
+        byte[] md5Bytes = md5.digest(byteArray);  
+        StringBuffer hexValue = new StringBuffer();  
+        for (int i = 0; i < md5Bytes.length; i++){  
+            int val = ((int) md5Bytes[i]) & 0xff;  
+            if (val < 16) {
+                hexValue.append("0");
+            }
+            hexValue.append(Integer.toHexString(val));  
+        }  
+        return hexValue.toString();  
+  
+    }  
+}

+ 153 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/Encodes.java

@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2005-2012 springside.org.cn
+ */
+package com.sckw.core.utils;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringEscapeUtils;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * 封装各种格式的编码解码工具类.
+ * 1.Commons-Codec的 hex/base64 编码
+ * 2.自制的base62 编码
+ * 3.Commons-Lang的xml/html escape
+ * 4.JDK提供的URLEncoder
+ * @author calvin
+ * @version 2013-01-15
+ */
+public class Encodes {
+
+	private static final String DEFAULT_URL_ENCODING = "UTF-8";
+	private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
+
+	/**
+	 * Hex编码.
+	 */
+	public static String encodeHex(byte[] input) {
+		return new String(Hex.encodeHex(input));
+	}
+
+	/**
+	 * Hex解码.
+	 */
+	public static byte[] decodeHex(String input) {
+		try {
+			return Hex.decodeHex(input.toCharArray());
+		} catch (DecoderException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * Base64编码.
+	 */
+	public static String encodeBase64(byte[] input) {
+		return new String(Base64.encodeBase64(input));
+	}
+	
+	/**
+	 * Base64编码.
+	 */
+	public static String encodeBase64(String input) {
+		try {
+			return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
+		} catch (UnsupportedEncodingException e) {
+			return "";
+		}
+	}
+
+//	/**
+//	 * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
+//	 */
+//	public static String encodeUrlSafeBase64(byte[] input) {
+//		return Base64.encodeBase64URLSafe(input);
+//	}
+
+	/**
+	 * Base64解码.
+	 */
+	public static byte[] decodeBase64(String input) {
+		return Base64.decodeBase64(input.getBytes());
+	}
+	
+	/**
+	 * Base64解码.
+	 */
+	public static String decodeBase64String(String input) {
+		try {
+			return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			return "";
+		}
+	}
+
+	/**
+	 * Base62编码。
+	 */
+	public static String encodeBase62(byte[] input) {
+		char[] chars = new char[input.length];
+		for (int i = 0; i < input.length; i++) {
+			chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
+		}
+		return new String(chars);
+	}
+
+	/**
+	 * Html 转码.
+	 */
+	public static String escapeHtml(String html) {
+		return StringEscapeUtils.escapeHtml4(html);
+	}
+
+	/**
+	 * Html 解码.
+	 */
+	public static String unescapeHtml(String htmlEscaped) {
+		return StringEscapeUtils.unescapeHtml4(htmlEscaped);
+	}
+
+	/**
+	 * Xml 转码.
+	 */
+	public static String escapeXml(String xml) {
+		return StringEscapeUtils.escapeXml10(xml);
+	}
+
+	/**
+	 * Xml 解码.
+	 */
+	public static String unescapeXml(String xmlEscaped) {
+		return StringEscapeUtils.unescapeXml(xmlEscaped);
+	}
+
+	/**
+	 * URL 编码, Encode默认为UTF-8. 
+	 */
+	public static String urlEncode(String part) {
+		try {
+			return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * URL 解码, Encode默认为UTF-8. 
+	 */
+	public static String urlDecode(String part) {
+
+		try {
+			return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+}

+ 123 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/EncryptionUtil.java

@@ -0,0 +1,123 @@
+package com.sckw.core.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 加密
+ * @author zk
+ * @date 2019-12-29
+ */
+public class EncryptionUtil {
+
+	private final static String[] HEX_DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d","e", "f" };
+	private final static String MD5 = "MD5";
+	private final static String SHA = "SHA";
+	private final static String SHA256 = "SHA-256";
+
+	private Object salt;
+	private String algorithm;
+
+	public EncryptionUtil() {
+
+	}
+
+	public EncryptionUtil(Object salt) {
+		this(salt, MD5);
+	}
+	
+	public EncryptionUtil(Object salt, String algorithm) {
+		this.salt = salt;
+		this.algorithm = algorithm;
+	}
+
+	/**
+	 * 加密
+	 * @param params
+	 * @return
+	 */
+	public String encode(String params) {
+		String result = null;
+		try {
+			MessageDigest md = MessageDigest.getInstance(algorithm);
+			// 加密后的字符串
+			result = byteArrayToHexString(md.digest(mergeEncryptionAndSalt(params).getBytes("utf-8")));
+		} catch (Exception ex) {
+		}
+		return result;
+	}
+
+	/**
+	 * 密码匹配验证
+	 * @param encParams 密文
+	 * @param rawParams 明文
+	 * @return
+	 */
+	public boolean matches(String encParams, String rawParams) {
+		String pass1 = "" + encParams;
+		String pass2 = encode(rawParams);
+		return pass1.equals(pass2);
+	}
+
+	private String mergeEncryptionAndSalt(String params) {
+		if (params == null) {
+			params = "";
+		}
+
+		if ((salt == null) || "".equals(salt)) {
+			return params;
+		} else {
+			return params + "{" + salt.toString() + "}";
+		}
+	}
+
+	/**
+	 * 转换字节数组为16进制字串
+	 * @param b 字节数组
+	 * @return 16进制字串
+	 */
+	private String byteArrayToHexString(byte[] b) {
+		StringBuffer resultSb = new StringBuffer();
+		for (int i = 0; i < b.length; i++) {
+			resultSb.append(byteToHexString(b[i]));
+		}
+		return resultSb.toString();
+	}
+
+	/**
+	 * 将字节转换为16进制
+	 * @param b
+	 * @return
+	 */
+	private static String byteToHexString(byte b) {
+		int n = b;
+		if (n < 0) {
+			n = 256 + n;
+		}
+		int d1 = n / 16;
+		int d2 = n % 16;
+		return HEX_DIGITS[d1] + HEX_DIGITS[d2];
+	}
+
+	/**
+	 * SHA-256加密
+	 * @param str
+	 * @return
+	 */
+	public String getSHA256Str(String str){
+		MessageDigest messageDigest;
+		String encodeStr = "";
+		try {
+			messageDigest = MessageDigest.getInstance(SHA256);
+			messageDigest.update(str.getBytes("UTF-8"));
+			encodeStr = byteArrayToHexString(messageDigest.digest());
+		} catch (NoSuchAlgorithmException e) {
+			e.printStackTrace();
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return encodeStr;
+	}
+
+}

+ 113 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/IdWorker.java

@@ -0,0 +1,113 @@
+package com.sckw.core.utils;
+
+/**
+ * 雪花算法生成ID
+ */
+public class IdWorker {
+    /** 开始时间截 (建议用服务第一次上线的时间,到毫秒级的时间戳) */
+    private final long twepoch = 1651070159429L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 10L;
+
+    /** 支持的最大机器id,结果是1023 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 时间截向左移22位(10+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     * <<为左移,每左移动1位,则扩大1倍
+     * */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~1024) */
+    private long workerId;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~1023)
+     */
+    public IdWorker(long workerId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
+        }
+        this.workerId = workerId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            //如果毫秒相同,则从0递增生成序列号
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间,从1970-01-01 08:00:00算起
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    public static void main(String[] args) {
+        System.out.println(new IdWorker(1).nextId());
+        System.out.println(System.currentTimeMillis());
+    }
+}

+ 57 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/LocUtils.java

@@ -0,0 +1,57 @@
+package com.sckw.core.utils;
+
+import java.net.URL;
+import java.util.StringJoiner;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+public class LocUtils {
+
+    public static String getAddressName(String point) {
+        // 返回数据
+        String res = "";
+        if (point == null || point.equals("0.0,0.0")) {
+            return res;
+        }
+        // 请求头
+        String urlHead = "http://restapi.amap.com/v3/geocode/regeo?key=8325164e247e15eea68b59e89200988b&s=rsv3&location=";
+        // 请求参数
+        String urlParam = "&radius=2800&callback=jsonp_452865_&platform=JS&logversion=2.0&sdkversion=1.3&appname=http%3A%2F%2Flbs.amap.com%2Fconsole%2Fshow%2Fpicker&csid=49851531-2AE3-4A3B-A8C8-675A69BCA316";
+        StringJoiner sj = new StringJoiner("");
+        // 完整请求地址
+        String requestUrl = sj.add(urlHead).add(point).add(urlParam).toString();
+
+        String methodStr = "GET";
+        String codeType = "UTF-8";
+        try {
+            URL url = new URL(requestUrl);
+            java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();
+            conn.setDoOutput(true);
+            conn.setRequestMethod(methodStr);
+            java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(), codeType));
+            String line;
+            while ((line = in.readLine()) != null) {
+                res += line + "\n";
+            }
+            in.close();
+
+            if (!"".equalsIgnoreCase(res)) {
+                String regeoKey = "regeocode";
+                String addressKey = "formatted_address";
+                String strAddrs = res.substring(res.indexOf("(") + 1, res.lastIndexOf(")"));
+                JSONObject addJson = JSON.parseObject(strAddrs);
+                JSONObject regeocodeObject = (null != addJson ? addJson.getJSONObject(regeoKey) : null);
+                res = (null != regeocodeObject ? regeocodeObject.getString(addressKey) : "");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return res;
+        }
+        return res;
+    }
+
+    public static void main(String[] args) {
+        String res = getAddressName("118.879289,38.052237");
+        System.out.println(res);
+    }
+}

+ 114 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/PasswordUtils.java

@@ -0,0 +1,114 @@
+package com.sckw.core.utils;
+
+import java.security.MessageDigest;
+import java.util.UUID;
+
+/**
+ * 密码工具类
+ * @author Louis
+ * @date Sep 1, 2018
+ */
+public class PasswordUtils {
+    public static final int HASH_INTERATIONS = 1024;
+    public static final int SALT_SIZE = 8;
+
+    /**
+     * 匹配密码
+     * @param salt 盐
+     * @param rawPass 明文
+     * @param encPass 密文
+     * @return
+     */
+    public static boolean matches(String salt, String rawPass, String encPass) {
+        return new EncryptionUtil(salt).matches(encPass, rawPass);
+    }
+
+    /**
+     * 明文密码加密
+     * @param rawPass 明文
+     * @param salt
+     * @return
+     */
+    public static String encode(String rawPass, String salt) {
+        return new EncryptionUtil(salt).encode(rawPass);
+    }
+
+    /**
+     * 获取加密盐
+     * @return
+     */
+    public static String getSalt() {
+        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 20);
+    }
+
+    /**
+     * MD5加密
+     * @param inStr 明文
+     * @return 32位密文
+     */
+    public static String md5(String inStr) {
+        MessageDigest md5 = null;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            byte[] byteArray = inStr.getBytes("UTF-8");
+            byte[] md5Bytes = md5.digest(byteArray);
+            StringBuffer hexValue = new StringBuffer();
+            for (int i = 0; i < md5Bytes.length; i++) {
+                int val = ((int) md5Bytes[i]) & 0xff;
+                if (val < 16) {
+                    hexValue.append("0");
+                }
+                hexValue.append(Integer.toHexString(val));
+            }
+            return hexValue.toString();
+        } catch (Exception e) {
+            System.out.println(e.toString());
+            e.printStackTrace();
+            return "";
+        }
+    }
+
+    /**
+     * md5密码校验
+     * @param rawPass
+     * @param encPass
+     * @return
+     */
+    public static boolean matchesMD5(String rawPass, String encPass){
+		if(md5(rawPass).equals(encPass)){
+			return true;
+		}else {
+			return false;
+		}
+	}
+
+    /**
+     * 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash
+     */
+    public static String entryptPassword(String plainPassword) {
+	  byte[] salt = Digests.generateSalt(SALT_SIZE);
+	  byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
+	  return Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);
+    }
+
+    /**
+     * 验证密码
+     * @param plainPassword 明文密码
+     * @param password 密文密码
+     * @return 验证成功返回true
+     */
+    public static boolean validatePassword(String plainPassword, String password) {
+	  byte[] salt = Encodes.decodeHex(password.substring(0,16));
+	  byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
+	  return password.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword));
+    }
+
+    public static void main(String[] args){
+      String password =  PasswordUtils.entryptPassword( PasswordUtils.md5("123456"));
+      String md5 = PasswordUtils.md5("123456");
+	  System.out.println(password);
+	  System.out.println(md5);
+	  System.out.println(validatePassword(md5, password));
+
+    }
+}

+ 170 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/ReflectionUtils.java

@@ -0,0 +1,170 @@
+package com.sckw.core.utils;
+
+import com.sckw.core.utils.StringUtils;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * 反射相关辅助方法
+ * @author zk
+ * @date Aug 19, 2018
+ */
+public class ReflectionUtils {
+
+	private static final String GETTER_PREFIX = "get";
+	/**
+	 * 点
+	 */
+	public static final String DOT = ".";
+	/**
+	 * 根据方法名调用指定对象的方法
+	 * @param object 要调用方法的对象
+	 * @param method 要调用的方法名
+	 * @param args 参数对象数组
+	 * @return
+	 */
+	public static Object invoke(Object object, String method, Object... args) {
+		Object result = null;
+		Class<? extends Object> clazz = object.getClass();
+		Method queryMethod = getMethod(clazz, method, args);
+		if(queryMethod != null) {
+			try {
+				result = queryMethod.invoke(object, args);
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+			} catch (IllegalArgumentException e) {
+				e.printStackTrace();
+			} catch (InvocationTargetException e) {
+				e.printStackTrace();
+			}
+		} else {
+			try {
+				throw new NoSuchMethodException(clazz.getName() + " 类中没有找到 " + method + " 方法。");
+			} catch (NoSuchMethodException e) {
+				e.printStackTrace();
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * 根据方法名和参数对象查找方法
+	 * @param clazz
+	 * @param name
+	 * @param args 参数实例数据
+	 * @return
+	 */
+	public static Method getMethod(Class<? extends Object> clazz, String name, Object[] args) {
+		Method queryMethod = null;
+		Method[] methods = clazz.getMethods();
+		for(Method method:methods) {
+			if(method.getName().equals(name)) {
+				Class<?>[] parameterTypes = method.getParameterTypes();
+				if(parameterTypes.length == args.length) {
+					boolean isSameMethod = true;
+					for(int i=0; i<parameterTypes.length; i++) {
+						Object arg = args[i];
+						if(arg == null) {
+							arg = "";
+						}
+						if(!parameterTypes[i].equals(args[i].getClass())) {
+							isSameMethod = false;
+						}
+					}
+					if(isSameMethod) {
+						queryMethod = method;
+						break ;
+					}
+				}
+			}
+		}
+		return queryMethod;
+	}
+	/**
+	 * 调用Getter方法.
+	 * 支持多级,如:对象名.对象名.方法
+	 */
+	public static Object invokeGetter(Object obj, String propertyName) {
+		Object object = obj;
+		for (String name : StringUtils.splitStr(propertyName, DOT)){
+			String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+			object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+		}
+		return object;
+	}
+
+	/**
+	 * 直接调用对象方法, 无视private/protected修饰符.
+	 * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
+	 * 同时匹配方法名+参数类型,
+	 */
+	public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+									  final Object[] args) {
+		Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+		if (method == null) {
+			throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
+		}
+
+		try {
+			return method.invoke(obj, args);
+		} catch (Exception e) {
+			throw convertReflectionExceptionToUnchecked(e);
+		}
+	}
+
+	/**
+	 * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+	 * 如向上转型到Object仍无法找到, 返回null.
+	 * 匹配函数名+参数类型。
+	 *
+	 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
+	 */
+	public static Method getAccessibleMethod(final Object obj, final String methodName,
+											 final Class<?>... parameterTypes) {
+		//Validate.notNull(obj, "object can't be null");
+		//Validate.notBlank(methodName, "methodName can't be blank");
+		if (obj == null) {
+			return null;
+		}
+		if (StringUtils.isBlank(obj)){
+			return null;
+		}
+
+		for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
+			try {
+				Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+				makeAccessible(method);
+				return method;
+			} catch (NoSuchMethodException e) {
+				// Method不在当前类定义,继续向上转型
+				continue;// new add
+			}
+		}
+		return null;
+	}
+	/**
+	 * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
+	 */
+	public static void makeAccessible(Method method) {
+		if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))) {
+			if(!method.isAccessible()){
+			method.setAccessible(true);
+			}
+		}
+	}
+	/**
+	 * 将反射时的checked exception转换为unchecked exception.
+	 */
+	public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
+		if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+				|| e instanceof NoSuchMethodException) {
+			return new IllegalArgumentException(e);
+		} else if (e instanceof InvocationTargetException) {
+			return new RuntimeException(((InvocationTargetException) e).getTargetException());
+		} else if (e instanceof RuntimeException) {
+			return (RuntimeException) e;
+		}
+		return new RuntimeException("Unexpected Checked Exception.", e);
+	}
+}

+ 52 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/SensitiveJsonSerializer.java

@@ -0,0 +1,52 @@
+package com.sckw.core.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.sckw.core.annotation.Sensitive;
+import com.sckw.core.model.enums.SensitiveStrategy;
+import com.sckw.core.service.SensitiveService;
+import org.springframework.beans.BeansException;
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * 数据脱敏json序列化工具
+ * @author zk
+ */
+//@Slf4j
+public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
+
+    private SensitiveStrategy strategy;
+
+    @Override
+    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        try {
+            SensitiveService sensitiveService = SpringUtils.getBean(SensitiveService.class);
+            if (ObjectUtil.isNotNull(sensitiveService) && sensitiveService.isSensitive()) {
+                gen.writeString(strategy.desensitizer().apply(value));
+            } else {
+                gen.writeString(value);
+            }
+        } catch (BeansException e) {
+            e.printStackTrace();
+            //log.error("脱敏实现不存在, 采用默认处理 => {}", e.getMessage());
+            System.out.println("脱敏实现不存在, 采用默认处理 => {}"+ e.getMessage());
+            gen.writeString(value);
+        }
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
+        Sensitive annotation = property.getAnnotation(Sensitive.class);
+        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
+            this.strategy = annotation.strategy();
+            return this;
+        }
+        return prov.findValueSerializer(property.getType(), property);
+    }
+}

+ 70 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/SpringUtils.java

@@ -0,0 +1,70 @@
+package com.sckw.core.utils;
+
+import cn.hutool.extra.spring.SpringUtil;
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * spring工具类
+ * @author
+ */
+public final class SpringUtils extends SpringUtil {
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name) {
+        return getBeanFactory().containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
+     * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     *
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker) {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取spring上下文
+     */
+    public static ApplicationContext context() {
+        return getApplicationContext();
+    }
+
+}

+ 701 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/StringUtils.java

@@ -0,0 +1,701 @@
+package com.sckw.core.utils;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @Description 自测公共处理类
+ * @Author zk
+ * @Date 2019/5/13 0013
+ */
+public class StringUtils {
+
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+    /** 下划线 */
+    private static final char SEPARATOR_CHAR = '_';
+    /** 下划线 */
+    private static final String SEPARATOR_STRING = "_";
+    /** 加密字符 */
+    public static final String HASH_ALGORITHM = "SHA-1";
+    /**${xxx}**/
+    public static final Pattern pattern = Pattern.compile("(\\$\\{)([\\w]+)(\\})");
+
+    /**
+     * 判断字符串是否为空
+     * @param str 源字符串
+     * @author dengyinghui
+     * @date 2018/11/12
+     * @return
+     */
+    public static boolean validatorEmpty(String str){
+        if(str != null && !"".equals(str)){
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 判空操作(空)
+     * @param str
+     * @return
+     */
+    public static boolean isBlank(Object str) {
+        String value = objectStr(str);
+        return value == null || "".equals(value) || "null".equals(value);
+    }
+
+    /**
+     * 判空操作(空)
+     * @param value
+     * @return
+     */
+    public static boolean isBlank(String value) {
+        return value == null || "".equals(value) || "null".equals(value);
+    }
+
+    /**
+     * 判空操作(非空)
+     * @param str
+     * @return
+     */
+    public static boolean isNotBlank(Object str) {
+        String value = objectStr(str);
+        return value != null && !"".equals(value) && !"null".equals(value);
+    }
+
+    /**
+     * 判空操作(非空)
+     * @param value
+     * @return
+     */
+    public static boolean isNotBlank(String value) {
+        return value != null && !"".equals(value) && !"null".equals(value);
+    }
+
+    /**
+     * 获取uuid
+     * @return
+     */
+    public static String uuid() {
+        return UUID.randomUUID().toString().replaceAll("-", "");
+    }
+
+    /**
+     * 获取参数不为空值
+     *
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     *
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     *
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     *
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     *
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     *
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     *
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     *
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }*/
+
+    /**
+     * 下划线转驼峰命名
+     */
+    public static String toUnderScoreCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            boolean nextUpperCase = true;
+
+            if (i < (s.length() - 1))
+            {
+                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
+            }
+
+            if ((i > 0) && Character.isUpperCase(c))
+            {
+                if (!upperCase || !nextUpperCase)
+                {
+                    sb.append(SEPARATOR_CHAR);
+                }
+                upperCase = true;
+            }
+            else
+            {
+                upperCase = false;
+            }
+
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     *
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 字符串转数组
+     * @param params 字符串
+     * @param regex 截取字符
+     * @return
+     */
+    public static String [] splitStr(String params, String regex){
+        regex = StringUtils.isNotBlank(regex) ? regex : ",";
+        return StringUtils.isNotBlank(params) ? params.split(regex) : new String[]{};
+    }
+
+    /**
+     * Object对象转字符串
+     * @param obj
+     * @return
+     */
+    public static String objectStr(Object obj){
+        if (obj != null) {
+            return obj.toString();
+        }
+        return null;
+    }
+
+    public static String trimNull(Object str) {
+        if (str == null) {
+            return "";
+        } else {
+            return str instanceof String ? ((String)str).trim() : str.toString();
+        }
+    }
+
+    /**
+     * 解析出url请求的路径,包括页面
+     * @param strURL url地址
+     * @return url路径
+     */
+    public static String urlPage(String strURL) {
+        String strPage = null;
+        String[] arrSplit = null;
+        strURL = strURL.trim().toLowerCase();
+        arrSplit = strURL.split("[?]");
+        if (strURL.length() > 0) {
+            if (arrSplit.length > 1) {
+                if (arrSplit[0] != null) {
+                    strPage = arrSplit[0];
+                }
+            }
+        }
+        return strPage;
+    }
+
+    /**
+     * 去掉url中的路径,留下请求参数部分
+     *
+     * @param strURL url地址
+     * @return url请求参数部分
+     */
+    private static String truncateUrlPage(String strURL) {
+        String strAllParam = null;
+        String[] arrSplit = null;
+        strURL = strURL.trim().toLowerCase();
+        arrSplit = strURL.split("[?]");
+        if (strURL.length() > 1) {
+            if (arrSplit.length > 1) {
+                if (arrSplit[1] != null) {
+                    strAllParam = arrSplit[1];
+                }
+            }
+        }
+        return strAllParam;
+    }
+
+    /**
+     * 解析出url参数中的键值对
+     * 如 "index.jsp?Action=del&id=123",解析出Action:del,id:123存入map中
+     *
+     * @param url url地址
+     * @return url请求参数部分
+     */
+    public static Map<String, String> urlRequest(String url) {
+        Map<String, String> mapRequest = new HashMap<String, String>();
+        String[] arrSplit = null;
+        String strUrlParam = truncateUrlPage(url);
+        if (strUrlParam == null) {
+            return mapRequest;
+        }
+        //每个键值为一组 www.2cto.com
+        arrSplit = strUrlParam.split("[&]");
+        for (String strSplit : arrSplit) {
+            String[] arrSplitEqual = null;
+            arrSplitEqual = strSplit.split("[=]");
+            //解析出键值
+            if (arrSplitEqual.length > 1) {
+                //正确解析
+                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
+            } else {
+                if (arrSplitEqual[0] != "") {
+                    //只有参数没有值,不加入
+                    mapRequest.put(arrSplitEqual[0], "");
+                }
+            }
+        }
+        return mapRequest;
+    }
+
+    /**
+     * 解析出url参数中的键值对
+     * 如 "Action=del&id=123",解析出Action:del,id:123存入map中
+     *
+     * @param strUrlParam url地址
+     * @return url请求参数部分
+     */
+    public static Map<String, String> urlParams(String strUrlParam) {
+        Map<String, String> mapRequest = new HashMap<String, String>();
+        String[] arrSplit = null;
+        if (strUrlParam == null) {
+            return mapRequest;
+        }
+        //每个键值为一组 www.2cto.com
+        arrSplit = strUrlParam.split("[&]");
+        for (String strSplit : arrSplit) {
+            String[] arrSplitEqual = null;
+            arrSplitEqual = strSplit.split("[=]");
+            //解析出键值
+            if (arrSplitEqual.length > 1) {
+                //正确解析
+                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
+            } else {
+                if (arrSplitEqual[0] != "") {
+                    //只有参数没有值,不加入
+                    mapRequest.put(arrSplitEqual[0], "");
+                }
+            }
+        }
+        return mapRequest;
+    }
+
+    /**
+     * 替换掉HTML标签方法
+     */
+    public static String replaceHtml(String html) {
+        if (isBlank(html)) {
+            return "";
+        }
+        String regEx = "<.+?>";
+        Pattern p = Pattern.compile(regEx);
+        Matcher m = p.matcher(html);
+        String s = m.replaceAll("");
+        return s;
+    }
+
+    /**
+     * 替换为手机识别的HTML,去掉样式及属性,保留回车。
+     *
+     * @param html
+     * @return
+     */
+    public static String replaceMobileHtml(String html) {
+        if (html == null) {
+            return "";
+        }
+        return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
+    }
+
+    /**
+     * 转换为Double类型
+     */
+    public static Double toDouble(Object val){
+        if (val == null){
+            return 0D;
+        }
+        try {
+            return Double.valueOf(trim(val.toString()));
+        } catch (Exception e) {
+            return 0D;
+        }
+    }
+
+    /**
+     * 转换为Float类型
+     */
+    public static Float toFloat(Object val) {
+        return toDouble(val).floatValue();
+    }
+
+        /**
+         * 转换为Long类型
+         */
+    public static Long toLong(Object val){
+        return toDouble(val).longValue();
+    }
+
+    /**
+     * 转换为Integer类型
+     */
+    public static Integer toInteger(Object val){
+        return toLong(val).intValue();
+    }
+
+    /**
+     * Object转String
+     * @param val 源字符串
+     * @author dengyinghui
+     * @date 2018/2/27
+     * @return
+     */
+    public static String valueOf(Object val){
+        if(val == null){
+            return "";
+        } else{
+            return String.valueOf(val);
+        }
+    }
+
+    private static String toHex(byte[] bytes) {
+        final char[] hexDigits = "0123456789ABCDEF".toCharArray();
+        StringBuilder ret = new StringBuilder(bytes.length * 2);
+        for (int i=0; i<bytes.length; i++) {
+            ret.append(hexDigits[(bytes[i] >> 4) & 0x0f]);
+            ret.append(hexDigits[bytes[i] & 0x0f]);
+        }
+        return ret.toString();
+    }
+
+    /**
+     * 替换字符串${xxxx}
+     * @param content 账号创建成功,欢迎使用危品汇!登录账号:${account},默认密码:${pwd}!
+     * @param regex 需要替换的字符(account)
+     * @param replacement 替换值(173xxxxxxxx)
+     * @return
+     */
+    public static String replace(String content, String regex, String replacement){
+        if (content == null || regex == null || replacement == null){
+            return null;
+        }
+        Matcher matcher = pattern.matcher(content);
+        StringBuffer strBuf = new StringBuffer();
+        while (matcher.find()) {
+            String group = matcher.group().replace("${", "").replace("}", "");
+            if (group.equals(regex)){
+                matcher.appendReplacement(strBuf, replacement);
+                return matcher.appendTail(strBuf).toString();
+            }
+        }
+        return matcher.appendTail(strBuf).toString();
+    }
+
+    /**
+     * 替换字符串${xxxx}
+     * @param content  账号创建成功,欢迎使用危品汇!登录账号:${account},默认密码:${pwd}!
+     * @param params {"account":"xxxxx", "pwd":"xxxx"}
+     * @return
+     */
+    public static String replace1(String content, Map<String, Object> params){
+        if (content == null || params == null){
+            return null;
+        }
+
+        Matcher matcher = pattern.matcher(content);
+        StringBuffer strBuf = new StringBuffer();
+        while(matcher.find()){
+            String group = matcher.group().replace("${", "").replace("}", "");
+            if (params.get(group) != null){
+                String replacement = StringUtils.objectStr(params.get(group));
+                matcher.appendReplacement(strBuf, replacement);
+            }
+        }
+        matcher.appendTail(strBuf);
+        return strBuf.toString();
+    }
+
+    public static String capitalize(final String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+
+        final int firstCodepoint = str.codePointAt(0);
+        final int newCodePoint = Character.toTitleCase(firstCodepoint);
+        if (firstCodepoint == newCodePoint) {
+            // already capitalized
+            return str;
+        }
+
+        final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
+        int outOffset = 0;
+        newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
+        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
+            final int codepoint = str.codePointAt(inOffset);
+            newCodePoints[outOffset++] = codepoint; // copy the remaining ones
+            inOffset += Character.charCount(codepoint);
+        }
+        return new String(newCodePoints, 0, outOffset);
+    }
+
+    public static void main(String[] args){
+        Map<String, Object> param = new HashMap();
+        param.put("account", "17358629955");
+        param.put("pwd", "123456");
+        String template = "账号创建成功,欢迎使用危品汇!登录账号:${account},默认密码:${pwd}!";
+        for(String key : param.keySet()){
+            template = StringUtils.replace(template, key, StringUtils.objectStr(param.get(key)));
+        }
+        System.out.println(template);
+
+        Map<String, Object> m = new HashMap<>();
+        m.put("account", "han");
+        m.put("pwd", "zhong");
+        System.out.println( replace1(template, m));
+    }
+}

+ 171 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/workerUtils.java

@@ -0,0 +1,171 @@
+package com.sckw.core.utils;
+
+import org.w3c.dom.CDATASection;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class workerUtils {
+
+    /**
+     * 开始时间截 (2023-05-26)
+     */
+    private final long twepoch = 1685030400000L;
+
+    /**
+     * 机器id所占的位数
+     */
+    private final long workerIdBits = 5L;
+
+    /**
+     * 数据标识id所占的位数
+     */
+    private final long datacenterIdBits = 5L;
+
+    /**
+     * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
+     */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /**
+     * 支持的最大数据标识id,结果是31
+     */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /**
+     * 序列在id中占的位数
+     */
+    private final long sequenceBits = 12L;
+
+    /**
+     * 机器ID向左移12位
+     */
+    private final long workerIdShift = sequenceBits;
+
+    /**
+     * 数据标识id向左移17位(12+5)
+     */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /**
+     * 时间截向左移22位(5+5+12)
+     */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /**
+     * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /**
+     * 工作机器ID(0~31)
+     */
+    private long workerId;
+
+    /**
+     * 数据中心ID(0~31)
+     */
+    private long datacenterId;
+
+    /**
+     * 毫秒内序列(0~4095)
+     */
+    private long sequence = 0L;
+
+    /**
+     * 上次生成ID的时间截
+     */
+    private long lastTimestamp = -1L;
+
+    /**
+     * 构造函数
+     * @param workerId     工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public workerUtils(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+        // 如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            // 毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        // 时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+        // 上次生成ID的时间截
+        lastTimestamp = timestamp;
+        // 移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    public static void main(String[] args) throws InterruptedException {
+        workerUtils idWorker = new workerUtils(0, 0);
+        for (int i = 0; i < 10; i++) {
+            long id = idWorker.nextId();
+            Thread.sleep(1);
+            System.out.println(id);
+        }
+
+        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
+        //有一个字符串表示的日期
+        String str = "2023-05-26";
+        Date date = null;
+        try {
+            date = formater.parse(str);
+            System.out.println(date.getTime());
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+
+    }
+}

+ 83 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/constant/HttpStatus.java

@@ -0,0 +1,83 @@
+package com.sckw.core.web.constant;
+
+/**
+ * @Description 自定义接口请求状态码(和http请求码无关)
+ * @Author zk
+ * @Date 2019/5/13 0013
+ */
+public class HttpStatus {
+
+    /**成功状态码*/
+    public static final int SUCCESS_CODE = 60200;
+    /**成功提示信息*/
+    public static final String SUCCESS_MESSAGE = "success";
+
+    /**未登录状态码*/
+    public static final int UN_LOGIN_CODE = 60300;
+    /**未登录提示信息*/
+    public static final String UN_LOGIN_MESSAGE = "您尚未登录,请先登录!";
+
+    /**访问权限状态码*/
+    public static final int AUTHORITY_NO_CODE = 60403;
+
+    /**全局异常状态码*/
+    public static final int GLOBAL_EXCEPTION_CODE = 60500;
+    /**全局异常提示信息*/
+    public static final String GLOBAL_EXCEPTION_MESSAGE = "攻城狮正在拼命优化,请您稍候再试!";
+
+    /**参数缺失状态码*/
+    public static final int PARAMETERS_MISSING_CODE = 60600;
+
+    /**其他自定义状态码*/
+    public static final int CODE_60601 = 60601;
+    public static final int CODE_60602 = 60602;
+    public static final int CODE_60603 = 60603;
+    public static final int CODE_60604 = 60604;
+    public static final int CODE_60605 = 60605;
+    public static final int CODE_60606 = 60606;
+    public static final int CODE_60607 = 60607;
+    public static final int CODE_60608 = 60608;
+    public static final int CODE_60609 = 60609;
+
+    /**版本号和接口版本不对称状态码*/
+    public static final int VERSION_NOT_NEWEST_CODE = 60700;
+    /**版本号和接口版本不对称提示信息*/
+    public static final String VERSION_NOT_NEWEST_MESSAGE = "当前版本较低,请更新升级后再试!";
+
+
+    /**参数格式不正确状态码*/
+    public static final int PARAMETERS_PATTERN_ERROR_CODE = 60800;
+    /**参数格式不正确提示信息*/
+    public static final String PARAMETERS_PATTERN_ERROR_MESSAGE = "参数格式不正确";
+
+    /**账号在别处登录状态码*/
+    public static final int ACCOUNT_OTHER_LOGIN_CODE = 60900;
+    /**账号在别处登录提示信息*/
+    public static final String ACCOUNT_OTHER_LOGIN_MESSAGE = "您的账号已在其他设备登录,如非本人操作,请及时修改密码!";
+
+
+    /**token无效状态码*/
+    public static final int TOKEN_INVALID_CODE = 60901;
+    /**token无效提示信息*/
+    public static final String TOKEN_INVALID_MESSAGE = "由于您一段时间未操作,为了您的账户安全,请重新登录!";
+
+    /**请求超过次数*/
+    public static final int FREQUENCY_OUT = 60902;
+    /**请求超过次数提示信息*/
+    public static final String FREQUENCY_OUT_MESSAGE = "您的操作过于频繁,请刷新浏览器或稍候重试!";
+
+    /**审核状态状态码*/
+    public static final int ACCOUNT_AUDIT_CODE = 60903;
+    /**审核状态状提示信息*/
+    public static final String ACCOUNT_AUDIT_MESSAGE = "您所属企业企业资质审批未通过,请核实确认!";
+
+    /**微信账号未绑定态码*/
+    public static final int WECHAR_BIND_CODE = 60904;
+    /**微信账号未绑定提示信息*/
+    public static final String WECHAR_BIND_MESSAGE = "您的微信还未绑定危品汇账号!";
+
+    /**
+     * 自定义状态码,该状态码没有特殊含义,只是提供一个状态标识(目前提供9个,可自行扩展)
+     */
+    public static final int CODE_10301 = 10301;
+}

+ 17 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/constant/RequestConstant.java

@@ -0,0 +1,17 @@
+package com.sckw.core.web.constant;
+
+/**
+ * @Description web请求常量
+ * @Author zk
+ * @Date 2022/6/16
+ */
+public class RequestConstant {
+
+    /**请求头token*/
+    public static final String TOKEN = "Access-Token";
+    /**客户终端类型*/
+    public static final String CLIENT_TYPE = "Client-Type";
+    /**系统类型*/
+    public static final String SYSTEM_TYPE = "System-Type";
+
+}

+ 95 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/LoginEntHolder.java

@@ -0,0 +1,95 @@
+package com.sckw.core.web.context;
+
+import com.sckw.core.web.model.LoginEntInfo;
+
+/**
+ * 当前登录用户企业的临时保存容器
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+public class LoginEntHolder {
+    private static final ThreadLocal<LoginEntInfo> LONGIN_ENT_HOLDER = new ThreadLocal<LoginEntInfo>();
+
+    /**
+     * 赋值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void set(LoginEntInfo loginEnterpriseInfo) {
+        LONGIN_ENT_HOLDER.set(loginEnterpriseInfo);
+    }
+
+    /**
+     * 取值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static LoginEntInfo get() {
+        return LONGIN_ENT_HOLDER == null ? null : LONGIN_ENT_HOLDER.get();
+    }
+
+    /**
+     * 删除保存的用户
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void remove() {
+        LONGIN_ENT_HOLDER.remove();
+    }
+
+    /**
+     * 用户所属企业id
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getEntId(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getId();
+    }
+
+    /**
+     * 用户所属企业名称
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getFirmName(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getFirmName();
+    }
+
+    /**
+     * 用户类型
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getUserType(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getUserType();
+    }
+
+    /**
+     * 资料审批状态(1通过、0未审批、2未通过、3审批中)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getApproval(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getApproval();
+    }
+
+    /**
+     * 用户状态(-1删除、0正常、1已锁)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getStatus(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getStatus();
+    }
+
+    /**
+     * 用户分支类型
+     * @author zk
+     * @date 2021/3/16 11:24
+     **/
+    public static Integer getBranchType(){
+        return LONGIN_ENT_HOLDER.get() == null ? null : LONGIN_ENT_HOLDER.get().getBranchType();
+    }
+
+
+}

+ 140 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/LoginUserHolder.java

@@ -0,0 +1,140 @@
+package com.sckw.core.web.context;
+
+import com.sckw.core.web.model.LoginUserInfo;
+
+/**
+ * 当前登录用户的临时保存容器
+ * @Author zk
+ * @date 2020/04/13 0021
+ */
+public class LoginUserHolder {
+
+    private static final ThreadLocal<LoginUserInfo> LONGIN_USER_HOLDER = new ThreadLocal<LoginUserInfo>();
+
+    /**
+     * 赋值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void set(LoginUserInfo loginUserInfo) {
+        LONGIN_USER_HOLDER.set(loginUserInfo);
+    }
+
+    /**
+     * 取值
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static LoginUserInfo get() {
+        return LONGIN_USER_HOLDER == null ? null : LONGIN_USER_HOLDER.get();
+    }
+
+    /**
+     * 删除保存的用户
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static void remove() {
+        LONGIN_USER_HOLDER.remove();
+    }
+
+    /**
+     * 用户id
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getUserId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getId();
+    }
+
+    /**
+     * 用户所属系统
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getSystemType(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getSystemType();
+    }
+
+    /**
+     * 用户账号
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getAccount(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getAccount();
+    }
+
+    /**
+     * 用户姓名
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getUserName(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getUserName();
+    }
+
+    /**
+     * 用户电话
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getTelephone(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getTelephone();
+    }
+
+    /**
+     * 是否主账号(0是/1否)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getIsMain(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getIsMain();
+    }
+
+    /**
+     * 用户账号状态(0正常/1锁定)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Integer getStatus(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getStatus();
+    }
+
+    /**
+     * 用户所属企业
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getEntId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getEntId();
+    }
+
+    /**
+     * 用户登录终端
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getClientType(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getClientType();
+    }
+
+    /**
+     * 用户机构
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static Long getDeptId(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getDeptId();
+    }
+
+    /**
+     * (司机)
+     * @author zhaokang
+     * @Date 2020/04/13 0021
+     */
+    public static String getUserIds(){
+        return LONGIN_USER_HOLDER.get() == null ? null : LONGIN_USER_HOLDER.get().getUserIds();
+    }
+
+}

+ 37 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/context/SignBase.java

@@ -0,0 +1,37 @@
+package com.sckw.core.web.context;
+
+import lombok.Data;
+import java.util.Map;
+
+/**
+ * @author zk
+ * @description 获取铭文请求参数
+ * @date 2020/08/15 16:11:10
+ */
+@Data
+public class SignBase {
+    /**
+     * 铭文
+     */
+    private String sign;
+
+    /**
+     * 公钥
+     */
+    private String accessKey;
+
+    /**
+     * 私钥
+     */
+    private String accessSecret;
+
+    /**
+     * 时间戳
+     */
+    private Long timeStamp;
+
+    /**
+     * 请求参数
+     */
+    private Map<String, Object> params;
+}

+ 47 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginBase.java

@@ -0,0 +1,47 @@
+package com.sckw.core.web.model;
+
+import lombok.Data;
+
+/**
+ * @author zk
+ * @description 登录信息
+ * @date 2020/06/12 09:06:14
+ */
+@Data
+public class LoginBase {
+
+    /**
+     * 账号
+     */
+    private String account;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 验证码
+     */
+    private String captcha;
+
+    /**
+     * 系统类型(1 运营管理中心/2 运营管理中心/3 官网/4 司机应用)
+     */
+    private String systemType;
+
+    /**
+     * 客户端类型(ios 苹果设备/android 安卓设备/pc 浏览器/pc-background 管理系统)
+     */
+    private String clientType;
+
+    /**
+     * 登录方式1 账号密码登录/2账号短信登录/3单账号登录
+     */
+    private int loginMethod;
+
+    /**
+     * 用户类型(1 表示官网 )
+     */
+    private String userType;
+}

+ 52 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginEntInfo.java

@@ -0,0 +1,52 @@
+package com.sckw.core.web.model;
+
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 登录中的用户企业信息
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+@Data
+public class LoginEntInfo {
+    /**
+     * 用户所属企业id
+     */
+    private Long id;
+    /**
+     * 用户所属企业名称
+     */
+    private String firmName;
+    /**
+     * 用户类型
+     */
+    private int userType;
+    /**
+     * 用户分支类型(1承运商企业、2车主)
+     */
+    private int branchType;
+    /**
+     * 资料审批状态(0未审批、1通过、2未通过、3审批中)
+     */
+    private int approval;
+    /**
+     * 用户状态(-1删除、0正常、1已锁)
+     */
+    private int status;
+
+    /**
+     * 交通安培账号状态
+     */
+    private int jtaqStatus;
+
+    /**
+     * 交通安培账号删除标识
+     */
+    private int jtaqDelFlag;
+
+    /**
+     * 企业注册时间
+     */
+    private Date regTime;
+}

+ 74 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/model/LoginUserInfo.java

@@ -0,0 +1,74 @@
+package com.sckw.core.web.model;
+
+import lombok.Data;
+
+/**
+ * 登录中的用户信息
+ * @Author zhaokang
+ * @date 2020/04/13 0021
+ */
+@Data
+public class LoginUserInfo {
+    /**
+     * 用户id
+     */
+    private Long id;
+    /**
+     * 用户所属系统
+     */
+    private Integer systemType;
+    /**
+     * 用户账号
+     */
+    private String account;
+    /**
+     * 用户姓名
+     */
+    private String userName;
+    /**
+     * 用户电话
+     */
+    private String telephone;
+    /**
+     *是否主账号(0是/1否)
+     */
+    private int isMain;
+    /**
+     *用户账号状态(0正常/1锁定)
+     */
+    private int status;
+    /**
+     * 用户所属企业id
+     */
+    private Long entId;
+    /**
+     * 用户登录终端
+     */
+    private String clientType;
+    /**
+     * 用户所属机构id
+     */
+    private Long deptId;
+    /**
+     * (司机)
+     */
+    private String userIds;
+
+
+    public LoginUserInfo() {
+    }
+
+    public LoginUserInfo(Long id, Integer systemType, String account, String userName, String telephone,
+                         int isMain, int status, Long entId, String clientType, Long deptId) {
+        this.id = id;
+        this.systemType = systemType;
+        this.account = account;
+        this.userName = userName;
+        this.telephone = telephone;
+        this.isMain = isMain;
+        this.status = status;
+        this.entId = entId;
+        this.clientType = clientType;
+        this.deptId = deptId;
+    }
+}

+ 63 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/response/HttpResult.java

@@ -0,0 +1,63 @@
+package com.sckw.core.web.response;
+
+import com.sckw.core.web.constant.HttpStatus;
+import lombok.Data;
+
+/**
+ * HTTP结果封装
+ * @author zk
+ * @date Oct 29, 2018
+ */
+@Data
+public class HttpResult {
+
+	private int code = HttpStatus.SUCCESS_CODE;
+	private String msg = HttpStatus.SUCCESS_MESSAGE;
+	private Object data;
+
+	public static HttpResult error() {
+		return error(HttpStatus.GLOBAL_EXCEPTION_CODE, HttpStatus.GLOBAL_EXCEPTION_MESSAGE);
+	}
+	
+	public static HttpResult error(String msg) {
+		return error(HttpStatus.GLOBAL_EXCEPTION_CODE, msg);
+	}
+	
+	public static HttpResult error(int code, String msg) {
+		HttpResult r = new HttpResult();
+		r.setCode(code);
+		r.setMsg(msg);
+		return r;
+	}
+
+	public static HttpResult error(int code, String msg, Object data) {
+		HttpResult r = new HttpResult();
+		r.setCode(code);
+		r.setMsg(msg);
+		r.setData(data);
+		return r;
+	}
+
+	public static HttpResult ok() {
+		return new HttpResult();
+	}
+
+	public static HttpResult ok(String msg) {
+		HttpResult r = new HttpResult();
+		r.setMsg(msg);
+		return r;
+	}
+	
+	public static HttpResult ok(Object data) {
+		HttpResult r = new HttpResult();
+		r.setData(data);
+		return r;
+	}
+
+	public static HttpResult ok(String msg, Object data) {
+		HttpResult r = new HttpResult();
+		r.setMsg(msg);
+		r.setData(data);
+		return r;
+	}
+}

+ 58 - 0
sckw-common/sckw-common-datasource/pom.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-datasource</artifactId>
+    <version>1.0.0</version>
+
+    <description>多数据源</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <mysql.version>8.0.30</mysql.version>
+        <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
+        <dynamic-datasource.version>3.6.1</dynamic-datasource.version>
+        <latest.release.version>5.2.0</latest.release.version>
+    </properties>
+
+
+    <dependencies>
+        <!--mysql-->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+        </dependency>
+
+        <!--mybatis-plus 依赖-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <!--多数据源-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+            <version>${dynamic-datasource.version}</version>
+        </dependency>
+
+        <!--ShardingSphere-JDBC-->
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
+            <version>${latest.release.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 28 - 0
sckw-common/sckw-common-elasticsearch/pom.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-elasticsearch</artifactId>
+    <version>1.0.0</version>
+    <description>核心模块</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+
+    <dependencies>
+
+    </dependencies>
+
+</project>

+ 80 - 0
sckw-common/sckw-common-excel/pom.xml

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-excel</artifactId>
+    <version>1.0.0</version>
+    <description>核心模块</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <easyexcel.version>3.0.5</easyexcel.version>
+        <commons-io.version>2.11.0</commons-io.version>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <!--alibaba EasyExcel导入导出-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>${easyexcel.version}</version>
+        </dependency>
+        <!--cglib-->
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm</artifactId>
+                </exclusion>
+            </exclusions>
+            <version>3.3.0</version>
+        </dependency>
+        <!-- validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.springframework</groupId>-->
+<!--            <artifactId>spring-core</artifactId>-->
+<!--            <version>6.0.9</version>-->
+<!--        </dependency>-->
+        <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+<!--            <version>2.0.1</version>-->
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+            <version>10.1.7</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 24 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/ExcelContext.java

@@ -0,0 +1,24 @@
+package com.sckw.excel.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ *
+ * 导出的文件全局属性
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ExcelContext {
+
+    String fileName() default "";
+
+    String sheetName();
+
+    @Target({ElementType.TYPE})
+    @Retention(RetentionPolicy.RUNTIME)
+    @Documented
+    public @interface Query {
+        boolean combine() default false;
+    }
+}

+ 30 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/ExcelSelected.java

@@ -0,0 +1,30 @@
+package com.sckw.excel.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * easy导出下拉框注解
+ */
+
+/**
+ * 标注导出的列为下拉框类型,并为下拉框设置内容
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ExcelSelected {
+    /**
+     * 固定下拉内容
+     */
+    String[] source() default {};
+
+    /**
+     * 设置下拉框的起始行,默认为第二行
+     */
+    int firstRow() default 1;
+
+    /**
+     * 设置下拉框的结束行,默认为最后一行
+     */
+    int lastRow() default 0x10000;
+}

+ 39 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/Translate.java

@@ -0,0 +1,39 @@
+package com.sckw.excel.annotation;
+
+
+import java.lang.annotation.*;
+
+/**
+ *
+ * 对某个字段进行翻译
+ *
+ * 可以标注在类和方法上
+ * 1. 标注在类上:适用于对整个实体的指定字段进行翻译
+ * 2. 标注在方法上:适用于对方法的返回值中的data数据实体进行翻译
+ *
+ * 标注在类和方法上时,如果同时存在@Translates和@Translate,则@Translates会生效,@Translate不会生效
+ *
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(Translates.class)
+@Documented
+public @interface Translate {
+    /**
+     * 需要翻译的字段
+     */
+    String field();
+    /**
+     * 指定数据源
+     */
+
+    /**
+     * 字段值为字符串
+     */
+    boolean isString() default true;
+    /**
+     * 字段值为数组
+     */
+    boolean isArray() default false;
+}

+ 21 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/annotation/Translates.java

@@ -0,0 +1,21 @@
+package com.sckw.excel.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ *
+ * 组合注解
+ * 用于指定翻译多个字段
+ *
+ * @author liyue
+ * @version v1
+ * @create 2020-11-28 15:37:35
+ * @copyright
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Documented
+public @interface Translates {
+
+    Translate[] value();
+}

+ 82 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/common/FileType.java

@@ -0,0 +1,82 @@
+package com.sckw.excel.common;
+
+/**
+ * @description:    文件类型
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:02
+ */
+public class FileType {
+
+    public enum type {
+        /**
+         * 商品主档信息导入模板
+         */
+        REGISTERED(1, "商品主档信息导入模板.xlsx"),
+        /**
+         * 备案结果导入模板
+         */
+        LOGIN(2, "备案结果导入模板.xlsx"),
+        /**
+         * 商品分类导入模板
+         */
+        BIND(3, "商品分类导入模板.xlsx"),
+        /**
+         * 商品品牌导入模板
+         */
+        UPDATE(4, "商品品牌导入模板.xlsx"),
+        /**
+         * 入库单导入模板
+         */
+        SET(5, "入库单导入模板.xlsx"),
+        /**
+         * 调拨单导入模板
+         */
+        SET_PASSWORD(6, "调拨单导入模板.xlsx"),
+        /**
+         * 出库单导入模板
+         */
+        BANK(7, "出库单导入模板.xlsx");
+        private Integer code;
+        private String value;
+
+        type(Integer code, String value) {
+            this.code = code;
+            this.value = value;
+        }
+
+        public int getCode() {
+            return code;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setCode(Integer code) {
+            this.code = code;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+
+    public static String getValue(Integer code) {
+        for (type ele : type.values()) {
+            if (ele.getCode() == code) {
+                return ele.getValue();
+            }
+        }
+        return null;
+    }
+
+    public static int getCode(Integer code) {
+        for (type ele : type.values()) {
+            if (ele.getCode() == code) {
+                return ele.getCode();
+            }
+        }
+        return 0;
+    }
+}

+ 66 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/common/NumberConstant.java

@@ -0,0 +1,66 @@
+package com.sckw.excel.common;
+
+/**
+ * @description:    定义常量
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:02
+ **/
+public final class NumberConstant {
+    public static final int ZERO = 0;
+    public static final int ONE = 1;
+    public static final int TWO = 2;
+    public static final int THREE = 3;
+    public static final int FOUR = 4;
+    public static final int FIVE = 5;
+    public static final int SIX = 6;
+    public static final int SEVEN = 7;
+    public static final int EIGHT = 8;
+    public static final int NINE = 9;
+    public static final int TEN = 10;
+    public static final int TWELVE = 12;
+    public static final int THREETEEN = 13;
+    public static final int FOURTEEN = 14;
+    public static final int ONE_FIVE = 15;
+    public static final int SIXTEEN = 16;
+    public static final int EIGHTTEEN = 18;
+    public static final int NINETEEN = 19;
+    public static final int TWETY = 20;
+    public static final int TWETYTHREE = 23;
+    public static final int TWENTY_FOUR = 24;
+    public static final int TWENTY_SIX = 26;
+    public static final int THIRTY = 30;
+    public static final int THIRTY_TREE = 32;
+    public static final int FOURTY = 40;
+    public static final int FIFTY = 50;
+    public static final int EIGTY = 80;
+    public static final int ONE_ZERO_ZERO = 100;
+    public static final int ONE_ONE_ZERO = 110;
+    public static final int ONE_ZERO_ONE = 101;
+    public static final int ONE_ONE_ONE = 111;
+    public static final int ONE_TWO_ONE = 121;
+    public static final int ONE_TWO_EIGHT = 128;
+    public static final int ONE_THREE_THREE = 133;
+    public static final int TWO_HUNDRED = 200;
+    public static final int TWO_FIVE_FIVE = 255;
+    public static final int TWO_FIVE_SIX = 256;
+    public static final int FOUR_HUNDRED = 400;
+    public static final int FOUR_ZERO_ONE = 401;
+    public static final int THREE_HUNDRED = 300;
+    public static final int THREE_FIVE_ZERO = 350;
+    public static final int FIVE_HUNDRED = 500;
+    public static final int EIGHT_HUNDRED = 800;
+    public static final int SIX_THREE_SEVEN_NINE = 6379;
+    public static final int ONE_ZERO_TWO_FOUR = 1024;
+    public static final int ONE_THOUSAND = 1000;
+    public static final int THREE_SIX_ZERO_ZERO = 3600;
+    public static final int FIFTY_MILLION = 52428800;
+    public static final double NINETY = 90.0D;
+    public static final double NEGATICE_NINETY = -90.0D;
+    public static final double ONE_HUNDRED_EIGHTY = 180.0D;
+    public static final double NEGATICE_ONE_HUNDRED_EIGHTY = -180.0D;
+    public static final int COOKIE_TIMEN = 300;
+
+    public NumberConstant() {
+    }
+}

+ 31 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/CustomCellWriteHandler.java

@@ -0,0 +1,31 @@
+package com.sckw.excel.config.easyexcel;
+
+
+
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+
+/**
+ * 自定义拦截器。对第一行第一列的头超链接
+ */
+@Slf4j
+public class CustomCellWriteHandler implements CellWriteHandler {
+
+
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+
+    }
+
+
+}

+ 46 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelImportListener.java

@@ -0,0 +1,46 @@
+package com.sckw.excel.config.easyexcel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.sckw.excel.utils.ValidDataUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author LengFaQiang
+ * @create 2021-11-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class ExcelImportListener extends AnalysisEventListener<Object> {
+    /**
+     * 成功的数据
+     */
+    private List<Object> dataList = new ArrayList<>();
+
+    /**
+     * 错误信息列表
+     */
+    private List<String> errorList = new ArrayList<>();
+
+    @Override
+    public void invoke(Object data, AnalysisContext context) {
+        String validMsg = ValidDataUtil.valid(data);
+        if (validMsg != null) {
+            //+1行(实际中excel中第几行的数据)
+            int rowIndex = context.readRowHolder().getRowIndex() + 1;
+            String errorMsg = "第" + rowIndex + "行数据有误," + validMsg;
+            errorList.add(errorMsg);
+        } else {
+            dataList.add(data);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+
+    }
+}

+ 64 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelListener.java

@@ -0,0 +1,64 @@
+package com.sckw.excel.config.easyexcel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 监听类,可以自定义
+ *
+ * @author LengFaQiang
+ * @Created 2019-7-18 18:01:53
+ **/
+public class ExcelListener extends AnalysisEventListener {
+
+    /**
+     * 自定义用于暂时存储data。
+     * 可以通过实例获取该值
+     */
+    private List<Object> datas = new ArrayList<>();
+
+    /**
+     * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
+     */
+    @Override
+    public void invoke(Object object, AnalysisContext context) {
+        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
+        datas.add(object);
+        //根据业务自行 do something
+        doSomething();
+        /*
+        如数据过大,可以进行定量分批处理
+        if(datas.size()<=100){
+            datas.add(object);
+        }else {
+            doSomething();
+            datas = new ArrayList<Object>();
+        }
+         */
+    }
+
+    /**
+     * 根据业务自行实现该方法
+     */
+    private void doSomething() {
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        /*
+            datas.clear();
+            解析结束销毁不用的资源
+         */
+    }
+
+    public List<Object> getDatas() {
+        return datas;
+    }
+
+    public void setDatas(List<Object> datas) {
+        this.datas = datas;
+    }
+}

+ 46 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/ExcelSelectedResolve.java

@@ -0,0 +1,46 @@
+package com.sckw.excel.config.easyexcel;
+
+import com.sckw.excel.annotation.ExcelSelected;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author LengFaQiang
+ * @version 1.0.0
+ * @ClassName ExcelSelectedResolve.java
+ * @Description easy导出设置下拉框
+ * @createTime 2022/4/27 10:27
+ */
+@Data
+@Slf4j
+public class ExcelSelectedResolve {
+
+    /**
+     * 下拉内容
+     */
+    private String[] source;
+
+    /**
+     * 设置下拉框的起始行,默认为第二行
+     */
+    private int firstRow;
+
+    /**
+     * 设置下拉框的结束行,默认为最后一行
+     */
+    private int lastRow;
+
+    public String[] resolveSelectedSource(ExcelSelected excelSelected) {
+        if (excelSelected == null) {
+            return null;
+        }
+
+        // 获取固定下拉框的内容
+        String[] source = excelSelected.source();
+        if (source.length > 0) {
+            return source;
+        }
+        return null;
+    }
+
+}

+ 30 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/LocalDateTimeConverter.java

@@ -0,0 +1,30 @@
+package com.sckw.excel.config.easyexcel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+
+import java.time.LocalDateTime;
+
+/**
+ *
+ * 导出时的字段类型转换
+ * LocalDateTime to「yyyy-MM-dd HH:mm:ss」
+ *
+ * @author LengFaQiang
+ * @version v1
+ * @create 2020-09-24 11:07:29
+ * @copyright
+ */
+public class LocalDateTimeConverter implements Converter<LocalDateTime> {
+
+    @Override
+    public Class<LocalDateTime> supportJavaTypeKey() {
+        return LocalDateTime.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+}

+ 21 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/RequestHolder.java

@@ -0,0 +1,21 @@
+package com.sckw.excel.config.easyexcel;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+/**
+ * 获取requestHolder
+ */
+public class RequestHolder {
+    public static HttpServletRequest getRequest(){
+        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        return req;
+    }
+
+    public static HttpServletResponse getResponse(){
+        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+        return resp;
+    }
+}

+ 36 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/RowWriteHandlerImpl.java

@@ -0,0 +1,36 @@
+package com.sckw.excel.config.easyexcel;
+
+//import com.alibaba.excel.metadata.CellData;
+
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import org.apache.poi.ss.usermodel.*;
+
+/**
+ * @author LengFaQiang
+ * @version 1.0.0
+ * @ClassName RowWriteHandlerImpl.java
+ * @Description 设置导出excel的单元格格式为文本
+ * @createTime 2022年012月021日 10:15:00
+ */
+public class RowWriteHandlerImpl implements CellWriteHandler {
+
+    CellStyle cellStyle;
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+        Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
+        if (cellStyle == null){
+            cellStyle = workbook.createCellStyle();
+        }
+        DataFormat dataFormat = workbook.createDataFormat();
+        cellStyle.setDataFormat(dataFormat.getFormat("@"));
+        cell.setCellStyle(cellStyle);
+    }
+}

+ 60 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/SelectedSheetWriteHandler.java

@@ -0,0 +1,60 @@
+package com.sckw.excel.config.easyexcel;
+
+import com.alibaba.excel.write.handler.SheetWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.Map;
+
+/**
+ * @author LengFaQiang
+ * @version 1.0.0
+ * @ClassName SelectedSheetWriteHandler.java
+ * @Description 导出设置下拉框handler
+ * @createTime 2022/4/27 10:29
+ */
+@Data
+@AllArgsConstructor
+public class SelectedSheetWriteHandler implements SheetWriteHandler {
+
+    private final Map<Integer, ExcelSelectedResolve> selectedMap;
+
+    /**
+     * Called before create the sheet
+     */
+    @Override
+    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+
+    }
+
+    /**
+     * Called after the sheet is created
+     */
+    @Override
+    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
+        // 这里可以对cell进行任何操作
+        Sheet sheet = writeSheetHolder.getSheet();
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        selectedMap.forEach((k, v) -> {
+            // 设置下拉列表的行: 首行,末行,首列,末列
+            CellRangeAddressList rangeList = new CellRangeAddressList(v.getFirstRow(), v.getLastRow(), k, k);
+            // 设置下拉列表的值
+            DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSource());
+            // 设置约束
+            DataValidation validation = helper.createValidation(constraint, rangeList);
+            // 阻止输入非下拉选项的值
+            validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
+            validation.setShowErrorBox(true);
+            validation.setSuppressDropDownArrow(true);
+            validation.createErrorBox("提示", "请输入下拉选项中的内容");
+            sheet.addValidationData(validation);
+        });
+    }
+}

+ 24 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/config/easyexcel/SheetExcelData.java

@@ -0,0 +1,24 @@
+package com.sckw.excel.config.easyexcel;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SheetExcelData<T> {
+
+    /**
+     * 数据
+     */
+    private List<T> dataList;
+
+    /**
+     * sheet名
+     */
+    private String sheetName;
+
+    /**
+     * 对象类型
+     */
+    private Class<T> tClass ;
+}

+ 404 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/DateUtil.java

@@ -0,0 +1,404 @@
+package com.sckw.excel.utils;
+
+
+import com.sckw.core.utils.StringUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @description: 时间工具类
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:04
+ **/
+public class DateUtil {
+    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    public static final String DEF_DATE_FORMAT = "yyyy-MM-dd";
+    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    public static final DateTimeFormatter HH_MM_SS = DateTimeFormatter.ofPattern("HH:mm:ss");
+
+    public DateUtil() {
+    }
+
+    public static long getSystemTimeMillis() {
+        Clock clock = Clock.systemDefaultZone();
+        return clock.millis();
+    }
+
+    public static String getDateTime(String pattern) {
+        if (StringUtils.isEmpty(pattern)) {
+            pattern = "yyyy-MM-dd HH:mm:ss";
+        }
+
+        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
+    }
+
+    public static String getDateTime(Date date) {
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
+        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+    }
+
+    public static String dateToStr(LocalDate date) {
+        return dateToStr(date, "yyyy-MM-dd");
+    }
+
+    public static String dateToStr(LocalDate date, String pattern) {
+        String dateStr = date.format(DateTimeFormatter.ofPattern(pattern));
+        return dateStr;
+    }
+
+    public static String timeToStr(LocalDateTime date) {
+        return timeToStr(date, "yyyy-MM-dd HH:mm:ss");
+    }
+
+    public static String timeToStr(LocalDateTime date, String pattern) {
+        String dateStr = date.format(DateTimeFormatter.ofPattern(pattern));
+        return dateStr;
+    }
+
+    public static LocalDateTime strToTime(String str) {
+        return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+    }
+
+    /**
+     * yyyy-MM-dd 转换成 LocalDate
+     * @param str
+     * @return
+     */
+    public static LocalDate strToDate(String str) {
+        return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+    }
+
+    /**
+     * yyyy-MM-dd 转换成 LocalDateTime
+     * @param str
+     * @return
+     */
+    public static LocalDateTime strToDateTime(String str) {
+        LocalDate localDate = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        LocalDateTime localDateTime = localDate.atStartOfDay();
+        String format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        LocalDateTime parse = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        return parse;
+    }
+
+    /**
+     * yyyyMMdd 转换成 LocalDate
+     *
+     * @param str
+     * @return
+     */
+    public static LocalDate stringToDate(String str) {
+        return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyyMMdd"));
+    }
+
+    /**
+     * 日期字符串转换为LocalDateTime方法
+     *
+     * @param dateString 日期字符串,格式:yyyyMMdd
+     * @return
+     */
+    public static LocalDateTime handleDateTimeString(String dateString) {
+        //日期字符串的长度
+        Integer dateLength = 10;
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(dateString) && dateString.length() == dateLength) {
+            StringBuilder sb = new StringBuilder(dateString);
+            return LocalDateTime.parse(sb.toString() + "T00:00:00");
+        }
+        return null;
+    }
+
+    /**
+     * 日期字符串转换为LocalDateTime方法
+     *
+     * @param dateString 日期字符串,格式:yyyyMMdd
+     * @return
+     */
+    public static LocalDateTime handleDateString(String dateString) {
+        //日期字符串的长度
+        Integer dateLength = 8;
+        if (org.apache.commons.lang3.StringUtils.isNotBlank(dateString) && dateString.length() == dateLength) {
+            StringBuilder sb = new StringBuilder(dateString);
+            sb.insert(4, "-");
+            sb.insert(7, "-");
+            return LocalDateTime.parse(sb.toString() + "T00:00:00");
+        }
+        return null;
+    }
+
+    public static String date() {
+        return LocalDate.now().format(YYYY_MM_DD);
+    }
+
+    public static int year() {
+        return LocalDate.now().getYear();
+    }
+
+    public static int month() {
+        return LocalDate.now().getMonthValue();
+    }
+
+    public static int dayOfMonth() {
+        return LocalDate.now().getDayOfMonth();
+    }
+
+    public static int dayOfYear() {
+        return LocalDate.now().getDayOfYear();
+    }
+
+    public static int dayOfWeek() {
+        return LocalDate.now().getDayOfWeek().getValue();
+    }
+
+    public static String newDate(int year, int month, int day) {
+        return LocalDate.of(year, month, day).toString();
+    }
+
+    public static String newDate(int year, int dayNum) {
+        return LocalDate.ofYearDay(year, dayNum).toString();
+    }
+
+    public static String time() {
+        return LocalTime.now().format(HH_MM_SS);
+    }
+
+    public static int hour() {
+        return LocalTime.now().getHour();
+    }
+
+    public static int minute() {
+        return LocalTime.now().getMinute();
+    }
+
+    public static int second() {
+        return LocalTime.now().getSecond();
+    }
+
+    public static String dateTime() {
+        return LocalDateTime.now().format(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static LocalDateTime parseDateTime(long time) {
+        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
+    }
+
+    public static LocalDateTime parseDateTime(String time) {
+        return LocalDateTime.parse(time, YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static LocalDate parseDate(long time) {
+        return LocalDate.from(parseDateTime(time));
+    }
+
+    public static LocalDate parseDate(String time) {
+        return LocalDate.parse(time, YYYY_MM_DD);
+    }
+
+    public static String format(LocalDate date) {
+        return date.format(YYYY_MM_DD);
+    }
+
+    public static String format(LocalDateTime dateTime) {
+        return dateTime.format(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static long millis(LocalDate date) {
+        return millis(date.atStartOfDay());
+    }
+
+    public static long millis(LocalDateTime dateTime) {
+        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    public static String getDateString(Date date, String pattern) {
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
+        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
+    }
+
+    public static long getBetweenDays(Date startDate, Date endDate) {
+        return betweenDate(startDate, endDate).toDays();
+    }
+
+    public static long getBetweenHours(Date startDate, Date endDate) {
+        return betweenDate(startDate, endDate).toHours();
+    }
+
+    public static long getBetweenMinutes(Date startDate, Date endDate) {
+        return betweenDate(startDate, endDate).toMinutes();
+    }
+
+    private static Duration betweenDate(Date startDate, Date endDate) {
+        ZoneId zoneId = ZoneId.systemDefault();
+        Instant startDateInstant = startDate.toInstant();
+        LocalDateTime startDateLocalDateTime = startDateInstant.atZone(zoneId).toLocalDateTime();
+        Instant endDateInstant = endDate.toInstant();
+        LocalDateTime endDateLocalDateTime = endDateInstant.atZone(zoneId).toLocalDateTime();
+        return Duration.between(startDateLocalDateTime, endDateLocalDateTime);
+    }
+
+    public static Date strToDate(String dateStr, String pattern) throws ParseException {
+        SimpleDateFormat dateFormat = new SimpleDateFormat();
+        if (pattern != null && !pattern.isEmpty()) {
+            dateFormat.applyPattern(pattern);
+        }
+
+        Date date = dateFormat.parse(dateStr);
+        return date;
+    }
+
+    public static int getCurrentMonthDays() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(5, 1);
+        calendar.roll(5, -1);
+        int days = calendar.get(5);
+        return days;
+    }
+
+    public static int getMonthDays(int year, int month) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(1, year);
+        calendar.set(2, month - 1);
+        calendar.set(5, 1);
+        calendar.roll(5, -1);
+        int days = calendar.get(5);
+        return days;
+    }
+
+    public static Date subtractionOneDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(5, -1);
+        Date startDate = calendar.getTime();
+        return startDate;
+    }
+
+    public static Date getDay(int offset, Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(5, offset);
+        return calendar.getTime();
+    }
+
+    public static Date getDelay(int offset, Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(1, offset);
+        return calendar.getTime();
+    }
+
+    public static String getWeekOfDate(Date date, Lanagues language) {
+        String name = "";
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int weekIndex = calendar.get(7) - 1;
+        if (weekIndex < 0) {
+            weekIndex = 0;
+        }
+
+        switch(language) {
+            case CHINESE:
+                name = Week.getName(weekIndex);
+                break;
+            case ENGLISH:
+                name = Week.getEnName(weekIndex);
+        }
+
+        return name;
+    }
+
+    public static enum Week {
+        SUNDAY("星期日", "Sunday", 0),
+        MONDAY("星期一", "Monday", 1),
+        TUESDAY("星期二", "Tuesday", 2),
+        WEDNESDAY("星期三", "Sunday", 3),
+        THURSDAY("星期四", "Thursday", 4),
+        FRIDAY("星期五", "Friday ", 5),
+        SATURDAY("星期六", "Saturday", 6);
+
+        private String name;
+        private String enName;
+        private int index;
+
+        public static String getName(int index) {
+            String name = null;
+            Week[] var2 = values();
+            int var3 = var2.length;
+
+            for(int var4 = 0; var4 < var3; ++var4) {
+                Week week = var2[var4];
+                if (week.getIndex() == index) {
+                    name = week.getName();
+                }
+            }
+
+            return name;
+        }
+
+        public static String getEnName(int index) {
+            String name = null;
+            Week[] var2 = values();
+            int var3 = var2.length;
+
+            for(int var4 = 0; var4 < var3; ++var4) {
+                Week week = var2[var4];
+                if (week.getIndex() == index) {
+                    name = week.getEnName();
+                }
+            }
+
+            return name;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getEnName() {
+            return this.enName;
+        }
+
+        public void setEnName(String enName) {
+            this.enName = enName;
+        }
+
+        public int getIndex() {
+            return this.index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+
+        private Week(String name, String enName, int index) {
+            this.name = name;
+            this.enName = enName;
+            this.index = index;
+        }
+
+        public String toString() {
+            return "Week [name=" + this.name + ", enName=" + this.enName + ", index=" + this.index + "]";
+        }
+    }
+
+    public static enum Lanagues {
+        CHINESE,
+        ENGLISH;
+
+        private Lanagues() {
+        }
+    }
+}

+ 151 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/EasyExcelUtil.java

@@ -0,0 +1,151 @@
+package com.sckw.excel.utils;
+
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.support.ExcelTypeEnum;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.alibaba.fastjson.JSON;
+import com.sckw.core.web.response.HttpResult;
+import com.sckw.excel.config.easyexcel.CustomCellWriteHandler;
+import com.sckw.excel.config.easyexcel.ExcelListener;
+import com.sckw.excel.config.easyexcel.RequestHolder;
+import com.sckw.excel.config.easyexcel.SheetExcelData;
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * Excel工具类
+ * @author LengFaQiang
+ * @Created 2019-7-18 18:01:53
+ **/
+@Slf4j
+public class EasyExcelUtil {
+    /**
+     * 读取单个sheet的excel文件
+     * @param excel 文件
+     * @param t 实体类型
+     * @param headRowNumber 头行数
+     * @return
+     * @throws Exception
+     */
+    public static <T> List<T> readSingleExcel(MultipartFile excel, T t, int headRowNumber) throws IOException {
+        return EasyExcel.read(excel.getInputStream(), t.getClass(), new ExcelListener())
+                .sheet().headRowNumber(headRowNumber).doReadSync();
+    }
+
+
+    /**
+     * 导出文件
+     * 导出模板时,tList传一个空list即可
+     * @param tList 数据集
+     * @param tClass 数据类型
+     * @param <T>
+     * @throws IOException
+     */
+    public static <T> void writeSingleExcel(String fileName,String sheetName, List<T> tList, Class tClass) throws IOException{
+        HttpServletResponse response = RequestHolder.getResponse();
+        try (ServletOutputStream outputStream = response.getOutputStream()){
+            setResponse(fileName, response);
+            EasyExcel.write(outputStream, tClass).autoCloseStream(Boolean.FALSE)
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .registerWriteHandler(new CustomCellWriteHandler())
+                    .sheet(sheetName)
+                    .doWrite(tList);
+        } catch (Exception e) {
+            errorWrite(response, e);
+        }
+    }
+
+    /**
+     * 导出多sheet
+     * @param fileName 文件名
+     * @param sheetExcelDataList sheet对象
+     * @throws IOException
+     */
+    public static void writeMultiExcel(String fileName, List<SheetExcelData> sheetExcelDataList) throws IOException{
+        HttpServletResponse response = RequestHolder.getResponse();
+        ServletOutputStream outputStream = response.getOutputStream();
+        setResponse(fileName, response);
+        ExcelWriter excelWriter = EasyExcel.write(outputStream).autoCloseStream(false).build();
+        try {
+            for (int i = 0,length = sheetExcelDataList.size(); i < length; i++) {
+                WriteSheet writeSheet = EasyExcel.writerSheet(i+1, sheetExcelDataList.get(i).getSheetName())
+                        .head(sheetExcelDataList.get(i).getTClass())
+                        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
+                excelWriter.write(sheetExcelDataList.get(i).getDataList(), writeSheet);
+            }
+        } catch (Exception e) {
+            errorWrite(response, e);
+        }finally {
+            // 刷新流,不加这句话,下载文件损坏打不开
+            outputStream.flush();
+            // outputStream.close();
+            if(excelWriter != null){
+                // 千万别忘记finish关闭流
+                excelWriter.finish();
+            }
+        }
+    }
+
+    /**
+     * 无对象导出
+     * @param fileName
+     * @param headList
+     * @param dataList
+     * @throws IOException
+     */
+    public static void writeWithoutModel(String fileName, List<List<String>> headList,List<List<Object>> dataList) throws IOException{
+        HttpServletResponse response = RequestHolder.getResponse();
+        try (ServletOutputStream outputStream = response.getOutputStream()){
+            setResponse(fileName, response);
+            // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
+            EasyExcel.write(outputStream).head(headList).sheet("模板").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).doWrite(dataList);
+        } catch (Exception e) {
+            errorWrite(response, e);
+        }
+    }
+
+    /**
+     * 导出错误
+     * @param response
+     * @param e
+     * @throws IOException
+     */
+    private static void errorWrite(HttpServletResponse response, Exception e) throws IOException {
+        // 重置response
+        response.reset();
+        log.error(e.getMessage(), e);
+        response.setContentType("application/json");
+        response.setCharacterEncoding("utf-8");
+        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+        response.getWriter().println(JSON.toJSONString(HttpResult.error(com.sckw.core.web.constant.HttpStatus.GLOBAL_EXCEPTION_CODE,"导出失败")));
+    }
+
+    /**
+     * 设置导出信息
+     * @param fileName
+     * @param response
+     * @throws UnsupportedEncodingException
+     */
+    private static void setResponse(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
+        // 重置response
+        response.reset();
+        response.setContentType("application/vnd.ms-excel;charset=utf-8");
+        response.setCharacterEncoding("utf-8");
+        // 这里URLEncoder.encode可以防止中文乱码
+        //,"yyyy-MM-dd_HH_mm_ss"
+        fileName = URLEncoder.encode(fileName + DateUtil.dateToStr(LocalDate.now()) + ExcelTypeEnum.XLSX.getValue(), "UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
+    }
+}

+ 201 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/ExcelUtil.java

@@ -0,0 +1,201 @@
+package com.sckw.excel.utils;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.alibaba.fastjson.JSONObject;
+import com.sckw.core.web.response.HttpResult;
+import com.sckw.excel.annotation.ExcelContext;
+import com.sckw.excel.annotation.ExcelSelected;
+import com.sckw.excel.config.easyexcel.ExcelSelectedResolve;
+import com.sckw.excel.config.easyexcel.LocalDateTimeConverter;
+import com.sckw.excel.config.easyexcel.RowWriteHandlerImpl;
+import com.sckw.excel.config.easyexcel.SelectedSheetWriteHandler;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.sckw.excel.common.NumberConstant.ZERO;
+
+
+/**
+ * 封装easyexcel
+ *
+ * @author LengFaQiang
+ * @version v1
+ * @create 2020-09-24 10:15:49
+ * @copyright
+ */
+@Slf4j
+public class ExcelUtil {
+
+    public static <T> void download(HttpServletResponse response, Class<T> clazz, List<T> data) {
+//        StaticComponentContainer.Modules.exportAllToAll();
+        Assert.notNull(clazz, "clazz can't be null");
+        Assert.isTrue(data != null && !data.isEmpty(), "data can't be empty");
+        try {
+            ExcelContext excelContext = clazz.getAnnotation(ExcelContext.class);
+            buildResponse(response, excelContext.fileName());
+            EasyExcel.write(response.getOutputStream(), clazz)
+                    .registerConverter(new LocalDateTimeConverter())
+                    .registerWriteHandler(new RowWriteHandlerImpl())
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .autoCloseStream(Boolean.FALSE).sheet(excelContext.sheetName())
+                    .doWrite(data);
+        } catch (Exception e) {
+            buildResponse(response, e);
+        }
+    }
+
+    public static void download(HttpServletResponse response, List<List> source) {
+        Assert.isTrue(source != null && source.size() > 0, "source can't be empty");
+        ExcelWriter excelWriter = null;
+        try {
+            String fileName = source.get(ZERO).get(ZERO).getClass().getAnnotation(ExcelContext.class).fileName();
+            buildResponse(response, fileName);
+            excelWriter = EasyExcel.write(response.getOutputStream())
+                    .registerConverter(new LocalDateTimeConverter())
+                    .registerWriteHandler(new RowWriteHandlerImpl())
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .autoCloseStream(Boolean.FALSE).build();
+            for (int i = 0; i < source.size(); i++) {
+                List list = source.get(i);
+                //Assert.isTrue(!CollectionUtils.isEmpty(list), "source can't be empty");
+                if (CollectionUtils.isEmpty(list)) {
+                    continue;
+                }
+                Class<?> clazz = list.get(ZERO).getClass();
+                ExcelContext context = clazz.getAnnotation(ExcelContext.class);
+                WriteSheet writeSheet = EasyExcel.writerSheet(i, context.sheetName()).registerWriteHandler(new RowWriteHandlerImpl()).head(clazz).build();
+                excelWriter.write(list, writeSheet);
+            }
+        } catch (Exception e) {
+            buildResponse(response, e);
+        } finally {
+            if (excelWriter != null) {
+                excelWriter.finish();
+            }
+        }
+
+    }
+
+    private static void buildResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
+        fileName = URLEncoder.encode(fileName + "-" + DateUtil.dateToStr(LocalDate.now()), "UTF-8").replaceAll("\\+", "%20");
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+    }
+
+    private static void buildResponse(HttpServletResponse response, Exception e) {
+        StackTraceElement[] stackTrace = e.getStackTrace();
+        log.error("Failed to export data. -> {}", String.valueOf(stackTrace[0]) + stackTrace[1] + stackTrace[2], e);
+        //response.reset();
+        response.setContentType("application/json");
+        response.setCharacterEncoding("UTF-8");
+        try (PrintWriter writer = response.getWriter()) {
+            writer.println(JSONObject.toJSONString(HttpResult.error("导出数据失败, " + e.toString())));
+        } catch (Exception ignored) {
+        }
+    }
+
+    /**
+     * 判断是否是excel
+     *
+     * @param file 文件
+     * @return 获取结果
+     */
+    public static boolean checkExcel(MultipartFile file) {
+        String fileName = file.getOriginalFilename();
+        String match1 = "^.+\\.(?i)(xls)$";
+        String match2 = "^.+\\.(?i)(xlsx)$";
+        return !fileName.matches(match1) && !fileName.matches(match2);
+    }
+
+    /**
+     * 导出单元格内容含有下拉框的excel 需要使用@ExcelSelected在对应字段上设置字段的下拉框的值
+     *
+     * @param response
+     * @param source
+     */
+    public static void writeSelectedSheet(HttpServletResponse response, List<List> source) {
+        Assert.isTrue(source != null && source.size() > 0, "source can't be empty");
+        ExcelWriter excelWriter = null;
+        try {
+            String fileName = source.get(ZERO).get(ZERO).getClass().getAnnotation(ExcelContext.class).fileName();
+            buildResponse(response, fileName);
+            excelWriter = EasyExcel.write(response.getOutputStream())
+                    .registerConverter(new LocalDateTimeConverter())
+                    .registerWriteHandler(new RowWriteHandlerImpl())
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .autoCloseStream(Boolean.FALSE).build();
+            for (int i = 0; i < source.size(); i++) {
+                List list = source.get(i);
+                //Assert.isTrue(!CollectionUtils.isEmpty(list), "source can't be empty");
+                if (CollectionUtils.isEmpty(list)) {
+                    continue;
+                }
+                Class<?> clazz = list.get(ZERO).getClass();
+                ExcelContext context = clazz.getAnnotation(ExcelContext.class);
+                Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(clazz);
+                WriteSheet writeSheet = EasyExcel.writerSheet(i, context.sheetName()).head(clazz).registerWriteHandler(new RowWriteHandlerImpl()).registerWriteHandler(new SelectedSheetWriteHandler(selectedMap)).build();
+                excelWriter.write(list, writeSheet);
+            }
+        } catch (Exception e) {
+            buildResponse(response, e);
+        } finally {
+            if (excelWriter != null) {
+                excelWriter.finish();
+            }
+        }
+
+    }
+
+    /**
+     * 解析表头类中的下拉注解
+     *
+     * @param head 表头类
+     * @param <T>  泛型
+     * @return Map<下拉框列索引, 下拉框内容> map
+     */
+    private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head) {
+        Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();
+
+        // getDeclaredFields(): 返回全部声明的属性;getFields(): 返回public类型的属性
+        Field[] fields = head.getDeclaredFields();
+        for (int i = 0; i < fields.length; i++) {
+            Field field = fields[i];
+            // 解析注解信息
+            ExcelSelected selected = field.getAnnotation(ExcelSelected.class);
+            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
+            if (selected != null) {
+                ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
+                String[] source = excelSelectedResolve.resolveSelectedSource(selected);
+                if (source != null && source.length > 0) {
+                    excelSelectedResolve.setSource(source);
+                    excelSelectedResolve.setFirstRow(selected.firstRow());
+                    excelSelectedResolve.setLastRow(selected.lastRow());
+                    if (property != null && property.index() >= 0) {
+                        selectedMap.put(property.index(), excelSelectedResolve);
+                    } else {
+                        selectedMap.put(i, excelSelectedResolve);
+                    }
+                }
+            }
+        }
+
+        return selectedMap;
+    }
+}

+ 42 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/utils/ValidDataUtil.java

@@ -0,0 +1,42 @@
+package com.sckw.excel.utils;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * <p>
+ *
+ *
+ * @author LengFaQiang
+ * @version v1
+ * @create 2021-04-26 16:31:11
+ * @copyright
+ */
+public class ValidDataUtil {
+
+    /**全属性验证器*/
+    private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+
+    /**
+     * 检查数据格式
+     * @param object 需要验证的带有{@link javax.validation.constraints}注解的实体
+     * @param <T> the type of the object to validate
+     * @return 是否验证通过 {@link Result} 不通过时{@code getMsg()}获取失败信息
+     */
+    @Nullable
+    public static <T> String valid(@NonNull T object) {
+        Set<ConstraintViolation<T>> validateSet = validator.validate(object);
+        if (!CollectionUtils.isEmpty(validateSet)) {
+            return validateSet.stream().map(validate -> validate.getMessage()).collect(Collectors.joining(","));
+        }
+        return null;
+    }
+}

BIN
sckw-common/sckw-common-excel/src/main/resources/excel/商品主档信息导入模板.xlsx


+ 154 - 0
sckw-common/sckw-common-excel/src/main/resources/log4j2.xml

@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="info" monitorInterval="30">
+    <properties>
+        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符 -->
+        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
+        <property name="LOG_PATTERN"
+                  value="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%t]}{faint} %clr{%c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx"/>
+        <property name="LOG_WITHOUT_COLOR_PATTERN"
+                  value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${sys:PID}--- [%t] %c{1.} : %m%n%xwEx"/>
+        <property name="LOG_PATH" value="logs/sckw-gateway"/>
+    </properties>
+    <!--DEBUG<INFO<WARNING<ERROR<CRITICAL-->
+    <!-- 先定义所有的appender(附加器)-->
+    <appenders>
+        <!-- 输出控制台的配置 -->
+        <Console name="Console" target="SYSTEM_OUT">
+            <!-- 输出日志的格式 -->
+            <PatternLayout pattern="${LOG_PATTERN}"/>
+        </Console>
+
+        <!--all级别日志-->
+        <RollingFile name="allFileAppender"
+                     fileName="${LOG_PATH}/all.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log.gz">
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--debug级别日志-->
+        <RollingFile name="debugFileAppender"
+                     fileName="${LOG_PATH}/debug.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉info及更高级别日志-->
+                <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--info级别日志-->
+        <RollingFile name="infoFileAppender"
+                     fileName="${LOG_PATH}/info.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉warn及更高级别日志-->
+                <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <!--<DefaultRolloverStrategy max="100"/>-->
+        </RollingFile>
+
+        <!--warn级别日志-->
+        <RollingFile name="warnFileAppender"
+                     fileName="${LOG_PATH}/warn.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
+            <Filters>
+                <!--过滤掉error及更高级别日志-->
+                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
+            </Filters>
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--error及更高级别日志-->
+        <RollingFile name="errorFileAppender"
+                     fileName="${LOG_PATH}/error.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
+            <!--设置日志格式-->
+            <PatternLayout pattern="${LOG_WITHOUT_COLOR_PATTERN}"/>
+            <Policies>
+                <!-- 设置日志文件切分参数 -->
+                <!--<OnStartupTriggeringPolicy/>-->
+                <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新-->
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置-->
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+            <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i-->
+            <DefaultRolloverStrategy max="100"/>
+        </RollingFile>
+
+        <!--json格式error级别日志-->
+        <RollingFile name="errorJsonAppender"
+                     fileName="${LOG_PATH}/error-json.log"
+                     filePattern="${LOG_PATH}/$${date:yyyy-MM}/error-json-%d{yyyy-MM-dd}-%i.log.gz">
+            <JSONLayout compact="true" eventEol="true" locationInfo="true"/>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
+            </Policies>
+        </RollingFile>
+
+    </appenders>
+
+    <loggers>
+        <root level="debug">
+            <AppenderRef ref="allFileAppender" level="all"/>
+            <AppenderRef ref="debugFileAppender" level="debug"/>
+            <AppenderRef ref="infoFileAppender" level="info"/>
+            <AppenderRef ref="warnFileAppender" level="warn"/>
+            <AppenderRef ref="errorFileAppender" level="error"/>
+            <AppenderRef ref="errorJsonAppender" level="error"/>
+            <appender-ref ref="Console" level="info"/>
+        </root>
+        <Logger name="org.springframework" level="info"/>
+        <Logger name="com.alibaba" level="info"/>
+        <Logger name="com.baomidou" level="info"/>
+    </loggers>
+
+</configuration>

+ 47 - 0
sckw-common/sckw-common-redis/pom.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-redis</artifactId>
+    <version>1.0.0</version>
+
+    <description>缓存服务</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <redisson.version>3.20.1</redisson.version>
+    </properties>
+
+
+    <dependencies>
+<!--        <dependency>-->
+<!--            <groupId>org.redisson</groupId>-->
+<!--            <artifactId>redisson-spring-boot-starter</artifactId>-->
+<!--            <version>${redisson.version}</version>-->
+<!--        </dependency>-->
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-json</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 92 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/RedisLockUtil.java

@@ -0,0 +1,92 @@
+package com.sckw.redis.config;
+
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author xucaiqin
+ * @date 2023-04-07 17:20:34
+ */
+@Component
+@Slf4j
+public class RedisLockUtil {
+    @Resource
+    private RedissonClient redissonClient;
+
+    /**
+     * 加锁
+     *
+     * @param lockKey 锁的key
+     * @return
+     */
+    public boolean tryLock(String lockKey) {
+        return tryLock(lockKey, 5, 10);
+    }
+
+    /**
+     * 加锁
+     *
+     * @param lockKey 锁的key
+     * @return
+     */
+    public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
+        RLock lock = redissonClient.getLock(lockKey);
+        try {
+            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            log.info("tryLock lockKey:{} waitTime:{} leaseTime:{}", lockKey, waitTime, leaseTime);
+            return false;
+        }
+    }
+
+    /**
+     * 加锁
+     *
+     * @param lockKey 锁的key
+     * @return
+     */
+    public RLock lock(String lockKey) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.lock();
+        return lock;
+    }
+
+    /**
+     * 加锁
+     *
+     * @param lockKey 锁的key
+     * @param timeout 超时时间
+     * @return
+     */
+    public RLock lock(String lockKey, long timeout) {
+        RLock lock = redissonClient.getLock(lockKey);
+        lock.lock(timeout, TimeUnit.SECONDS);
+        return lock;
+    }
+
+    /**
+     * 解锁
+     *
+     * @param lockKey 锁的key
+     */
+    public void unlock(String lockKey) {
+        RLock lock = redissonClient.getLock(lockKey);
+        if (lock.isHeldByCurrentThread()) {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * 解锁
+     *
+     * @param lock 锁对象
+     */
+    public void unlock(RLock lock) {
+        lock.unlock();
+    }
+}

+ 80 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/RedissonConfig.java

@@ -0,0 +1,80 @@
+package com.sckw.redis.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.sckw.redis.config.serializer.FastJson2JsonRedisSerializer;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @Author xucaiqin
+ * @date 2023-06-01 14:50:29
+ */
+@AutoConfiguration
+public class RedissonConfig {
+
+    /**
+     * jackson序列化方式的redisTemplate
+     *
+     * @param redisConnectionFactory
+     * @return
+     */
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        // 设置值(value)的序列化采用jackson
+        redisTemplate.setValueSerializer(serializer());
+        redisTemplate.setHashValueSerializer(serializer());
+
+        // 设置键(key)的序列化采用StringRedisSerializer。
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    /**
+     * fastjson序列化方式的redisTemplate
+     *
+     * @param redisConnectionFactory
+     * @return
+     */
+    @Bean
+    public RedisTemplate<String, Object> redisTemplateFastJson(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        FastJson2JsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJson2JsonRedisSerializer<>(Object.class);
+        // 设置值(value)的序列化采用FastJsonRedisSerializer。
+        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
+        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
+
+        // 设置键(key)的序列化采用StringRedisSerializer。
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    private Jackson2JsonRedisSerializer<Object> serializer() {
+        // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
+        ObjectMapper objectMapper = new ObjectMapper();
+        // 解决jackson2无法序列化LocalDateTime问题
+        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+        objectMapper.registerModule(new JavaTimeModule());
+        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+
+        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
+        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
+        return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
+    }
+}

+ 49 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/config/serializer/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,49 @@
+package com.sckw.redis.config.serializer;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * fastJson序列化
+ * @author xcq
+ * @date 2022年06月14日 15:21
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
+    public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+
+
+    private final Class<T> clazz;
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz) {
+        super();
+        this.clazz = clazz;
+    }
+
+    /**
+     * 序列化
+     */
+    @Override
+    public byte[] serialize(T t) throws SerializationException {
+        if (null == t) {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    /**
+     * 反序列化
+     */
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException {
+        if (null == bytes || bytes.length == 0) {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+        return (T) JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
+    }
+}

+ 50 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/configure/RedissonConfiguration.java

@@ -0,0 +1,50 @@
+package com.sckw.redis.configure;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author xxx
+ * @DATE 2022/3/27 11:13
+ */
+@Configuration
+public class RedissonConfiguration {
+
+    @Value("${spring.redis.host}")
+    private String address;
+
+    @Value("${spring.redis.port}")
+    private String port;
+
+    @Value("${spring.redis.password}")
+    private String password;
+
+    @Value("${spring.redis.database}")
+    private String database;
+
+    @Value("${spring.redis.timeout}")
+    private String timeout;
+
+    @Bean
+    public RedissonClient redisson() {
+        Config config = new Config();
+        config.useSingleServer()
+                .setAddress(address())
+                .setPassword(password)
+                .setDatabase(Integer.parseInt(database))
+                .setConnectTimeout(Integer.parseInt(timeout));
+        return Redisson.create(config);
+    }
+
+    /**
+     * 生成address
+     * @return
+     */
+    private String address() {
+        return "redis://" + address + ":" + port;
+    }
+}

+ 64 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/utils/RedissonUtils.java

@@ -0,0 +1,64 @@
+package com.sckw.redis.utils;
+
+import org.redisson.api.RBucket;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedissonUtils {
+
+    @Autowired
+    RedissonClient redissonClient;
+
+    /**
+     * 添加缓存
+     * @param key key
+     * @param value value
+     */
+    public void add(String key, String value) {
+        //根据key获取bucket桶对象
+        RBucket<Object> bucket = redissonClient.getBucket(key);
+        //判读是否存在,并打印日志信息
+        if (!bucket.isExists()) {
+            //log.info("");
+        }else {
+            //log.info("update data");
+        }
+        //添加缓存,若已存在,则替换,设置缓存超时时间
+        bucket.set(value, 60, TimeUnit.SECONDS);
+    }
+
+
+    /**
+     * 在缓存中获取信息
+     * @param key key
+     * @return 信息结果
+     */
+    public Object get(String key) {
+        //根据key获取bucket桶对象
+        RBucket<Object> bucket = redissonClient.getBucket(key);
+        //判读是否存在,并打印日志信息
+        if (!bucket.isExists()) {
+            //log.info("error");
+        }
+        //log.info("cache is {}", bucket.get());
+        return bucket.get();
+    }
+
+    /**
+     * 删除缓存信息
+     * @param key key
+     */
+    public void delete(String key) {
+        //根据key获取bucket桶对象
+        RBucket<Object> bucket = redissonClient.getBucket(key);
+        //判读是否存在,并打印日志信息
+        if (!bucket.isExists()) {
+            //log.info("error");
+        }
+        bucket.delete();
+    }
+
+}

+ 37 - 0
sckw-common/sckw-common-redis/src/main/java/com/sckw/redis/utils/TestService.java

@@ -0,0 +1,37 @@
+package com.sckw.redis.utils;
+
+import org.redisson.Redisson;
+import org.redisson.api.RBucket;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+
+public class TestService {
+
+    public void test(){
+        Config config = new Config();
+        config.useSingleServer()
+                // use "rediss://" for SSL connection
+                .setAddress("redis://39.104.183.141:6379").setPassword("123456");
+
+        // or read config from file
+        // config = Config.fromYAML(new File("config-file.yaml"));
+
+        // 2. Create Redisson instance, support Sync and Async API
+        RedissonClient redisson = Redisson.create(config);
+
+        RBucket<Object> mytest = redisson.getBucket("mytest");
+        mytest.set("value");
+        System.out.println(mytest.get());//value
+        mytest.set("value2");
+        System.out.println(mytest.get());//value2
+        boolean b = mytest.compareAndSet("value2", "value3"); //true
+        System.out.println(mytest.get());//value3
+        boolean b1 = mytest.compareAndSet("value2", "value4"); //flase
+        System.out.println(mytest.get());//value3
+    }
+
+    public static void main(String[] args) {
+        TestService testService = new TestService();
+        testService.test();
+    }
+}

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

@@ -0,0 +1,4 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.sckw.redis.configure.RedissonConfiguration
+  com.sckw.redis.utils.RedissonUtils
+

+ 1 - 0
sckw-common/sckw-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1 @@
+com.sckw.redis.config.RedissonConfig

+ 54 - 0
sckw-common/sckw-common-remote/pom.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-remote</artifactId>
+    <version>1.0.0</version>
+    <description>远程调用模块</description>
+
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.alibaba.fastjson2</groupId>
+                    <artifactId>fastjson2</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-commons</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 19 - 0
sckw-common/sckw-common-remote/src/main/java/com/sckw/remote/annotation/SckwCloudApplication.java

@@ -0,0 +1,19 @@
+package com.sckw.remote.annotation;
+
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@EnableDubbo
+@EnableFeignClients({"com.sckw.*.api.feign"})
+@EnableDiscoveryClient
+@SpringBootApplication
+public @interface SckwCloudApplication {
+}

+ 51 - 0
sckw-common/sckw-common-stream/pom.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-common</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-common-stream</artifactId>
+    <version>1.0.0</version>
+    <description>消息驱动服务</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <alicloud-sms.version>2.2.0.RELEASE</alicloud-sms.version>
+        <lombok.version>1.18.26</lombok.version>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-stream</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-alicloud-sms</artifactId>
+            <version>${alicloud-sms.version}</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 9 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/constant/Destination.java

@@ -0,0 +1,9 @@
+package com.sckw.stream.constant;
+
+public class Destination {
+
+    /**默认**/
+    public static final String SCKWMESSAGE = "sckw-message";
+    /**短信**/
+    public static final String SCKWSMSMESSAGE = "sckw-sms-message";
+}

+ 125 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/enums/MessageEnum.java

@@ -0,0 +1,125 @@
+package com.sckw.stream.enums;
+
+/**
+ * @author zk
+ * @description 短信模板
+ * @date 2020/06/16 08:37:44
+ */
+public enum MessageEnum {
+    /**SYSTEM 系统消息、BUSINESS业务消息、INDUSTRY行业消息**/
+    XXXXXX("SYSTEM", "xxxxx", "xxxx", "xxxxxx","terminal"),
+    XXXXXX1("BUSINESS", "xxxxx", "xxxx", "xxxxxx","terminal"),
+
+    //认证通过
+    AUDIT_PASS("SYSTEM","SYSTEM_ENT_APPR","认证通过通知","审核通过!您的资质已认证成功,危品汇欢迎您的入驻!","terminal,ios,android"),
+    //委托单-指派成功
+    RECEIVE_ASSIGN_ENTRUST("BUSINESS", "RECEIVE_ASSIGN_ENTRUST", "新委托单通知",
+            "${firmName}委托承运:从${loadAddress}至${unloadAddress},承运${supplyName},委托量${weight}吨,运价${price}!","terminal,ios,android");
+
+    /**
+     * 消息分类
+     */
+    private String category;
+
+    /**
+     * 消息类型
+     */
+    private String type;
+
+    /**
+     * 消息标题
+     */
+    private String title;
+
+    /**
+     * 消息内容
+     */
+    private String content;
+
+    /**
+     * 显示终端 terminal ios android
+     */
+    private String pushType;
+
+    /**
+     * @description 构造方法
+     * @author zk
+     * @date 2020/6/08 11:28
+     * @param category 消息分类, type 消息类型, title 消息标题, content 消息内容
+     * @return
+     **/
+    private MessageEnum(String category, String type, String title, String content, String pushType) {
+        this.category = category;
+        this.type = type;
+        this.title = title;
+        this.content = content;
+        this.pushType = pushType;
+    }
+
+    public static String getCategoryByType(String type) {
+        for (MessageEnum entityEnum : MessageEnum.values()) {
+            if (entityEnum.getType().equals(type)) {
+                return entityEnum.getCategory();
+            }
+        }
+        return null;
+    }
+
+    public static String getTitleByType(String type) {
+        for (MessageEnum entityEnum : MessageEnum.values()) {
+            if (entityEnum.getType().equals(type)) {
+                return entityEnum.getTitle();
+            }
+        }
+        return null;
+    }
+
+    public static String getContentByType(String type) {
+        for (MessageEnum entityEnum : MessageEnum.values()) {
+            if (entityEnum.getType().equals(type)) {
+                return entityEnum.getContent();
+            }
+        }
+        return null;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getPushType() {
+        return pushType;
+    }
+
+    public void setPushType(String pushType) {
+        this.pushType = pushType;
+    }
+}

+ 49 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/enums/SmsCodeEnum.java

@@ -0,0 +1,49 @@
+package com.sckw.stream.enums;
+
+public enum SmsCodeEnum {
+    VERIFICATION_CODE("SMS_262585113", "验证码", "您的验证码为:${code},该验证码为平台重要凭证,请勿泄露于他人!");
+
+    private String name;
+
+    private String title;
+
+    private String value;
+
+    /**
+     * @description 构造方法
+     * @author zk
+     * @date 2020/6/08 11:28
+     * @param value 键 标题 类型 name 值
+     * @return
+     **/
+    private SmsCodeEnum(String name, String title, String value){
+        this.name = name;
+        this.value = value;
+        this.value = value;
+    }
+
+    public static String getNameByValue(String value) {
+        for (SmsCodeEnum entityEnum : SmsCodeEnum.values()) {
+            if (entityEnum.getValue().equals(value)) {
+                return entityEnum.getName();
+            }
+        }
+        return null;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+}

+ 30 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/Person.java

@@ -0,0 +1,30 @@
+package com.sckw.stream.model;
+
+import com.sckw.stream.enums.MessageEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Person {
+
+    private String name;
+
+    /**
+     * 消息跳转url
+     */
+    private String msgUrl;
+
+    /**
+     * 推送设备类型
+     */
+    private String pushType;
+
+    /**
+     * 短信模板code
+     */
+    private MessageEnum messageEnum;
+}
+

+ 61 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/SckwMessage.java

@@ -0,0 +1,61 @@
+package com.sckw.stream.model;
+
+import com.sckw.stream.enums.MessageEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.Map;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SckwMessage {
+
+    /**
+     * 短信模板code
+     */
+    private MessageEnum messageEnum;
+
+    /**
+     * 消息跳转参数
+     */
+    private Map<String, Object> params;
+
+    /**
+     * 消息跳转url
+     */
+    private String msgUrl;
+
+    /**
+     * 推送设备类型
+     */
+    private String pushType;
+
+    /**
+     * 定时推送开始时间
+     */
+    private Date pushTime;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 推送用户
+     */
+    private String userIds;
+
+    /**
+     * 移动端推送
+     */
+    private boolean appPush;
+
+    /**
+     * 推送设备id
+     */
+    private String clientId;
+}
+

+ 44 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/model/SckwSms.java

@@ -0,0 +1,44 @@
+package com.sckw.stream.model;
+
+import com.sckw.stream.enums.SmsCodeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.util.Map;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SckwSms {
+
+    /**
+     * 短信模板code
+     */
+    private SmsCodeEnum templateCode;
+
+    /**
+     * 手机号
+     */
+    private String telephone;
+
+    /**
+     * 手机号集合(腾讯短信)
+     */
+    private String[] phoneNumSet;
+
+    /**
+     * 模板参数
+     */
+    private Map<String, Object> params;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 签名
+     */
+    private String signName;
+}
+

+ 76 - 0
sckw-common/sckw-common-stream/src/main/java/com/sckw/stream/utils/SmsUtil.java

@@ -0,0 +1,76 @@
+package com.sckw.stream.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import com.sckw.stream.enums.SmsCodeEnum;
+import com.sckw.stream.model.SckwSms;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+
+public class SmsUtil {
+    //替换成自己申请的accessKeyId
+    private static String accessKeyId = "LTAI5tEyvh6N9HhxDMkW2MqT"; //替换成自己申请的accessKeySecret
+    private static String accessKeySecret = "ClQ2q9fxytnhDraX7axAOjlK0zGJAP";
+    static final String product = "Dysmsapi";
+    static final String domain = "dysmsapi.aliyuncs.com";
+    //{"accessKeyId":"LTAI5tEyvh6N9HhxDMkW2MqT","accessKeySecret":"ClQ2q9fxytnhDraX7axAOjlK0zGJAP","signName":"矿拉拉"}
+
+    /**
+     * 发送短信
+     *
+     * @param phoneNumbers 要发送短信到哪个手机号
+     * @param signName     短信签名[必须使用前面申请的]
+     * @param templateCode 短信短信模板ID[必须使用前面申请的]
+     * @param param        模板中${code}位置传递的内容
+     */
+    public static void sendSms(String phoneNumbers, String signName, String templateCode, String param) {
+        try {
+            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+            //初始化acsClient,暂不支持region化
+            String accessKeySecret = "ClQ2q9fxytnhDraX7axAOjlK0zGJAP";
+            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+
+            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
+            IAcsClient acsClient = new DefaultAcsClient(profile);
+            SendSmsRequest request = new SendSmsRequest();
+            request.setPhoneNumbers(phoneNumbers);
+            request.setSignName(signName);
+            request.setTemplateCode(templateCode);
+            request.setTemplateParam(param);
+            request.setOutId("yourOutId");
+            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+            if (!"OK".equals(sendSmsResponse.getCode())) {
+                throw new RuntimeException(sendSmsResponse.getMessage());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("发送短信失败");
+        }
+    }
+
+    public static void main(String[] args) {
+        SckwSms sckwSms = new SckwSms();
+        sckwSms.setTelephone("17358629955");
+        sckwSms.setSignName("矿拉拉");
+        sckwSms.setTemplateCode(SmsCodeEnum.VERIFICATION_CODE);
+        sckwSms.setParams(new HashMap(){{put("code", "123456");}});
+        try {
+            //发送短信 {"code":"123456"}
+            SmsUtil.sendSms(sckwSms.getTelephone(), sckwSms.getSignName(), sckwSms.getTemplateCode().getName(), JSON.toJSONString(sckwSms.getParams()));
+            System.out.println("短信发送成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+}
+

+ 57 - 0
sckw-gateway/pom.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sckw</groupId>
+        <artifactId>sckw-service-platform</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>sckw-gateway</artifactId>
+    <version>1.0.0</version>
+    <description>网关服务</description>
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <spring-cloud-gateway.version>4.0.1</spring-cloud-gateway.version>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-common-core</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <!--注册中心客户端-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!--配置中心客户端-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+        <!--GateWay ⽹关-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+        <!--负载均衡-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 19 - 0
sckw-gateway/src/main/java/com/sckw/gateway/GatewayApplication.java

@@ -0,0 +1,19 @@
+package com.sckw.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * @author zk
+ * @description 网关服务
+ * @date 2023/5/14 21:12
+ **/
+@EnableDiscoveryClient
+@SpringBootApplication
+public class GatewayApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GatewayApplication.class, args);
+    }
+}

+ 5 - 0
sckw-gateway/src/main/resources/banner.txt

@@ -0,0 +1,5 @@
+====================================================================================================================
+
+                    欢迎使用 [sckw-gateway] 开物供应链服务平台-网关服务 - Powered By https://www.xxxx.com
+
+====================================================================================================================

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