zy 1 سال پیش
کامیت
52493dcf25
100فایلهای تغییر یافته به همراه9984 افزوده شده و 0 حذف شده
  1. 47 0
      .gitignore
  2. 25 0
      GumbelmaximumorderstatisticProbabilityPlotOutput.txt
  3. 25 0
      TwoParameterWeibullProbabilityPlotOutput.txt
  4. 314 0
      pom.xml
  5. 25 0
      wps-biz/TwoParameterWeibullProbabilityPlotOutput.txt
  6. 216 0
      wps-biz/pom.xml
  7. 22 0
      wps-biz/src/main/java/com/jiayue/WpsApplication.java
  8. 17 0
      wps-biz/src/main/java/com/jiayue/WpsServletInitializer.java
  9. 308 0
      wps-biz/src/main/java/com/jiayue/biz/conf/Channel.java
  10. 47 0
      wps-biz/src/main/java/com/jiayue/biz/conf/RequestDataHelper.java
  11. 54 0
      wps-biz/src/main/java/com/jiayue/biz/domain/EquipmentAttribute.java
  12. 33 0
      wps-biz/src/main/java/com/jiayue/biz/domain/PointAttribute.java
  13. 30 0
      wps-biz/src/main/java/com/jiayue/biz/domain/TunnelInfo.java
  14. 51 0
      wps-biz/src/main/java/com/jiayue/biz/eunms/ProvinceEnum.java
  15. 35 0
      wps-biz/src/main/java/com/jiayue/biz/eunms/WindDirectionEnum.java
  16. 9 0
      wps-biz/src/main/java/com/jiayue/biz/mapper/PointAttributeMapper.java
  17. 9 0
      wps-biz/src/main/java/com/jiayue/biz/mapper/TunnelInfoMapper.java
  18. 7 0
      wps-biz/src/main/java/com/jiayue/biz/service/PointAttributeService.java
  19. 7 0
      wps-biz/src/main/java/com/jiayue/biz/service/TunnelInfoService.java
  20. 30 0
      wps-biz/src/main/java/com/jiayue/biz/service/impl/PointAttributeServiceImpl.java
  21. 14 0
      wps-biz/src/main/java/com/jiayue/biz/service/impl/TunnelInfoServiceImpl.java
  22. 394 0
      wps-biz/src/main/java/com/jiayue/biz/util/CommonUtil.java
  23. 197 0
      wps-biz/src/main/java/com/jiayue/biz/util/DateMomentUtil.java
  24. 344 0
      wps-biz/src/main/java/com/jiayue/biz/util/DateTimeUtil.java
  25. 276 0
      wps-biz/src/main/java/com/jiayue/biz/util/FileUtil.java
  26. 138 0
      wps-biz/src/main/java/com/jiayue/biz/util/SEDateUtil.java
  27. 100 0
      wps-biz/src/main/resources/application-dev.yml
  28. 93 0
      wps-biz/src/main/resources/application-prod.yml
  29. 195 0
      wps-biz/src/main/resources/application.yml
  30. 110 0
      wps-biz/src/main/resources/logback-nerp.xml
  31. 237 0
      wps-system/pom.xml
  32. 27 0
      wps-system/src/main/java/com/jiayue/common/annotation/DataScope.java
  33. 24 0
      wps-system/src/main/java/com/jiayue/common/annotation/DataSource.java
  34. 175 0
      wps-system/src/main/java/com/jiayue/common/annotation/Excel.java
  35. 18 0
      wps-system/src/main/java/com/jiayue/common/annotation/Excels.java
  36. 45 0
      wps-system/src/main/java/com/jiayue/common/annotation/Log.java
  37. 40 0
      wps-system/src/main/java/com/jiayue/common/annotation/RateLimiter.java
  38. 29 0
      wps-system/src/main/java/com/jiayue/common/annotation/RepeatSubmit.java
  39. 131 0
      wps-system/src/main/java/com/jiayue/common/config/ElfConfig.java
  40. 186 0
      wps-system/src/main/java/com/jiayue/common/constant/GenConstants.java
  41. 176 0
      wps-system/src/main/java/com/jiayue/common/constant/Global.java
  42. 89 0
      wps-system/src/main/java/com/jiayue/common/constant/HttpStatus.java
  43. 56 0
      wps-system/src/main/java/com/jiayue/common/constant/ScheduleConstants.java
  44. 111 0
      wps-system/src/main/java/com/jiayue/common/constant/UserConstants.java
  45. 169 0
      wps-system/src/main/java/com/jiayue/common/core/controller/BaseController.java
  46. 154 0
      wps-system/src/main/java/com/jiayue/common/core/domain/AjaxResult.java
  47. 82 0
      wps-system/src/main/java/com/jiayue/common/core/domain/AuditEntity.java
  48. 47 0
      wps-system/src/main/java/com/jiayue/common/core/domain/BaseEntity.java
  49. 78 0
      wps-system/src/main/java/com/jiayue/common/core/domain/TreeEntity.java
  50. 74 0
      wps-system/src/main/java/com/jiayue/common/core/domain/TreeSelect.java
  51. 176 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysDictData.java
  52. 97 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysDictType.java
  53. 261 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysMenu.java
  54. 232 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysRole.java
  55. 235 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysUnit.java
  56. 342 0
      wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysUser.java
  57. 69 0
      wps-system/src/main/java/com/jiayue/common/core/domain/model/LoginBody.java
  58. 268 0
      wps-system/src/main/java/com/jiayue/common/core/domain/model/LoginUser.java
  59. 10 0
      wps-system/src/main/java/com/jiayue/common/core/domain/model/RegisterBody.java
  60. 92 0
      wps-system/src/main/java/com/jiayue/common/core/page/PageDomain.java
  61. 85 0
      wps-system/src/main/java/com/jiayue/common/core/page/TableDataInfo.java
  62. 53 0
      wps-system/src/main/java/com/jiayue/common/core/page/TableSupport.java
  63. 228 0
      wps-system/src/main/java/com/jiayue/common/core/redis/RedisCache.java
  64. 91 0
      wps-system/src/main/java/com/jiayue/common/core/text/CharsetKit.java
  65. 854 0
      wps-system/src/main/java/com/jiayue/common/core/text/Convert.java
  66. 77 0
      wps-system/src/main/java/com/jiayue/common/core/text/StrFormatter.java
  67. 20 0
      wps-system/src/main/java/com/jiayue/common/enums/BusinessStatus.java
  68. 59 0
      wps-system/src/main/java/com/jiayue/common/enums/BusinessType.java
  69. 19 0
      wps-system/src/main/java/com/jiayue/common/enums/DataSourceType.java
  70. 18 0
      wps-system/src/main/java/com/jiayue/common/enums/LimitType.java
  71. 24 0
      wps-system/src/main/java/com/jiayue/common/enums/OperatorType.java
  72. 30 0
      wps-system/src/main/java/com/jiayue/common/enums/UserStatus.java
  73. 15 0
      wps-system/src/main/java/com/jiayue/common/exception/DemoModeException.java
  74. 52 0
      wps-system/src/main/java/com/jiayue/common/exception/GlobalException.java
  75. 65 0
      wps-system/src/main/java/com/jiayue/common/exception/ServiceException.java
  76. 26 0
      wps-system/src/main/java/com/jiayue/common/exception/UtilException.java
  77. 85 0
      wps-system/src/main/java/com/jiayue/common/exception/base/BaseException.java
  78. 17 0
      wps-system/src/main/java/com/jiayue/common/exception/file/FileException.java
  79. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/file/FileNameLengthLimitExceededException.java
  80. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/file/FileSizeLimitExceededException.java
  81. 69 0
      wps-system/src/main/java/com/jiayue/common/exception/file/InvalidExtensionException.java
  82. 34 0
      wps-system/src/main/java/com/jiayue/common/exception/job/TaskException.java
  83. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/user/CaptchaException.java
  84. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/user/CaptchaExpireException.java
  85. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/user/UserException.java
  86. 16 0
      wps-system/src/main/java/com/jiayue/common/exception/user/UserPasswordNotMatchException.java
  87. 47 0
      wps-system/src/main/java/com/jiayue/common/filter/RepeatableFilter.java
  88. 67 0
      wps-system/src/main/java/com/jiayue/common/filter/RepeatedlyRequestWrapper.java
  89. 69 0
      wps-system/src/main/java/com/jiayue/common/filter/XssFilter.java
  90. 98 0
      wps-system/src/main/java/com/jiayue/common/filter/XssHttpServletRequestWrapper.java
  91. 113 0
      wps-system/src/main/java/com/jiayue/common/utils/Arith.java
  92. 70 0
      wps-system/src/main/java/com/jiayue/common/utils/DateUtil.java
  93. 160 0
      wps-system/src/main/java/com/jiayue/common/utils/DictUtils.java
  94. 35 0
      wps-system/src/main/java/com/jiayue/common/utils/ExceptionUtil.java
  95. 18 0
      wps-system/src/main/java/com/jiayue/common/utils/LogUtils.java
  96. 26 0
      wps-system/src/main/java/com/jiayue/common/utils/MessageUtils.java
  97. 32 0
      wps-system/src/main/java/com/jiayue/common/utils/PageUtils.java
  98. 100 0
      wps-system/src/main/java/com/jiayue/common/utils/SecurityUtils.java
  99. 130 0
      wps-system/src/main/java/com/jiayue/common/utils/ServletUtils.java
  100. 100 0
      wps-system/src/main/java/com/jiayue/common/utils/Threads.java

+ 47 - 0
.gitignore

@@ -0,0 +1,47 @@
+######################################################################
+# Build Tools
+
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+######################################################################
+# IDE
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### JRebel ###
+rebel.xml
+
+### NetBeans ###
+nbproject/private/
+build/*
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+######################################################################
+# Others
+*.log
+*.xml.versionsBackup
+*.swp
+
+!*/build/*.java
+!*/build/*.html
+!*/build/*.xml

+ 25 - 0
GumbelmaximumorderstatisticProbabilityPlotOutput.txt

@@ -0,0 +1,25 @@
+Gumbel (maximum order statistic) Probability Plot
+
+Tuesday, 20 September 2022, 18.30
+
+Unweighted constrained simplex regression
+
+Gradient:  1.0           s.e. 0.1473
+Intercept: 9.1355E-8     s.e. 3.5125
+
+Correlation Coefficient, r: 0.8051
+Critical Value for r:       0.6694
+Significance level used:    5.0%
+Sum of squares:             11.1542
+
+Best Estimates of the Parameters
+mu:     22.397      'pseudo-linear' s.e. 0.424
+sigma:  2.5638      'pseudo-linear' s.e. 0.3777
+
+The 'pseudo-linear' s.e.s are a lower limit to the s.e. and may significantly underestimate the s.e.
+See documentation, http://www.ee.ucl.ac.uk/~mflanaga/java/ProbabilityPlot.html, for details
+
+'Pseudo-linear' Parameter-Parameter Correlation Coefficients
+        mu          sigma       
+mu      1.0         -0.4533     
+sigma   -0.4533     1.0         

+ 25 - 0
TwoParameterWeibullProbabilityPlotOutput.txt

@@ -0,0 +1,25 @@
+Two Parameter Weibull Probability Plot
+
+Tuesday, 21 February 2023, 10.10
+
+Unweighted constrained simplex regression
+
+Gradient:  1.0479        s.e. 0.0105
+Intercept: -0.4092       s.e. 0.0832
+
+Correlation Coefficient, r: 0.9699
+Critical Value for r:       0.0501
+Significance level used:    5.0%
+Sum of squares:             310.8105
+
+Best Estimates of the Parameters
+sigma:  8.3156      'pseudo-linear' s.e. 0.0328
+gamma:  2.7443      'pseudo-linear' s.e. 0.0312
+
+The 'pseudo-linear' s.e.s are a lower limit to the s.e. and may significantly underestimate the s.e.
+See documentation, http://www.ee.ucl.ac.uk/~mflanaga/java/ProbabilityPlot.html, for details
+
+'Pseudo-linear' Parameter-Parameter Correlation Coefficients
+        sigma       gamma       
+sigma   1.0         0.2401      
+gamma   0.2401      1.0         

+ 314 - 0
pom.xml

@@ -0,0 +1,314 @@
+<?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>
+
+    <groupId>com.jiayue</groupId>
+    <artifactId>wps</artifactId>
+    <version>1.0.0</version>
+
+    <name>wps</name>
+    <url>www.jiayuepowertech.com</url>
+    <description>风压管理平台</description>
+
+    <properties>
+        <wps.version>1.0.0</wps.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+        <spring-boot.version>2.5.13</spring-boot.version>
+        <druid.version>1.2.16</druid.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <swagger.version>3.0.0</swagger.version>
+        <kaptcha.version>2.3.2</kaptcha.version>
+        <pagehelper.boot.version>1.4.1</pagehelper.boot.version>
+        <fastjson.version>1.2.80</fastjson.version>
+        <oshi.version>6.1.2</oshi.version>
+        <jna.version>5.10.0</jna.version>
+        <commons.io.version>2.11.0</commons.io.version>
+        <commons.fileupload.version>1.4</commons.fileupload.version>
+        <commons.collections.version>3.2.2</commons.collections.version>
+        <poi.version>4.1.2</poi.version>
+        <velocity.version>2.3</velocity.version>
+        <jwt.version>0.9.1</jwt.version>
+        <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
+        <jasypt.version>2.1.1</jasypt.version>
+        <hutool.version>5.7.18</hutool.version>
+        <dynamic-datasource.version>3.6.1</dynamic-datasource.version>
+    </properties>
+
+    <!-- 依赖声明 -->
+    <dependencyManagement>
+        <dependencies>
+
+            <!-- SpringBoot的依赖配置-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- 阿里数据库连接池 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+
+            <!-- 解析客户端操作系统、浏览器等 -->
+            <dependency>
+                <groupId>eu.bitwalker</groupId>
+                <artifactId>UserAgentUtils</artifactId>
+                <version>${bitwalker.version}</version>
+            </dependency>
+
+            <!-- pagehelper 分页插件 -->
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper-spring-boot-starter</artifactId>
+                <version>${pagehelper.boot.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.mybatis</groupId>
+                        <artifactId>mybatis</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <!-- 获取系统信息 -->
+            <dependency>
+                <groupId>com.github.oshi</groupId>
+                <artifactId>oshi-core</artifactId>
+                <version>${oshi.version}</version>
+            </dependency>
+
+            <!-- 调用dll动态链接库 -->
+            <dependency>
+                <groupId>net.java.dev.jna</groupId>
+                <artifactId>jna</artifactId>
+                <version>${jna.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>net.java.dev.jna</groupId>
+                <artifactId>jna-platform</artifactId>
+                <version>${jna.version}</version>
+            </dependency>
+
+            <!-- Swagger3依赖 -->
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-boot-starter</artifactId>
+                <version>${swagger.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>io.swagger</groupId>
+                        <artifactId>swagger-models</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <!-- io常用工具类 -->
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${commons.io.version}</version>
+            </dependency>
+
+            <!-- 文件上传工具类 -->
+            <dependency>
+                <groupId>commons-fileupload</groupId>
+                <artifactId>commons-fileupload</artifactId>
+                <version>${commons.fileupload.version}</version>
+            </dependency>
+
+            <!-- excel工具 -->
+            <dependency>
+                <groupId>org.apache.poi</groupId>
+                <artifactId>poi-ooxml</artifactId>
+                <version>${poi.version}</version>
+            </dependency>
+
+            <!-- velocity代码生成使用模板 -->
+            <dependency>
+                <groupId>org.apache.velocity</groupId>
+                <artifactId>velocity-engine-core</artifactId>
+                <version>${velocity.version}</version>
+            </dependency>
+
+            <!-- collections工具类 -->
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>${commons.collections.version}</version>
+            </dependency>
+
+            <!-- 阿里JSON解析器 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!-- Token生成与解析-->
+            <dependency>
+                <groupId>io.jsonwebtoken</groupId>
+                <artifactId>jjwt</artifactId>
+                <version>${jwt.version}</version>
+            </dependency>
+
+            <!-- 验证码 -->
+            <dependency>
+                <groupId>com.github.penggle</groupId>
+                <artifactId>kaptcha</artifactId>
+                <version>${kaptcha.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>mybatis-plus-boot-starter</artifactId>
+                <version>${mybatis-plus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>mybatis-plus-extension</artifactId>
+                <version>${mybatis-plus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-all</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+                <version>${dynamic-datasource.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <modules>
+        <module>wps-system</module>
+        <module>wps-biz</module>
+    </modules>
+    <packaging>pom</packaging>
+
+
+    <dependencies>
+        <!-- 配置文件处理器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- jasypt配置文件加解密 -->
+        <dependency>
+            <groupId>com.github.ulisesbocchio</groupId>
+            <artifactId>jasypt-spring-boot-starter</artifactId>
+            <version>${jasypt.version}</version>
+        </dependency>
+        <!-- 监控 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <!-- Lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </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.1</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArgs>
+                        <!-- 过期方法警告 -->
+                        <arg>-Xlint:deprecation</arg>
+                    </compilerArgs>
+                    <compilerArguments>
+                        <!-- 解决maven命令编译报错,因为rt.jar 和jce.jar在jre的lib下面,不在jdk的lib下面,
+                        导致maven找不到(java7以后会出现这个问题)-->
+                        <bootclasspath>${java.home}\lib\rt.jar;${java.home}\lib\jce.jar</bootclasspath>
+                    </compilerArguments>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <!-- 打包该目录下的 application.yml -->
+                <directory>src/main/resources</directory>
+                <!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <profiles>
+        <profile>
+            <id>dev</id>
+            <properties>
+                <!-- 环境标识,需要与配置文件的名称相对应 -->
+                <profiles.active>dev</profiles.active>
+                <logging.level>debug</logging.level>
+            </properties>
+            <activation>
+                <!-- 默认环境 -->
+                <activeByDefault>true</activeByDefault>
+            </activation>
+        </profile>
+        <profile>
+            <id>prod</id>
+            <properties>
+                <profiles.active>prod</profiles.active>
+                <logging.level>warn</logging.level>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>

+ 25 - 0
wps-biz/TwoParameterWeibullProbabilityPlotOutput.txt

@@ -0,0 +1,25 @@
+Two Parameter Weibull Probability Plot
+
+Thursday, 18 August 2022, 9.20
+
+Unweighted constrained simplex regression
+
+Gradient:  1.0259        s.e. 0.001
+Intercept: -0.2705       s.e. 0.0098
+
+Correlation Coefficient, r: 0.9941
+Critical Value for r:       0.0072
+Significance level used:    5.0%
+Sum of squares:             5771.7308
+
+Best Estimates of the Parameters
+sigma:  9.4273      'pseudo-linear' s.e. 0.0049
+gamma:  2.0973      'pseudo-linear' s.e. 0.0025
+
+The 'pseudo-linear' s.e.s are a lower limit to the s.e. and may significantly underestimate the s.e.
+See documentation, http://www.ee.ucl.ac.uk/~mflanaga/java/ProbabilityPlot.html, for details
+
+'Pseudo-linear' Parameter-Parameter Correlation Coefficients
+        sigma       gamma       
+sigma   1.0         0.4239      
+gamma   0.4239      1.0         

+ 216 - 0
wps-biz/pom.xml

@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>wps</artifactId>
+        <groupId>com.jiayue</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>wps-biz</artifactId>
+
+    <description>
+        wps-biz业务模块
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.taosdata.jdbc</groupId>
+            <artifactId>taos-jdbcdriver</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>2.9.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>javax.mail</artifactId>
+            <version>1.5.4</version>
+        </dependency>
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
+        </dependency>
+<!--        modbus-->
+        <dependency>
+            <groupId>wei.yigulu</groupId>
+            <artifactId>protocol-modbus</artifactId>
+            <version>1.2.11</version>
+        </dependency>
+        <!-- 系统服务-->
+        <dependency>
+            <groupId>com.jiayue</groupId>
+            <artifactId>wps-system</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+
+    </dependencies>
+
+    <profiles>    <!--考虑到window 和linux环境 npm命令格式的问题,使用maven的profile实现动态指定命令-->
+        <profile>
+            <id>window</id>
+            <properties>
+                <npm>npm.cmd</npm>
+            </properties>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+        </profile>
+        <profile>
+            <id>linux</id>
+            <properties>
+                <npm>npm</npm>
+            </properties>
+        </profile>
+    </profiles>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <!--跳过test类-->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.21.0</version>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+            <!-- 插件maven-clean-plugin,用于在编译前,清除之前编译的文件、文件夹等,避免残留之前的内容 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-clean-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <!-- Vue项目打包自动生成的dist目录 -->
+                            <directory>../wps-ui/dist</directory>
+                        </fileset>
+                        <fileset>
+                            <!-- 最终项目打包自动生成的package目录 -->
+                            <directory>../package/wps/${project.version}</directory>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>1.6.0</version>
+                <executions>
+                    <execution>
+                        <id>exec-npm-install</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <executable>${npm}</executable>
+                            <arguments>
+                                <argument>install</argument>
+                            </arguments>
+                            <workingDirectory>../wps-ui</workingDirectory>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>exec-npm-run-build</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <executable>${npm}</executable>
+                            <arguments>
+                                <argument>run</argument>
+                                <argument>build:prod</argument>
+                            </arguments>
+                            <workingDirectory>../wps-ui</workingDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <nonFilteredFileExtensions>
+                        <nonFilteredFileExtension>woff</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>woff2</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>eot</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>swf</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>ico</nonFilteredFileExtension>
+                        <nonFilteredFileExtension>png</nonFilteredFileExtension>
+                    </nonFilteredFileExtensions>
+                    <includeEmptyDirs>true</includeEmptyDirs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>copy static</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <!-- 复制前端打包文件到这里 -->
+                            <outputDirectory>../package/wps/${project.version}/vue</outputDirectory>
+                            <overwrite>true</overwrite>
+                            <resources>
+                                <resource>
+                                    <!-- 从前端打包的目录dist进行指定文件、文件夹内容的复制-->
+                                    <directory>../wps-ui</directory>
+                                    <includes>
+                                        <!-- 具体根据实际前端代码、及目录结构进行配置-->
+                                        <include>dist/</include>
+                                        <include>nginx.conf</include>
+                                        <include>index.html</include>
+                                        <include>robots.txt</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.7.RELEASE</version>
+                <configuration>
+                    <outputDirectory>../package/wps/${project.version}/java</outputDirectory>
+                    <!--控制是否启用支持Linux下service方式运行-->
+                    <executable>true</executable>
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build-info</goal>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 22 - 0
wps-biz/src/main/java/com/jiayue/WpsApplication.java

@@ -0,0 +1,22 @@
+package com.jiayue;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * 启动程序
+ *
+ * @author L.ym
+ * @date 2022-05-10
+ **/
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+@EnableScheduling
+public class WpsApplication {
+    public static void main(String[] args) {
+        System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(WpsApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  WPS 启动成功   ლ(´ڡ`ლ)゙");
+    }
+}

+ 17 - 0
wps-biz/src/main/java/com/jiayue/WpsServletInitializer.java

@@ -0,0 +1,17 @@
+package com.jiayue;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ *
+ * @author L.ym
+ * @date 2022-05-10
+ **/
+public class WpsServletInitializer extends SpringBootServletInitializer {
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        return application.sources(WpsApplication.class);
+    }
+}

+ 308 - 0
wps-biz/src/main/java/com/jiayue/biz/conf/Channel.java

@@ -0,0 +1,308 @@
+//package com.jiayue.biz.conf;
+//
+//import cn.hutool.core.date.DateTime;
+//import cn.hutool.core.thread.ThreadFactoryBuilder;
+//import com.jiayue.biz.domain.PointAttribute;
+//import com.jiayue.biz.domain.TunnelInfo;
+//import com.jiayue.biz.domain.WindTowerInfo;
+//import com.jiayue.biz.service.PointAttributeService;
+//import com.jiayue.biz.service.TunnelInfoService;
+//import com.jiayue.biz.service.WindTowerInfoService;
+//import com.jiayue.biz.service.impl.PointAttributeServiceImpl;
+//import com.jiayue.biz.service.impl.WindTowerDataParentTableServiceImpl;
+//import com.jiayue.biz.util.CalculationUtil;
+//import com.jiayue.common.annotation.Log;
+//import com.jiayue.common.utils.DateUtil;
+//import io.netty.channel.ChannelFuture;
+//import lombok.AllArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.scheduling.annotation.Scheduled;
+//import wei.yigulu.modbus.domain.FunctionCode;
+//import wei.yigulu.modbus.domain.Obj4RequestRegister;
+//import wei.yigulu.modbus.domain.datatype.IModbusDataType;
+//import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
+//import wei.yigulu.modbus.domain.datatype.NumericModbusData;
+//import wei.yigulu.modbus.exceptiom.ModbusException;
+//import wei.yigulu.modbus.netty.ModbusTcpMasterBuilder;
+//import wei.yigulu.modbus.utils.ModbusRequestDataUtils;
+//
+//import java.math.BigDecimal;
+//import java.util.*;
+//import java.util.concurrent.ExecutorService;
+//import java.util.concurrent.SynchronousQueue;
+//import java.util.concurrent.ThreadPoolExecutor;
+//import java.util.concurrent.TimeUnit;
+//import java.util.stream.Collectors;
+//
+////@Configuration
+//@AllArgsConstructor
+//@Slf4j
+//public class Channel {
+//    private final
+//    TunnelInfoService tunnelInfoService;
+//
+//    private final
+//    PointAttributeService pointAttributeService;
+//
+//    private final
+//    WindTowerDataParentTableServiceImpl windTowerDataParentTableService;
+//    private final
+//    WindTowerInfoService windTowerInfoService;
+//
+//
+//    private final ExecutorService calculatorThread = new ThreadPoolExecutor(15, 1000,
+//            60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactoryBuilder().setNamePrefix("MyRecurringTaskThread-").build());
+//
+//
+//    private HashMap<String, ModbusTcpMasterBuilder> masterMap;
+//
+//
+////    @Bean
+//    public void timingTunnel() {
+//        List<TunnelInfo> tunnelInfoList = tunnelInfoService.list();
+//        tunnelInfoList.clear();
+//        TunnelInfo tunnelInfo1 = new TunnelInfo();
+//        TunnelInfo tunnelInfo2 = new TunnelInfo();
+//        tunnelInfo1.setDataFormat("CDAB");
+////        tunnelInfo1.setIp("192.168.10.75");
+//        tunnelInfo1.setIp("192.168.1.206");
+//        tunnelInfo1.setPort(502);
+//        tunnelInfo1.setStationId("七台河3005");
+//        tunnelInfo1.setEquipmentNo("3005");
+////        tunnelInfo1.setStationId("虎林15244");
+////        tunnelInfo1.setEquipmentNo("15244");
+//
+//        tunnelInfo2.setDataFormat("CDAB");
+//        tunnelInfo2.setIp("192.168.10.75");
+//        tunnelInfo2.setPort(502);
+//        tunnelInfo2.setStationId("虎林15244");
+//        tunnelInfo2.setEquipmentNo("15244");
+//        tunnelInfoList.add(tunnelInfo1);
+//        tunnelInfoList.add(tunnelInfo2);
+//        for (TunnelInfo tunnelInfo : tunnelInfoList) {
+//            ModbusTcpMasterBuilder master = start(tunnelInfo);
+//            masterMap.put(tunnelInfo.getStationId(), master);
+//
+//        }
+//    }
+//
+//    //创建线程
+//    public ModbusTcpMasterBuilder start(TunnelInfo tunnelInfo) {
+//        //创建通道后    对通道map 进行  采集数据
+//        //获取场站id   形成map
+//        ModbusTcpMasterBuilder master = new ModbusTcpMasterBuilder(tunnelInfo.getIp(), tunnelInfo.getPort());
+//        master.getConfigInfoMap().put("stationId", tunnelInfo.getStationId());
+//        //create  会阻塞线程
+//        calculatorThread.execute(master::create);
+//        master.isConnected();
+//        return master;
+//    }
+//
+//    //关闭通道移除连接
+//    public void stop(String stationId) {
+//        if (masterMap.get(stationId).isConnected()) {
+//            masterMap.get(stationId).stop();
+//            masterMap.remove(stationId);
+//        }
+//    }
+//
+////    @Scheduled(cron = "0 0/5 * * * ? ")
+//    public void tunnel() {
+//        List<TunnelInfo> tunnelInfoList = tunnelInfoService.list();
+//        List<PointAttribute> attributeList = pointAttributeService.list();
+//        String time = DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm");
+//        for (Map.Entry<String, ModbusTcpMasterBuilder> masterBuilderEntry : masterMap.entrySet()) {
+//            //获取通道map中的key
+//            String stationId = masterBuilderEntry.getKey();
+//            //风速层高
+//            HashSet<Integer> wsHeightSet = new HashSet<>();
+//            //风向层高
+//            HashSet<Integer> wdHeightSet = new HashSet<>();
+//            //根据通道key获取ip端口号等数据
+//            List<TunnelInfo> tunnelist = tunnelInfoList.stream().filter(t -> t.getStationId().equals(stationId)).collect(Collectors.toList());
+//            TunnelInfo tunnelInfo;
+//            if (!tunnelist.isEmpty()) {
+//                tunnelInfo = tunnelist.get(0);
+//            } else {
+//                //如果此通道不存在 关闭通道
+//                this.stop(stationId);
+//                continue;
+//            }
+//            //根据通道key获取点表数据
+//            List<PointAttribute> pointAttributeList = attributeList.stream().filter(a -> a.getStationId().equals(stationId)).collect(Collectors.toList());
+//            //拿到所有点位
+//            List<Integer> points = pointAttributeList.stream().map(PointAttribute::getPoint).collect(Collectors.toList());
+//            Map<Integer, ModbusDataTypeEnum> pointTypeMap = new HashMap<>();
+//            for (Integer point : points) {
+//                //点位以及点位类型存入map
+//                pointTypeMap.put(point, ModbusDataTypeEnum.valueOf(tunnelInfo.getDataFormat()));
+//            }
+//
+//            //获取连接
+//            ModbusTcpMasterBuilder master = masterBuilderEntry.getValue();
+//            //获取点位信息map
+//            Map<String, Integer> stringStringBuilderMap = savePoints(pointAttributeList, wsHeightSet, wdHeightSet);
+//            WindTowerInfo windTowerInfo = new WindTowerInfo();
+//            //判断是否存在此塔
+//            boolean emptyOfEntity = windTowerInfoService.lambdaQuery().eq(WindTowerInfo::getEquipmentNo, tunnelInfo.getEquipmentNo()).list().isEmpty();
+//            if (emptyOfEntity) {
+//                StringBuilder wsHeightStr = new StringBuilder();
+//                for (Integer height : wsHeightSet) {
+//                    wsHeightStr = wsHeightStr.append(height + ",");
+//                }
+//                String wsHeight = null;
+//                if (wsHeightStr.length() > 0) {
+//                    wsHeight = wsHeightStr.substring(0, wsHeightStr.length() - 1);
+//                }
+//
+//                StringBuilder wdHeightStr = new StringBuilder();
+//                for (Integer height : wsHeightSet) {
+//                    wdHeightStr = wdHeightStr.append(height + ",");
+//                }
+//                String wdHeight = null;
+//                if (wdHeightStr.length() > 0) {
+//                    wdHeight = wdHeightStr.substring(0, wdHeightStr.length() - 1);
+//                }
+//                //存储测风塔信息
+//                windTowerInfo.setEquipmentNo(tunnelist.get(0).getEquipmentNo());
+//                windTowerInfo.setName(tunnelist.get(0).getStationId());
+//                windTowerInfo.setHeights(wsHeight);
+//                windTowerInfo.setWdHeights(wdHeight);
+//                windTowerInfo.setType("2");
+//                windTowerInfoService.save(windTowerInfo);
+//            }
+//            // 例如: key:wsAve val:数据
+//            HashMap<String, BigDecimal> pointMap = new HashMap<>();
+//            //分解成Obj4RequestCoil
+//            List<Obj4RequestRegister> obj4RequestRegisters = null;
+//            try {
+//                obj4RequestRegisters = ModbusRequestDataUtils.splitModbusRequest(pointTypeMap, 1, FunctionCode.READ_HOLDING_REGISTERS);
+//                for (Obj4RequestRegister obj4RequestRegister : obj4RequestRegisters) {
+//                    Map<Integer, IModbusDataType> registerData = ModbusRequestDataUtils.getRegisterData(master, obj4RequestRegister);
+//                    if(!registerData.isEmpty()){
+//                        for (Map.Entry<Integer, IModbusDataType> typeEntry : registerData.entrySet()) {
+//                            for (Map.Entry<String, Integer> entry : stringStringBuilderMap.entrySet()) {
+//                                if (typeEntry.getKey().equals(entry.getValue())) {
+//                                    log.info("点位:{}-----数值:{}",typeEntry.getKey(),((NumericModbusData) typeEntry.getValue()).getValue());
+//                                    //点位一致 置换value
+//                                    pointMap.put(entry.getKey(), ((NumericModbusData) typeEntry.getValue()).getValue());
+//                                }
+//                            }
+//                        }
+//                    }
+//
+//                }
+//            } catch (ModbusException e) {
+//                log.info(e.getMsg());
+//                throw new RuntimeException(e);
+//            }
+//            wsHeightSet.addAll(wdHeightSet);
+//            windTowerDataParentTableService.saveDataForTunnel(pointMap, wsHeightSet,tunnelInfo.getEquipmentNo(),time);
+//        }
+//    }
+//
+//
+//    //获取点表所对应数据
+//    public Map<String, Integer> savePoints(List<PointAttribute> channelPoints, HashSet<Integer> wsHeightSet, HashSet<Integer> wdHeightSet) {
+//        //如果数据库没有此测风塔 读取点表信息增加塔表
+//        HashMap<String, Integer> dataMap = new HashMap<>();
+//        for (PointAttribute channelPoint : channelPoints) {
+//            if(channelPoint.getUnit() == null){
+//                channelPoint.setUnit("");
+//            }
+//            if ((channelPoint.getUnit().equals("y") || channelPoint.getUnit().equals("Y")) && channelPoint.getMeaning().contains("年")) {
+//                dataMap.put("yyyy", channelPoint.getPoint());
+//            } else if ((channelPoint.getUnit().equals("y") || channelPoint.getMeaning().equals("Y")) && channelPoint.getMeaning().contains("月")) {
+//                dataMap.put("MM", channelPoint.getPoint());
+//            } else if (channelPoint.getUnit().equals("d") && channelPoint.getMeaning().contains("日")) {
+//                dataMap.put("dd", channelPoint.getPoint());
+//            } else if (channelPoint.getUnit().equals("h") && channelPoint.getMeaning().contains("时")) {
+//                dataMap.put("HH", channelPoint.getPoint());
+//            } else if (channelPoint.getUnit().equals("m") && channelPoint.getMeaning().contains("分")) {
+//                dataMap.put("mm", channelPoint.getPoint());
+//            }  else if (channelPoint.getMeaning().contains("纬")) {
+//                dataMap.put("latitude", channelPoint.getPoint());
+//            } else if (channelPoint.getMeaning().contains("经")) {
+//                dataMap.put("longitude", channelPoint.getPoint());
+//            } else if (channelPoint.getMeaning().contains("海拔")) {
+//                dataMap.put("elevation", channelPoint.getPoint());
+//            } else if (channelPoint.getMeaning().contains("电压")) {
+//                String status = status(channelPoint.getMeaning());
+//                dataMap.put("v" + status, channelPoint.getPoint());
+//            } else {
+//                String dataType = dataType(channelPoint.getMeaning(), wsHeightSet, wdHeightSet);
+//                if (!dataType.equals("")) {
+//                    dataMap.put(dataType, channelPoint.getPoint());
+//                }
+//            }
+//
+//        }
+//        return dataMap;
+//    }
+//
+//
+//    public String dataType(String str, HashSet<Integer> wsHeightSet, HashSet<Integer> wdHeightSet) {
+//        String typeStr = "";
+//        int index;
+//        if (!str.contains("米") && !str.contains("m")) {
+//            return "";
+//        }
+//        if (str.contains("米")) {
+//            index = str.indexOf("米");
+//        } else {
+//            index = str.indexOf("m");
+//        }
+//        //截取风速
+//        String dataStr = str.substring(0, index);
+//        Integer height = Integer.valueOf(CalculationUtil.getNumberFromString(dataStr));
+//        String dataType = "";
+//        typeStr = status(str);
+//
+//        if (str.contains("风速") && !str.contains("风向")) {
+//            dataType = "ws";
+//            wsHeightSet.add(height);
+//        } else if (str.contains("风向")) {
+//            dataType = "wd";
+//            wdHeightSet.add(height);
+//        } else if (str.contains("湿度")) {
+//            dataType = "rh";
+//            return dataType + typeStr;
+//        } else if (str.contains("温度")) {
+//            dataType = "t";
+//            return dataType + typeStr;
+//        } else if (str.contains("气压") || str.contains("压力")) {
+//            dataType = "pa";
+//            return dataType + typeStr;
+//        }
+//        return dataType + typeStr + height;
+//    }
+//
+//    public String status(String str) {
+//        String typeStr = "";
+//        if (str.contains("平均值") && !str.contains("G")) {
+//            typeStr = "Ave";
+//        } else if (str.contains("方差") || str.contains("标准偏差") || str.contains("标准差")) {
+//            typeStr = "Sta";
+//        } else if (str.contains("最大值") && !str.contains("极大")) {
+//            typeStr = "Max";
+//        } else if (str.contains("最小值")) {
+//            typeStr = "Min";
+//        } else if (str.contains("瞬时")) {
+//            typeStr = "Inst";
+//        } else if (str.contains("极大")) {
+//            typeStr = "Great";
+//        } else if (str.contains("Gust") || str.contains("GUST")) {
+//            typeStr = "Gust";
+//        } else if (str.contains("风速") && str.contains("风向")) {
+//            typeStr = "OnWs";
+//        } else if (str.contains("实时")) {
+//            typeStr = "Now";
+//        }
+//        return typeStr;
+//    }
+//
+//
+//}

+ 47 - 0
wps-biz/src/main/java/com/jiayue/biz/conf/RequestDataHelper.java

@@ -0,0 +1,47 @@
+package com.jiayue.biz.conf;
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+
+import java.util.Map;
+
+/**
+ * 请求参数传递辅助类
+ */
+public class RequestDataHelper {
+    /**
+     * 请求参数存取
+     */
+    private static final ThreadLocal<Map<String, Object>> REQUEST_DATA = new ThreadLocal<>();
+
+    /**
+     * 设置请求参数
+     *
+     * @param requestData 请求参数 MAP 对象
+     */
+    public static void setRequestData(Map<String, Object> requestData) {
+        REQUEST_DATA.set(requestData);
+    }
+
+    /**
+     * 获取请求参数
+     *
+     * @param param 请求参数
+     * @return 请求参数 MAP 对象
+     */
+    public static <T> T getRequestData(String param) {
+        Map<String, Object> dataMap = getRequestData();
+        if (CollectionUtils.isNotEmpty(dataMap)) {
+            return (T) dataMap.get(param);
+        }
+        return null;
+    }
+
+    /**
+     * 获取请求参数
+     *
+     * @return 请求参数 MAP 对象
+     */
+    public static Map<String, Object> getRequestData() {
+        return REQUEST_DATA.get();
+    }
+}

+ 54 - 0
wps-biz/src/main/java/com/jiayue/biz/domain/EquipmentAttribute.java

@@ -0,0 +1,54 @@
+package com.jiayue.biz.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import com.jiayue.common.annotation.Excel;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+
+/**
+ * 数据类型对象 equipment_attribute
+ *
+ * @author L.ym
+ * @date 2022-05-23
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("equipment_attribute")
+public class EquipmentAttribute implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+
+    /** 主键ID */
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    /** 属性的定义 */
+    @Excel(name = "属性的定义")
+    private String explanation;
+
+    /** 属性所对应的的类的属性 */
+    @Excel(name = "属性所对应的的类的属性")
+    private String fieldName;
+
+    /** 计量单位 */
+    @Excel(name = "计量单位")
+    private String measurementUnits;
+
+    /** 设备类型 */
+    @Excel(name = "设备类型")
+    private String equipmentType;
+
+
+    /** 属性作用 */
+    @Excel(name = "属性作用")
+    private String attributeFunction;
+}

+ 33 - 0
wps-biz/src/main/java/com/jiayue/biz/domain/PointAttribute.java

@@ -0,0 +1,33 @@
+package com.jiayue.biz.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 点表属性表
+ *
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+//@TableName("point_attribute")
+public class PointAttribute {
+    //ID
+    @TableId
+    private String id;
+    //点位号
+    private Integer point;
+    //点位含义
+    private String meaning;
+    //单位
+    private String unit;
+    //场站Id
+    private String stationId;
+    //设备编号
+    private String equipmentNo;
+
+
+}

+ 30 - 0
wps-biz/src/main/java/com/jiayue/biz/domain/TunnelInfo.java

@@ -0,0 +1,30 @@
+package com.jiayue.biz.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+/*通道信息表*/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+//@TableName("tunnel_info")
+public class TunnelInfo {
+    /*通道id*/
+    @TableId
+    private String id;
+    // 通道名称
+    private String tunnelName;
+    //ip
+    private String ip;
+    //端口号
+    private int port;
+    //场站Id
+    private String stationId;
+    //数据类型 CDAB
+    private String dataFormat;
+    //设备编号
+    private String equipmentNo;
+
+}

+ 51 - 0
wps-biz/src/main/java/com/jiayue/biz/eunms/ProvinceEnum.java

@@ -0,0 +1,51 @@
+package com.jiayue.biz.eunms;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 省调度中心枚举
+ *
+ * @author zy
+ * @version 1.0
+ * @since 2023/2/20
+ */
+@Getter
+@AllArgsConstructor
+public enum ProvinceEnum {
+    E11(11, "北京市"),
+    E12(12, "天津市"),
+    E13(13, "河北省-冀北"),
+    E17(17, "河北省-南网"),
+    E14(14, "山西省"),
+    E15(15, "内蒙古自治区-蒙东"),
+    E16(16, "内蒙古自治区-蒙西"),
+    E21(21, "辽宁省"),
+    E22(22, "吉林省"),
+    E23(23, "黑龙江省"),
+    E31(31, "上海市"),
+    E32(32, "江苏省"),
+    E33(33, "浙江省"),
+    E34(34, "安徽省"),
+    E35(35, "福建省"),
+    E36(36, "江西省"),
+    E37(37, "山东省"),
+    E41(41, "河南省"),
+    E42(42, "湖北省"),
+    E43(43, "湖南省"),
+    E44(44, "广东省"),
+    E45(45, "广西壮族自治区"),
+    E46(46, "海南省"),
+    E50(50, "重庆市"),
+    E51(51, "四川省"),
+    E52(52, "贵州省"),
+    E53(53, "云南省"),
+    E54(54, "西藏自治区"),
+    E61(61, "陕西省"),
+    E62(62, "甘肃省"),
+    E63(63, "青海省"),
+    E64(64, "宁夏回族自治区"),
+    E65(65, "新疆维吾尔自治区");
+    private Integer code;
+    private String message;
+}

+ 35 - 0
wps-biz/src/main/java/com/jiayue/biz/eunms/WindDirectionEnum.java

@@ -0,0 +1,35 @@
+package com.jiayue.biz.eunms;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+
+import java.math.BigDecimal;
+
+@AllArgsConstructor
+@Getter
+/*玫瑰图风向枚举*/
+public enum WindDirectionEnum {
+    // N的范围为 348.75<wd<360 + 0<wd<11.25
+    N(new BigDecimal(348.75),new BigDecimal(11.25),"北"),
+    NNE(new BigDecimal(11.25),new BigDecimal(33.75),"北东北"),
+    NE(new BigDecimal(33.75),new BigDecimal(56.25),"东北"),
+    ENE(new BigDecimal(56.25),new BigDecimal(78.75),"东东北"),
+    E(new BigDecimal(78.75),new BigDecimal(101.25),"东"),
+    ESE(new BigDecimal(101.25),new BigDecimal(123.75),"东东南"),
+    SE(new BigDecimal(123.75),new BigDecimal(146.25),"东南"),
+    SSE(new BigDecimal(146.25),new BigDecimal(168.75),"南东南"),
+    S(new BigDecimal(168.75),new BigDecimal(191.25),"南"),
+    SSW(new BigDecimal(191.25),new BigDecimal(213.75),"南西南"),
+    SW(new BigDecimal(213.75),new BigDecimal(236.25),"西南"),
+    WSW(new BigDecimal(236.25),new BigDecimal(258.75),"西西南"),
+    W(new BigDecimal(258.75),new BigDecimal(281.25),"西"),
+    WNW(new BigDecimal(281.25),new BigDecimal(303.75),"西西北"),
+    NW(new BigDecimal(303.75),new BigDecimal(326.25),"西北"),
+    NNW(new BigDecimal(326.25),new BigDecimal(348.75),"北西北");
+
+
+    private BigDecimal lower;
+    private BigDecimal upper;
+    private String message;
+}

+ 9 - 0
wps-biz/src/main/java/com/jiayue/biz/mapper/PointAttributeMapper.java

@@ -0,0 +1,9 @@
+package com.jiayue.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jiayue.biz.domain.PointAttribute;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface PointAttributeMapper extends BaseMapper<PointAttribute> {
+}

+ 9 - 0
wps-biz/src/main/java/com/jiayue/biz/mapper/TunnelInfoMapper.java

@@ -0,0 +1,9 @@
+package com.jiayue.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jiayue.biz.domain.TunnelInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface TunnelInfoMapper extends BaseMapper<TunnelInfo> {
+}

+ 7 - 0
wps-biz/src/main/java/com/jiayue/biz/service/PointAttributeService.java

@@ -0,0 +1,7 @@
+package com.jiayue.biz.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.biz.domain.PointAttribute;
+
+public interface PointAttributeService extends IService<PointAttribute> {
+}

+ 7 - 0
wps-biz/src/main/java/com/jiayue/biz/service/TunnelInfoService.java

@@ -0,0 +1,7 @@
+package com.jiayue.biz.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.biz.domain.TunnelInfo;
+
+public interface TunnelInfoService extends IService<TunnelInfo> {
+}

+ 30 - 0
wps-biz/src/main/java/com/jiayue/biz/service/impl/PointAttributeServiceImpl.java

@@ -0,0 +1,30 @@
+package com.jiayue.biz.service.impl;
+
+import cn.hutool.core.thread.ThreadFactoryBuilder;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.biz.domain.PointAttribute;
+import com.jiayue.biz.mapper.PointAttributeMapper;
+import com.jiayue.biz.service.PointAttributeService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Service
+@AllArgsConstructor
+@Slf4j
+public class PointAttributeServiceImpl extends ServiceImpl<PointAttributeMapper, PointAttribute> implements PointAttributeService {
+
+
+    private final ExecutorService calculatorThread = new ThreadPoolExecutor(15, 1000,
+            60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactoryBuilder().setNamePrefix("MyRecurringTaskThread-").build());
+
+
+
+
+
+
+}

+ 14 - 0
wps-biz/src/main/java/com/jiayue/biz/service/impl/TunnelInfoServiceImpl.java

@@ -0,0 +1,14 @@
+package com.jiayue.biz.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.biz.domain.TunnelInfo;
+import com.jiayue.biz.mapper.TunnelInfoMapper;
+import com.jiayue.biz.service.TunnelInfoService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 通道信息
+ */
+@Service
+public class TunnelInfoServiceImpl extends ServiceImpl<TunnelInfoMapper, TunnelInfo> implements TunnelInfoService {
+}

+ 394 - 0
wps-biz/src/main/java/com/jiayue/biz/util/CommonUtil.java

@@ -0,0 +1,394 @@
+package com.jiayue.biz.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.file.FileSystem;
+import java.nio.file.*;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * 通用工具类
+ *
+ * @author zzy
+ * @version 2.0
+ * @since 2018/11/20 17:27
+ */
+@Slf4j
+public abstract class CommonUtil {
+    /**
+     * 获取随机数
+     *
+     * @param min 最小值
+     * @param max 最大值
+     * @return 随机数
+     */
+    public static long getRandom(int min, int max) {
+        return Math.round(Math.random() * (max - min) + min);
+    }
+
+    private static final int BUFFER_SIZE = 2 * 1024;
+    public static Properties props = System.getProperties();
+    public static String osName = props.getProperty("os.name");
+
+    /**
+     * 功能描述: 获取异常堆栈信息
+     *
+     * @param t 异常
+     * @return String 异常堆栈信息
+     */
+    public static String printStackTraceToString(Throwable t) {
+        StringWriter sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw, true));
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * 获取目录下所有文件(按时间排序)
+     *
+     * @param path
+     * @return
+     */
+    public static List<File> getFileSort(String path) {
+
+        List<File> list = getFiles(path, new ArrayList<>());
+
+        if (list != null && list.size() > 0) {
+
+            Collections.sort(list, new Comparator<File>() {
+                public int compare(File file, File newFile) {
+                    if (file.lastModified() < newFile.lastModified()) {
+                        return 1;
+                    } else if (file.lastModified() == newFile.lastModified()) {
+                        return 0;
+                    } else {
+                        return -1;
+                    }
+
+                }
+            });
+
+        }
+
+        return list;
+    }
+
+    /**
+     * 获取目录下所有文件
+     *
+     * @param realpath 文件路径
+     * @param files    返回的文件集合
+     * @return files
+     */
+    public static List<File> getFiles(String realpath, List<File> files) {
+
+        File realFile = new File(realpath);
+        File[] subfiles = realFile.listFiles();
+        for (File file : subfiles) {
+            files.add(file);
+        }
+        return files;
+    }
+
+
+    /**
+     * @param srcDir           压缩文件夹路径
+     * @param out              压缩文件输出流
+     * @param KeepDirStructure 是否保留原来的目录结构,
+     *                         true:保留目录结构;
+     *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
+     * @throws RuntimeException 压缩失败会抛出运行时异常
+     */
+    public static void toZip(String[] srcDir, OutputStream out,
+                             boolean KeepDirStructure) throws RuntimeException, Exception {
+
+
+        long start = System.currentTimeMillis();
+        ZipOutputStream zos = null;
+        try {
+            zos = new ZipOutputStream(out);
+            List<File> sourceFileList = new ArrayList<File>();
+            for (String dir : srcDir) {
+                File sourceFile = new File(dir);
+                sourceFileList.add(sourceFile);
+            }
+            compress(sourceFileList, zos, KeepDirStructure);
+            long end = System.currentTimeMillis();
+        } catch (Exception e) {
+            throw new RuntimeException("zip error from ZipUtils", e);
+        } finally {
+            if (zos != null) {
+                try {
+                    zos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+    }
+
+    /**
+     * 递归压缩方法
+     *
+     * @param sourceFile       源文件
+     * @param zos              zip输出流
+     * @param name             压缩后的名称
+     * @param KeepDirStructure 是否保留原来的目录结构,
+     *                         true:保留目录结构;
+     *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
+     * @throws Exception
+     */
+    private static void compress(File sourceFile, ZipOutputStream zos,
+                                 String name, boolean KeepDirStructure) throws Exception {
+        byte[] buf = new byte[BUFFER_SIZE];
+        if (sourceFile.isFile()) {
+            zos.putNextEntry(new ZipEntry(name));
+            int len;
+            FileInputStream in = new FileInputStream(sourceFile);
+            while ((len = in.read(buf)) != -1) {
+                zos.write(buf, 0, len);
+            }
+            // Complete the entry
+            zos.closeEntry();
+            in.close();
+        } else {
+            File[] listFiles = sourceFile.listFiles();
+            if (listFiles == null || listFiles.length == 0) {
+                if (KeepDirStructure) {
+                    zos.putNextEntry(new ZipEntry(name + "/"));
+                    zos.closeEntry();
+                }
+
+            } else {
+                for (File file : listFiles) {
+                    if (KeepDirStructure) {
+                        compress(file, zos, name + "/" + file.getName(),
+                                KeepDirStructure);
+                    } else {
+                        compress(file, zos, file.getName(), KeepDirStructure);
+                    }
+
+                }
+            }
+        }
+    }
+
+    private static void compress(List<File> sourceFileList,
+                                 ZipOutputStream zos, boolean KeepDirStructure) throws Exception {
+        byte[] buf = new byte[BUFFER_SIZE];
+        for (File sourceFile : sourceFileList) {
+            String name = sourceFile.getName();
+            if (sourceFile.isFile()) {
+                zos.putNextEntry(new ZipEntry(name));
+                int len;
+                FileInputStream in = new FileInputStream(sourceFile);
+                while ((len = in.read(buf)) != -1) {
+                    zos.write(buf, 0, len);
+                }
+                zos.closeEntry();
+                in.close();
+            } else {
+                File[] listFiles = sourceFile.listFiles();
+                if (listFiles == null || listFiles.length == 0) {
+                    if (KeepDirStructure) {
+                        zos.putNextEntry(new ZipEntry(name + "/"));
+                        zos.closeEntry();
+                    }
+
+                } else {
+                    for (File file : listFiles) {
+                        if (KeepDirStructure) {
+                            compress(file, zos, name + "/" + file.getName(),
+                                    KeepDirStructure);
+                        } else {
+                            compress(file, zos, file.getName(),
+                                    KeepDirStructure);
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 字符串转换成为16进制(无需Unicode编码)
+     *
+     * @param str
+     * @return
+     */
+    public static String str2HexStr(String str) {
+        char[] chars = "0123456789ABCDEF".toCharArray();
+        StringBuilder sb = new StringBuilder("");
+        byte[] bs = str.getBytes();
+        int bit;
+        for (int i = 0; i < bs.length; i++) {
+            bit = (bs[i] & 0x0f0) >> 4;
+            sb.append(chars[bit]);
+            bit = bs[i] & 0x0f;
+            sb.append(chars[bit]);
+            // sb.append(' ');
+        }
+        return sb.toString().trim();
+    }
+
+    /**
+     * 16进制直接转换成为字符串(无需Unicode解码)
+     *
+     * @param hexStr
+     * @return
+     */
+    public static String hexStr2Str(String hexStr) {
+        String str = "0123456789ABCDEF";
+        char[] hexs = hexStr.toCharArray();
+        byte[] bytes = new byte[hexStr.length() / 2];
+        int n;
+        for (int i = 0; i < bytes.length; i++) {
+            n = str.indexOf(hexs[2 * i]) * 16;
+            n += str.indexOf(hexs[2 * i + 1]);
+            bytes[i] = (byte) (n & 0xff);
+        }
+        return new String(bytes);
+    }
+
+    public static String byteToString(byte[] b) {
+        StringBuffer stringBuffer = new StringBuffer();
+        for (int i = 0; i < b.length; i++) {
+            stringBuffer.append((char) b[i]);
+        }
+        return stringBuffer.toString();
+    }
+
+    /**
+     * 参数1:原始路径
+     * 参数2:.zip结束后的路径:例:D:\\temp\\playbook_1936_拍照商品照片.zip\\11\\22。此时11\\22\\文件名称就是参数2
+     * 参数3:固定写死的zip路径
+     * 注意: 1:zip压缩包不能动态的添加文件夹,所以在压缩之前需要生成好全部的文件夹。
+     * 2:在往zip包下不同文件夹添加数据时,需要注意:完整路径。例:D:/temp/playbook_1936_拍照商品照片.zip/33/44/时toUrl的路径开始地必须时zip之后第一个开始
+     */
+    public static boolean addZip(String zipUrl, String fromUrl, String toUrl) throws IOException {
+        Map<String, String> env = new HashMap<>();
+        env.put("create", "true");
+        //使用语法定位文件系统
+        //在java.net.JarURLConnection中定义
+        Path path = Paths.get(zipUrl);
+        URI uri = URI.create("jar:" + path.toUri());
+        try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
+            Path externalTxtFile = Paths.get(fromUrl);
+            Path pathInZipfile = zipfs.getPath(toUrl);
+            //将文件复制到zip文件中
+            Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * 写入txt文件
+     *
+     * @param result
+     * @param fileName
+     * @return
+     */
+    public static boolean writeDataHubData(List<String> result, String filePath, String fileName) throws UnsupportedEncodingException {
+        long start = System.currentTimeMillis();
+//        String filePath = "D:\\temp\\txt";
+        filePath = URLDecoder.decode(filePath, "UTF-8");
+        //判断目标文件夹是否存在,不存在则创建
+        File dir = new File(filePath);
+        if (dir.exists()) {
+            if (!dir.isDirectory()) {
+                dir.mkdirs();
+            }
+        } else {
+            dir.mkdirs();
+        }
+        boolean flag = false;
+        BufferedWriter out = null;
+        try {
+            if (result != null && !result.isEmpty() && StringUtils.isNotEmpty(fileName)) {
+                File pathFile = new File(filePath);
+                if (!pathFile.exists()) {
+                    pathFile.mkdirs();
+                }
+                String relFilePath = filePath + File.separator + fileName;
+                File file = new File(relFilePath);
+                if (!file.exists()) {
+                    file.createNewFile();
+                }
+                try {
+                    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
+                    for (String info : result) {
+                        out.write(info);
+                        out.newLine();
+                    }
+                } finally {
+                    if (out != null) {
+                        out.close();
+                    }
+                }
+                flag = true;
+                log.info("写入文件耗时:*********************************" + (System.currentTimeMillis() - start) + "毫秒");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (out != null) {
+                try {
+                    out.flush();
+                    out.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            return flag;
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        File zip = new File("C:/temp/utf-16le1.zip");
+        if (!zip.exists()) {
+            ZipOutputStream zoutput = null;
+            FileOutputStream fOutputStream = null;
+            try {
+                zip.createNewFile();
+                File file = new File("C:/temp/utf-16le1");
+                if (!file.exists())
+                    file.createNewFile();
+                String string = "test ZIP!";
+                byte[] buffer = string.getBytes();
+                fOutputStream = new FileOutputStream(file);
+                zoutput = new ZipOutputStream(fOutputStream);
+                ZipEntry zEntry = new ZipEntry("utf-16le1");
+                zoutput.putNextEntry(zEntry);
+                zoutput.write(buffer);
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                zoutput.close();
+                fOutputStream.close();
+                zoutput.closeEntry();
+            }
+        }
+
+        String zipUrl = "C:/temp/utf-16le1.zip";
+        String fromUrl = "C:/temp/test";
+        String toUrl = "/test";
+        try {
+            boolean result = addZip(zipUrl, fromUrl, toUrl);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+}

+ 197 - 0
wps-biz/src/main/java/com/jiayue/biz/util/DateMomentUtil.java

@@ -0,0 +1,197 @@
+package com.jiayue.biz.util;
+
+import com.sun.istack.internal.NotNull;
+
+import java.util.Calendar;
+
+/**
+ * 时刻工具类
+ *
+ * @author zzy
+ * @version 2.0
+ * @since 2018/11/2 11:31
+ */
+public abstract class DateMomentUtil {
+
+
+    /**
+     * 获取月份
+     *
+     * @param dateTime 时间,单位毫秒
+     * @return 月份
+     */
+    public static Integer getMonth(@NotNull final Long dateTime) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(dateTime);
+        return calendar.get(Calendar.MONTH) + 1;
+    }
+
+    /**
+     * 获取指定时间在当天所处于的时刻
+     * 例如:dateTime:2018-10-22 16:44:00 momentLength: 15分钟,既 15*60*1000毫秒
+     * 从0点0分开始计算,0点0分-0点15为第一个时刻,依次类推该时间的时刻数为67
+     *
+     * @param dateTime     时间毫秒
+     * @param momentLength 时刻长度,单位毫秒
+     * @return 时刻
+     */
+    public static int getMoment(@NotNull final Long dateTime, @NotNull final Long momentLength) {
+        return (int) ((dateTime - DateMomentUtil.getDayStartTime(dateTime)) / momentLength) + 1;
+    }
+
+    /**
+     * 获取指定时间所在时刻的标记时间 <br>
+     * 例如:dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
+     * 当前标记signType:1 那么该时刻的标记时间为2018-10-22 16:30:00
+     * 当后标记singType:2 那么该时刻的标记时间为2018-10-22 16:45:00
+     *
+     * @param dateTime     时间毫秒
+     * @param signType     标记方式:1前标记 2后标记
+     * @param momentLength 时刻长度,单位:毫秒
+     * @return 指定时间所在时刻的标记时间,单位:毫秒
+     */
+    public static long getMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
+        if (24 * 3600 * 1000L % momentLength != 0)
+            throw new Exception("时刻长度非法,时刻长度需要能够被一天整除");
+        int moment = DateMomentUtil.getMoment(dateTime, momentLength);// 获取指定时间所在时刻数
+        long differentTime = moment * momentLength;// 获取从0分0秒开始到现在的时间间隔,单位:毫秒
+        long dayStartTime = DateMomentUtil.getDayStartTime(dateTime);
+        switch (signType) {
+            case 2:
+                return dayStartTime + differentTime;
+            default:
+                return dayStartTime + differentTime - momentLength;
+        }
+    }
+
+    /**
+     * 获取指定时间所在天第一个时刻的标记时间 <br>
+     * 例如:dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
+     * 当前标记signType:1 那么第一个时刻的标记时间为2018-10-22 00:00:00
+     * 当后标记singType:2 那么第一个时刻的标记时间为2018-10-22 00:15:00
+     *
+     * @param dateTime     时间毫秒
+     * @param signType     标记方式:1前标记 2后标记
+     * @param momentLength 时刻长度,单位:毫秒
+     * @return 一天第一个时刻的标记时间,单位:毫秒
+     */
+    public static long getDayFirstMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
+        if (24 * 3600 * 1000L % momentLength != 0)
+            throw new Exception("时刻长度非法,时刻长度需要能够被一天整除");
+        long dayStartTime = DateMomentUtil.getDayStartTime(dateTime);
+        switch (signType) {
+            case 2:
+                return dayStartTime + momentLength;
+            default:
+                return dayStartTime;
+        }
+    }
+
+    /**
+     * 获取指定时间所在天的最后一个时刻的标记时间 <br>
+     * 例如:dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
+     * 当前标记signType:1 那么最后一个时刻的标记时间为2018-10-22 23:45:00
+     * 当后标记singType:2 那么最后一个时刻的标记时间为2018-10-23 00:00:00
+     *
+     * @param dateTime     时间毫秒
+     * @param signType     标记方式:1前标记 2后标记, 当null时按照前标记1处理
+     * @param momentLength 时刻长度,单位:毫秒
+     * @return 一天第一个时刻的标记时间,单位:毫秒
+     */
+    public static long getDayLastMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
+        if (24 * 3600 * 1000L % momentLength != 0)
+            throw new Exception("时刻长度非法,时刻长度需要能够被一天整除");
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.add(Calendar.DATE, 1);
+        date.set(Calendar.HOUR_OF_DAY, 0);
+        date.set(Calendar.MINUTE, 0);
+        date.set(Calendar.SECOND, 0);
+        date.set(Calendar.MILLISECOND, 0);
+        switch (signType) {
+            case 2:
+                return date.getTimeInMillis();
+            default:
+                return date.getTimeInMillis() - momentLength;
+        }
+    }
+
+    /**
+     * 获取指定时间所在天的0点0分
+     *
+     * @param dateTime 时间毫秒
+     * @return 0点0分的毫秒
+     */
+    public static long getDayStartTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 0);
+        date.set(Calendar.MINUTE, 0);
+        date.set(Calendar.SECOND, 0);
+        date.set(Calendar.MILLISECOND, 0);
+        return date.getTimeInMillis();
+    }
+
+    /**
+     * 获取指定时间所在天的23点59分59秒
+     *
+     * @param dateTime 时间毫秒
+     * @return 23点59分59秒的毫秒
+     */
+    public static long getDayLastTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 23);
+        date.set(Calendar.MINUTE, 59);
+        date.set(Calendar.SECOND, 59);
+        date.set(Calendar.MILLISECOND, 999);
+        return date.getTimeInMillis();
+    }
+
+    /**
+     * 获取两个时间间的间隔天数(自然天)
+     * @param dateFrom 开始时间
+     * @param dateTo 结束时间
+     * @return 自然天数
+     */
+    public static Integer getDaysBetweenTwoDate(Long dateFrom, Long dateTo) {
+        return (int) ((DateMomentUtil.getDayStartTime(dateTo) - DateMomentUtil.getDayStartTime(dateFrom)) / (1000 * 60 * 60 * 24L));
+    }
+
+    /**
+     * 获取当前月第一天0点0分
+     * 如果是当月1号的0点-1点直接,则返回上个月的第一天的0点0分
+     * @return 0点0分的毫秒
+     */
+    public static long getMonthFirstDayStartTime() {
+        Calendar date = Calendar.getInstance();
+        //每月1号的0-1点的时间,返回上个月的1号0点
+        if("1".equals(date.get(Calendar.DAY_OF_MONTH)) && date.get(Calendar.HOUR_OF_DAY)<1){
+            date.set(Calendar.MONTH,-1);
+        }
+        date.set(Calendar.DAY_OF_MONTH, 1);
+        date.set(Calendar.HOUR_OF_DAY, 0);
+        date.set(Calendar.MINUTE, 0);
+        date.set(Calendar.SECOND, 0);
+        date.set(Calendar.MILLISECOND, 0);
+        return date.getTimeInMillis();
+    }
+
+    /**
+     * 获取当前时间
+     * 如果是当月1号的0点-1点直接,则返回上个月的最后一天23点59分
+     * @return 0点0分的毫秒
+     */
+    public static long getMonthLastDayStartTime() {
+        Calendar date = Calendar.getInstance();
+        //每月1号的0-1点的时间,返回上个月的1号0点
+        if("1".equals(date.get(Calendar.DAY_OF_MONTH)) && date.get(Calendar.HOUR_OF_DAY)<1){
+            date.set(Calendar.DAY_OF_MONTH, -1);
+            date.set(Calendar.HOUR_OF_DAY, 23);
+            date.set(Calendar.MINUTE, 59);
+            date.set(Calendar.SECOND, 59);
+            date.set(Calendar.MILLISECOND, 999);
+        }
+        return date.getTimeInMillis();
+    }
+}

+ 344 - 0
wps-biz/src/main/java/com/jiayue/biz/util/DateTimeUtil.java

@@ -0,0 +1,344 @@
+package com.jiayue.biz.util;
+
+import com.jiayue.common.utils.DateUtil;
+import com.sun.istack.internal.NotNull;
+import lombok.SneakyThrows;
+import org.apache.commons.lang3.time.DateUtils;
+
+import com.sun.istack.internal.NotNull;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 时间工具类
+ *
+ * @author zzy
+ * @version 1.0
+ * @since 2019/8/2 13:09
+ */
+@SuppressWarnings("WeakerAccess")
+public class DateTimeUtil {
+
+    /**
+     * 获取月份
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 月份
+     */
+    public static int getMonth(@NotNull final Long dateTime) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(dateTime);
+        return calendar.get(Calendar.MONTH) + 1;
+    }
+
+    /**
+     * 获取指定时间在当天所处于的时刻(15分钟为一个时刻)
+     * 例如:dateTime:2018-10-22 16:44:00
+     * 从0点0分开始计算,0点0分-0点15为第一个时刻,依次类推该时间的时刻数为67
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 时刻
+     */
+    public static int getMomentFor15Minute(@NotNull final Long dateTime) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (15 * 60 * 1000)) + 1;
+    }
+
+    /**
+     * 获取指定时间在当天所处于的时刻(5分钟为一个时刻)
+     * 例如:dateTime:2018-10-22 01:44:00
+     * 从0点0分开始计算,0点0分-0点5为第一个时刻,依次类推该时间的时刻数为
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 时刻
+     */
+    public static int getMomentFor5Minute(@NotNull final Long dateTime) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (5 * 60 * 1000)) + 1;
+    }
+
+    /**
+     * 获取指定时间所在时刻的标记时间(15分钟为一个时刻)<br>
+     * 例如:dateTime:2018-10-22 16:44:00 <br>
+     * 标记时间为2018-10-22 16:30:00
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 指定时间所在时刻的标记时间,单位:毫秒
+     */
+    public static Date getMomentTimeFor15Minute(@NotNull final Long dateTime) {
+        int moment = DateTimeUtil.getMomentFor15Minute(dateTime);// 获取指定时间所在时刻数
+        long differentTime = moment * 15 * 60 * 1000;// 获取从0分0秒开始到现在的时间间隔,单位:毫秒
+        long dayStartTime = DateTimeUtil.getDayStartTime(dateTime).getTime();
+        return new Date(dayStartTime + differentTime - 15 * 60 * 1000);
+    }
+
+    /**
+     * 获取指定时间所在时刻的标记时间(5分钟为一个时刻)<br>
+     * 例如:dateTime:2018-10-22 16:44:00 <br>
+     * 标记时间为2018-10-22 16:40:00
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 指定时间所在时刻的标记时间,单位:毫秒
+     */
+    public static Date getMomentTimeFor5Minute(@NotNull final Long dateTime) {
+        int moment = DateTimeUtil.getMomentFor15Minute(dateTime);// 获取指定时间所在时刻数
+        long differentTime = moment * 5 * 60 * 1000;// 获取从0分0秒开始到现在的时间间隔,单位:毫秒
+        long dayStartTime = DateTimeUtil.getDayStartTime(dateTime).getTime();
+        return new Date(dayStartTime + differentTime - 5 * 60 * 1000);
+    }
+
+    /**
+     * 获取当前时间(时间粒度分钟)
+     *
+     * @return 当前时间
+     */
+    public static Date getCurrentTimeForMinute() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定时间所在天的0点0分
+     *
+     * @param dateTime 时间毫秒
+     * @return 0点0分的毫秒
+     */
+    public static Date getDayStartTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 0);
+        date.set(Calendar.MINUTE, 0);
+        date.set(Calendar.SECOND, 0);
+        date.set(Calendar.MILLISECOND, 0);
+        return date.getTime();
+    }
+
+    /**
+     * 今日凌晨 毫秒
+     *
+     * @return 时间
+     */
+    public static long getMillisecondsSubDay() {
+
+        Calendar c = Calendar.getInstance();
+
+        return c.getTimeInMillis() - DateUtils.getFragmentInMilliseconds(c, Calendar.DAY_OF_MONTH);
+    }
+
+    /**
+     * 获取指定时间所在天的23点59分59秒
+     *
+     * @param dateTime 时间毫秒
+     * @return 23点59分59秒的毫秒
+     */
+    public static Date getDayLastTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 23);
+        date.set(Calendar.MINUTE, 59);
+        date.set(Calendar.SECOND, 59);
+        date.set(Calendar.MILLISECOND, 999);
+        return date.getTime();
+    }
+
+    /**
+     * 获取两个时间间的间隔天数(自然天)
+     *
+     * @param dateFrom 开始时间
+     * @param dateTo   结束时间
+     * @return 自然天数
+     */
+    public static int getDaysBetweenTwoDate(Long dateFrom, Long dateTo) {
+        return (int) ((DateTimeUtil.getDayStartTime(dateTo).getTime() - DateTimeUtil.getDayStartTime(dateFrom).getTime()) / (1000 * 60 * 60 * 24L));
+    }
+
+    /**
+     * 获取两个时间间的间隔间隔时刻数(15分钟一个时刻)
+     *
+     * @param dateFrom 开始时间
+     * @param dateTo   结束时间
+     * @return 间隔时刻数
+     */
+    public static int getMomentsBetweenTwoDate(Long dateFrom, Long dateTo) {
+        return (int) ((dateTo - dateFrom) / (15 * 60 * 1000));
+    }
+
+
+    /**
+     * 获取现在时间
+     *
+     * @return 返回字符串格式 yyyy-MM-dd HH:mm:ss
+     */
+    public static String getStringDate() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
+     *
+     * @param dateDate
+     * @return
+     */
+    public static String dateToStrLong(Date dateDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(dateDate);
+        return dateString;
+    }
+
+    /**
+     * 将时间格式字符串转换为时间 HH:mm
+     *
+     * @param strDate
+     * @return
+     */
+    public static Date strToDateLongHM(String strDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
+        ParsePosition pos = new ParsePosition(0);
+        Date strtodate = formatter.parse(strDate, pos);
+        return strtodate;
+    }
+
+    /**
+     * 判断时间是不是今天
+     *
+     * @param date
+     * @return 是返回true,不是返回false
+     */
+    public static boolean isNow(Date date) {
+        //当前时间
+        Date now = new Date();
+        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
+        //获取今天的日期
+        String nowDay = sf.format(now);
+        //对比的时间
+        String day = sf.format(date);
+        return day.equals(nowDay);
+    }
+
+    /**
+     * 获取指定时间所在的月初
+     *
+     * @param date
+     * @return
+     */
+    public static Date beginOfMonth(Date date) {
+        return DateUtil.beginOfMonth(date);
+    }
+
+    /**
+     * 获取指定时间所在的月末
+     *
+     * @param date
+     * @return
+     */
+    public static Date endOfMonth(Date date) {
+        return DateUtil.endOfMonth(date);
+    }
+
+    /**
+     * 将时间戳转换为指定格式并加上分钟
+     *
+     * @param
+     * @param strDate
+     * @param hour
+     * @return
+     */
+    @SneakyThrows
+    public static Date strToDateLongYMDH(long strDate, Integer hour, String minute) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+        String strtodate = formatter.format(new Date(strDate));
+        return formatter2.parse(strtodate + " " + hour + ":" + minute);
+    }
+
+    /**
+     * 时间戳 获取天
+     */
+    public static int getDay(Long time) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        Date date = new Date();
+        String timeString = sdf.format(time);
+        try {
+            date = sdf.parse(timeString);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int day = (calendar.get(Calendar.DAY_OF_MONTH));
+        return day;
+    }
+
+    /*当月的前n个月得第一天*/
+    public static Date mouthOneDay(int num) {
+        Calendar date = Calendar.getInstance();
+        date.set(Calendar.MONDAY, date.get(Calendar.MONDAY) - num);
+        date.set(Calendar.DAY_OF_MONTH, 1);
+        return date.getTime();
+    }
+
+    /*当月的前n个月得最后一天*/
+    public static Date mouthLastDay(int num) {
+        Calendar date = Calendar.getInstance();
+        date.set(Calendar.MONDAY, date.get(Calendar.MONDAY) - num);
+        date.set(Calendar.DAY_OF_MONTH, date.getActualMaximum(Calendar.DAY_OF_MONTH));
+        return date.getTime();
+    }
+
+    /*
+     * 指定去年的某一天
+     *
+     */
+    public static Date getYearDay(Long dayTime) {
+        //过去一年
+        Calendar date = Calendar.getInstance();
+        date.setTime(new Date(dayTime));
+        date.add(Calendar.YEAR, -1);
+        return date.getTime();
+    }
+
+    /**
+     * 按照开始时间结束时间分割出所有月份(开始时间月初 结束时间月末)
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     */
+    public static List<Long> getIntervalTimeByMonth(Date startTime, Date endTime) {
+        startTime = beginOfMonth(startTime);
+        endTime = endOfMonth(endTime);
+        List<Long> dateList = new ArrayList<>();
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(startTime);
+        dateList.add(calendar.getTimeInMillis());
+        while (calendar.getTimeInMillis() < endTime.getTime()) {
+            // 当月底
+            calendar.add(Calendar.MONTH, 1);
+            calendar.set(Calendar.DAY_OF_MONTH, 1);
+            calendar.add(Calendar.DATE, -1);
+            calendar.set(Calendar.HOUR_OF_DAY, 23);
+            calendar.set(Calendar.MINUTE, 59);
+            calendar.set(Calendar.SECOND, 59);
+            if (calendar.getTimeInMillis() >= endTime.getTime()) {
+                dateList.add(endTime.getTime());
+                break;
+            }
+            // 下月初
+            calendar.add(Calendar.DATE, 1);
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            dateList.add(calendar.getTimeInMillis());
+        }
+        dateList.remove(dateList.size() - 1);
+        return dateList;
+    }
+}

+ 276 - 0
wps-biz/src/main/java/com/jiayue/biz/util/FileUtil.java

@@ -0,0 +1,276 @@
+package com.jiayue.biz.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.springframework.util.ResourceUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.security.MessageDigest;
+import java.util.Date;
+
+/**
+ * 文件工具类
+ *
+ * @author xsl
+ * @version 3.0
+ */
+@Slf4j
+public class FileUtil {
+    /**
+     * 移动本地文件
+     *
+     * @param remoteAbsoluteFile 远程文件名(包括完整路径)
+     * @param localAbsoluteFile  本地文件名(包括完整路径)
+     * @return 成功时,返回true,失败返回false
+     * @throws Exception
+     */
+    public static void move(String localAbsoluteFile, String remoteAbsoluteFile) throws Exception {
+        File srcFile = new File(localAbsoluteFile);
+        File destDir = new File(remoteAbsoluteFile);
+        try {
+            if (!destDir.exists()) {// 如果目录不存在则创建目录
+                boolean b = destDir.mkdirs();
+                if (!b) // 如果创建失败则抛出异常
+                    throw new RuntimeException(destDir + " 目录创建失败");
+            }
+            File file = new File(remoteAbsoluteFile + File.separator + srcFile.getName());
+            if(file.exists()){
+                file.delete();
+            }
+            FileUtils.moveFile(srcFile, new File(remoteAbsoluteFile + File.separator + srcFile.getName()));
+        } catch (IOException e) {
+            throw new Exception("文件:" + srcFile.getName() + "移动到" + destDir.getPath() + "失败。", e);
+        }
+    }
+
+    //文件内容md5加密
+    public static String getMD5(byte[] fileByte) {
+        String md5 = new String();
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            md.update(fileByte);
+            byte b[] = md.digest();
+
+            int i;
+
+            StringBuffer buf = new StringBuffer("");
+            for (int offset = 0; offset < b.length; offset++) {
+                i = b[offset];
+                if (i < 0)
+                    i += 256;
+                if (i < 16)
+                    buf.append("0");
+                buf.append(Integer.toHexString(i));
+            }
+
+            md5 = buf.toString();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return md5;
+    }
+
+    /**
+     * 获取文件创建时间
+     *
+     * @param fullFileName
+     * @return
+     */
+    public static Long getFileCreateTime(String fullFileName) {
+        Path path = Paths.get(fullFileName);
+        BasicFileAttributeView basicview = Files.getFileAttributeView(path, BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
+        BasicFileAttributes attr;
+        try {
+            attr = basicview.readAttributes();
+            Date createDate = new Date(attr.creationTime().toMillis());
+            return createDate.getTime();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return new Date().getTime();
+    }
+
+    /**
+     * 获取项目根路径
+     *
+     * @return
+     */
+    public static String getResourceBasePath() {
+        // 获取跟目录
+        File path = null;
+        try {
+            path = new File(ResourceUtils.getURL("classpath:").getPath());
+
+        } catch (FileNotFoundException e) {
+            // nothing to do
+        }
+        if (path == null || !path.exists()) {
+            path = new File("");
+        }
+
+        String pathStr = path.getAbsolutePath();
+        try {
+            pathStr = URLDecoder.decode(pathStr, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        // 如果是在eclipse中运行,则和target同级目录,如果是jar部署到服务器,则默认和jar包同级
+//    pathStr = pathStr.replace("\\target\\classes", "");
+
+        return pathStr;
+    }
+
+    /**
+     * 获取上报文件目录相对路径
+     *
+     * @return
+     */
+    public static String getFileUploadPath() {
+        return createUploadAllDir("uploadFile");
+    }
+
+    /**
+     * 获取上传测风塔附件相对路径
+     *
+     * @return
+     */
+    public static String getEnclosurePath() {
+        return createUploadAllDir("enclosure");
+    }
+
+    /**
+     * 获取下载文件目录相对路径
+     *
+     * @return
+     */
+    public static String getDownloadFilePath() {
+        return createUploadAllDir("downloadFile");
+    }
+
+    /**
+     * 获取下载文件目录相对路径
+     *
+     * @return
+     */
+    public static String getZxglFilePath() {
+        return createUploadAllDir("zxgl");
+    }
+
+    /**
+     * 获取日志目录相对路径
+     *
+     * @return
+     */
+    public static String getLogsPath() {
+        return createUploadAllDir("logs");
+    }
+
+    /**
+     * 获取系统脚本相对路径
+     *
+     * @return
+     */
+    public static String getBinPath() {
+        return createUploadAllDir("bin");
+    }
+
+    /**
+     * 程序备份相对路径
+     *
+     * @return
+     */
+    public static String getOriginalPath() {
+        return createUploadAllDir("original");
+    }
+
+    /**
+     * 系统资料相对路径
+     *
+     * @return
+     */
+    public static String getSystemFilePath() {
+        return createUploadAllDir("systemFile");
+    }
+
+    /**
+     * 获取被删除文件目录
+     *
+     * @return 路径
+     */
+    public static String getDeleteFilePath() {
+        return createUploadAllDir("deleteFile");
+    }
+
+    /**
+     * 程序运行相对路径
+     *
+     * @return
+     */
+    public static String getProducePath() {
+        return createUploadAllDir("produce");
+    }
+
+    /**
+     * 报表相对路径
+     *
+     * @return
+     */
+    public static String getreportFormPath() {
+        return createUploadAllDir("reportForm");
+    }
+
+    /**
+     * 获取临时文件目录相对路径
+     *
+     * @return
+     */
+    public static String getTempFilePath() {
+        return createUploadAllDir("tempFile");
+    }
+
+    public static String getE46Path() {
+        return createUploadAllDir("HN");
+    }
+
+    private static String createUploadAllDir(String dir) {
+        String path = "";
+        /*if (System.getProperties().getProperty("file.separator").equals("\\")) {
+            path = new File(getResourceBasePath()).getParentFile().getParentFile().getParentFile().getAbsolutePath() + File.separator + dir;
+            try {
+                path = URLDecoder.decode(path, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+            File file = new File(path);
+            if (!file.exists()) {
+                boolean b = file.mkdirs();
+                if (!b)
+                    log.error("目录创建失败" + path);
+            }
+        } else {
+            path = "D:\\program\\" + dir;
+        }*/
+        path = "D:\\program\\" + dir;
+        return path;
+    }
+
+    /**
+     * 获取环境数据导出文件目录相对路径
+     *
+     * @return
+     */
+    public static String getEnvironmentalDataFile() {
+        return createUploadAllDir("environmentalDataFile");
+    }
+}

+ 138 - 0
wps-biz/src/main/java/com/jiayue/biz/util/SEDateUtil.java

@@ -0,0 +1,138 @@
+package com.jiayue.biz.util;
+
+import java.util.Calendar;
+import java.util.Date;
+
+public class SEDateUtil {
+
+    /**
+     * 获取指定天的开始时间
+     * @return
+     */
+    public static Date getStartTimeOfCurrentDay(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        setMinTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定天的结束时间
+     * @return
+     */
+    public static Date getEndTimeOfCurrentDay(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        setMaxTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定周的开始时间
+     * @return
+     */
+    public static Date getStartTimeOfCurrentWeek(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        calendar.setFirstDayOfWeek(Calendar.MONDAY);
+        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
+        setMinTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定月的结束时间
+     * @return
+     */
+    public static Date getEndTimeOfCurrentWeek(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        calendar.setFirstDayOfWeek(Calendar.MONDAY);
+        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
+        setMaxTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定月的开始时间
+     * @return
+     */
+    public static Date getStartTimeOfCurrentMonth(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),1);
+        setMinTimeOfDay(calendar);
+        Date time = calendar.getTime();
+        return time;
+    }
+
+    /**
+     * 获取指定月的结束时间
+     * @return
+     */
+    public static Date getEndTimeOfCurrentMonth(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        int maxMonthDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
+        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),maxMonthDay);
+        setMaxTimeOfDay(calendar);
+        Date time = calendar.getTime();
+        return time;
+    }
+
+    /**
+     * 获取指定年的开始时间 注意月份要减1
+     * @return
+     */
+    public static Date getStartTimeOfCurrentYear(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        calendar.set(calendar.get(Calendar.YEAR),0,1);
+        setMinTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定年的结束时间 注意月份要减1
+     * @return
+     */
+    public static Date getEndTimeOfCurrentYear(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.clear();
+        calendar.setTime(date);
+        calendar.set(calendar.get(Calendar.YEAR),11,31);
+        setMaxTimeOfDay(calendar);
+        return calendar.getTime();
+    }
+
+    /**
+     * 设置当天的开始时间
+     * @param calendar
+     */
+    private static void setMinTimeOfDay(Calendar calendar) {
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+    }
+
+    /**
+     * 设置当天的结束时间
+     * @param calendar
+     */
+    private static void setMaxTimeOfDay(Calendar calendar) {
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+    }
+
+
+}

+ 100 - 0
wps-biz/src/main/resources/application-dev.yml

@@ -0,0 +1,100 @@
+# 数据源配置
+spring:
+  servlet:
+    multipart:
+      max-file-size: 10MB
+      max-request-size: 20MB
+  datasource:
+    dynamic:
+      primary: mysql #设置默认的数据源或者数据源组,默认值即为master
+      datasource:
+        mysql:
+          url: jdbc:mysql://192.168.1.205:3306/nerp-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
+          #          url: jdbc:mysql://49.4.78.194:17136/nerp-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
+          #          url: jdbc:mysql://10.124.252.246:3306/nerp-db-v2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
+          username: root
+          password: '!QAZ2root'
+          driver-class-name: com.mysql.cj.jdbc.Driver
+          type: com.alibaba.druid.pool.DruidDataSource
+          druid:
+            # 初始连接数
+            initial-size: 5
+            # 最小连接池数量
+            min-idle: 10
+            # 最大连接池数量
+            max-active: 20
+            # 配置获取连接等待超时的时间
+            max-wait: 60000
+            # 配置一个连接在池中最小生存的时间,单位是毫秒
+            min-evictable-idle-time-millis: 300000
+            # 配置一个连接在池中最大生存的时间,单位是毫秒
+            max-evictable-idle-time-millis: 900000
+            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+            time-between-eviction-runs-millis: 60000
+            # 配置检测连接是否有效
+            test-while-idle: true
+            test-on-borrow: false
+            test-on-return: false
+            validation-query: select 1
+            validation-query-timeout: -1
+            webStatFilter:
+              enabled: true
+            statViewServlet:
+              enabled: true
+              # 设置白名单,不填则允许所有访问
+              allow:
+              url-pattern: /druid/*
+              # 控制台管理用户名和密码
+              login-username: nerp
+              login-password: nerp
+            filter:
+              stat:
+                enabled: true
+                # 慢SQL记录
+                log-slow-sql: true
+                slow-sql-millis: 1000
+                merge-sql: true
+              wall:
+                config:
+                  multi-statement-allow: true
+        tdengine:
+          url: jdbc:TAOS://192.168.1.208:6030/nerp_db
+          #          url: jdbc:TAOS://10.124.252.246:6030/nerp_db
+          #          url: jdbc:TAOS://49.4.78.194:17139/nerp_db
+          username: root
+          password: 123456
+          #          password: "!QAZ2root"
+          driver-class-name: com.taosdata.jdbc.TSDBDriver
+          type: com.alibaba.druid.pool.DruidDataSource
+          druid:
+            initial-size: 5
+            min-idle: 5
+            max-active: 5
+  # redis 配置
+  redis:
+    # 地址
+    host: 192.168.1.205
+    #    host: 10.124.252.244
+    # 端口,默认为6379
+    port: 6379
+    #    port: 17137
+    # 数据库索引
+    database: 0
+    # 密码
+    password: jiayue
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+
+#mybatis-plus:
+#  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

+ 93 - 0
wps-biz/src/main/resources/application-prod.yml

@@ -0,0 +1,93 @@
+# 数据源配置
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:mysql://10.124.252.246:3306/nerp-db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true
+        username: root
+        password: '!QAZ2root'
+      # 从库数据源
+      slave:
+        # 从数据源开关/默认关闭
+        enabled: false
+        url:
+        username:
+        password:
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: nerp
+        login-password: nerp
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # redis 配置
+  redis:
+    # 地址
+    host: 10.124.252.244
+    # 端口,默认为6379
+    port: 6379
+    # 数据库索引
+    database: 0
+    # 密码
+    password: jiayue
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+#
+#mybatis-plus:
+#  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
+file:
+  outPutDir: "D:\\out\\new\\"
+  excelDir: "D:\\analysisData\\new\\"
+  outPutBackDir: "D:\\out\\backUps\\"
+  excelBackDir: "D:\\analysisData\\backUps\\"
+email:
+  user: "wanghongchen942"
+  password: "LXQDEOCRCSXWBIAO"
+  host: "imap.126.com"
+  path: "d:\\in\\"

+ 195 - 0
wps-biz/src/main/resources/application.yml

@@ -0,0 +1,195 @@
+# 项目相关配置
+elf:
+  # 名称
+  name: WPS
+  # 版本
+  version: 1.0.0
+  # 版权年份
+  copyrightYear: 2022
+  # 实例演示开关
+  demoEnabled: true
+  # 文件路径,使用jvm系统变量,兼容windows和linux;
+  profile: ${user.dir}/nerp/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数组计算 char 字符验证
+  captchaType: math
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8080
+  port: 9093
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  undertow:
+    # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的
+    max-http-post-size: -1
+    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
+    # 每块buffer的空间大小,越小的空间被利用越充分
+    buffer-size: 512
+    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
+    io-threads: 8
+    # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
+    worker-threads: 256
+    # 是否分配的直接内存
+    direct-buffers: true
+
+# 配置actuator
+management:
+  endpoints:
+    enabled-by-default: true
+    web:
+      exposure:
+        #        include: ["health", "info", "logfile", "mappings"]
+        include: [ "logfile" ]
+  endpoint:
+    health:
+      show-details: always
+    logfile:
+      enabled: true
+      external-file: logs/sys-error.log
+
+# 日志配置
+logging:
+  config: classpath:logback-nerp.xml
+
+# Spring配置
+spring:
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  profiles:
+    active: @profiles.active@
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: Authorization
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 60
+
+# MyBatis配置
+# https://baomidou.com/config/
+mybatis-plus:
+  # 对应的 XML 文件位置
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.jiayue.**.domain
+  # 针对 typeAliasesPackage,如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象
+  #typeAliasesSuperType: Class<?>
+  # 如果配置了该属性,SqlSessionFactoryBean 会把该包下面的类注册为对应的 TypeHandler
+  #typeHandlersPackage: null
+  # 如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性
+  #typeEnumsPackage: null
+  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
+  checkConfigLocation: false
+  # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种:
+  # SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句(PreparedStatement)
+  # REUSE:该执行器类型会复用预处理语句(PreparedStatement)
+  # BATCH:该执行器类型会批量执行所有的更新语句
+  executorType: SIMPLE
+  # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
+  configurationProperties: null
+  configuration:
+    # 自动驼峰命名规则(camel case)映射
+    # 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
+    mapUnderscoreToCamelCase: true
+    # 默认枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理
+    # org.apache.ibatis.type.EnumTypeHandler : 存储枚举的名称
+    # org.apache.ibatis.type.EnumOrdinalTypeHandler : 存储枚举的索引
+    # com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler : 枚举类需要实现IEnum接口或字段标记@EnumValue注解.
+    defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
+    # 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。
+    aggressiveLazyLoading: true
+    # MyBatis 自动映射策略
+    # NONE:不启用自动映射
+    # PARTIAL:只对非嵌套的 resultMap 进行自动映射
+    # FULL:对所有的 resultMap 都进行自动映射
+    autoMappingBehavior: PARTIAL
+    # MyBatis 自动映射时未知列或未知属性处理策
+    # NONE:不做任何处理 (默认值)
+    # WARNING:以日志的形式打印相关警告信息
+    # FAILING:当作映射失败处理,并抛出异常和详细信息
+    autoMappingUnknownColumnBehavior: NONE
+    # Mybatis一级缓存,默认为 SESSION
+    # SESSION session级别缓存,同一个session相同查询语句不会再次查询数据库
+    # STATEMENT 关闭一级缓存
+    localCacheScope: SESSION
+    # 开启Mybatis二级缓存,默认为 true
+    cacheEnabled: true
+  global-config:
+    # 是否打印 Logo banner
+    banner: true
+    # 是否初始化 SqlRunner
+    enableSqlRunner: false
+    dbConfig:
+      # 主键类型
+      # AUTO 数据库ID自增
+      # NONE 空
+      # INPUT 用户输入ID
+      # ASSIGN_ID 全局唯一ID
+      # ASSIGN_UUID 全局唯一ID UUID
+      idType: AUTO
+      # 表名前缀
+      tablePrefix: null
+      # 字段 format,例: %s,(对主键无效)
+      columnFormat: null
+      # 表名是否使用驼峰转下划线命名,只对表名生效
+      tableUnderline: true
+      # 大写命名,对表名和字段名均生效
+      capitalMode: false
+      # 全局的entity的逻辑删除字段属性名
+      logicDeleteField: null
+      # 逻辑已删除值
+      logicDeleteValue: 1
+      # 逻辑未删除值
+      logicNotDeleteValue: 0
+      # 字段验证策略之 insert,在 insert 的时候的字段验证策略
+      # IGNORED 忽略判断
+      # NOT_NULL 非NULL判断
+      # NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
+      # DEFAULT 默认的,一般只用于注解里
+      # NEVER 不加入 SQL
+      insertStrategy: NOT_NULL
+      # 字段验证策略之 update,在 update 的时候的字段验证策略
+      updateStrategy: NOT_NULL
+      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
+      selectStrategy: NOT_NULL
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*

+ 110 - 0
wps-biz/src/main/resources/logback-nerp.xml

@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration scan="false" scanPeriod="60 seconds" debug="false"><!-- 这个是根配置文件,一定要有的
+                            scan:
+                                是当配置文件被修改后会被重新加载
+                            scanPeriod:
+                                设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,
+                                默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
+                            debug:
+                                当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。
+                                默认值为false。
+                             -->
+    <!-- 日志存放路径
+        下面的标签可以自己定义
+        name:相当于Map的key
+        value:就是map的value
+        ${catalina.base}是tomcat的当前路径
+        /logs:就是tomcat下的日志路径,
+        /ehrlog:如果没有目录会默认创建
+    -->
+    <property name="logbase" value="./logs/"/>
+    <!-- 时间戳:这个时间戳可以作为每日日志的名称 -->
+    <timestamp key="bySecond" datePattern="yyyy-MM-dd"/>
+    <!-- appender:
+        name相当于一个名称
+        class:确定要加载哪个类
+        encoder:一定要加 encoder ,
+        默认配置为PatternLayoutEncoder
+        patter:必填
+        ConsoleAppender:也明白是什么意思,就是输出在控制台上-->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+    <!-- 把日志存储
+        encoding:日志的编码
+        file:指定当前生成的日志文件名称
+        rollingPolicy:滚动策略
+        FileNamePattern:移动文件最后的名称,跟file标签结合使用,
+        比如file里面的内容是  1.txt
+        那么,FileNamePattern里面写的是2.txt,那么最后文件名就为2.txt
+        如果最后结尾是gz或者zip,那么,就会自动打成压缩包
+        -->
+    <appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 编码 -->
+        <!--<Encoding>UTF-8</Encoding>-->
+        <!-- 按照时间来 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${logbase}/%d{yyyy-MM}/nerp.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>180</MaxHistory>
+            <maxFileSize>10MB</maxFileSize>
+            <totalSizeCap>1024MB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <!-- 布局 -->
+        <encoder>
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <append>false</append>
+    </appender>
+
+
+    <!-- <appender name="TunnelLogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+       &lt;!&ndash; 编码 &ndash;&gt;
+       &lt;!&ndash;<Encoding>UTF-8</Encoding>&ndash;&gt;
+       &lt;!&ndash; 按照时间来 &ndash;&gt;
+       <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+         &lt;!&ndash;日志文件输出的文件名&ndash;&gt;
+         <FileNamePattern>D://testlog//#TunnelName#.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+         &lt;!&ndash;日志文件保留天数&ndash;&gt;
+         <MaxHistory>180</MaxHistory>
+         <maxFileSize>10MB</maxFileSize>
+         <totalSizeCap>1024MB</totalSizeCap>
+         <cleanHistoryOnStart>true</cleanHistoryOnStart>
+       </rollingPolicy>
+       &lt;!&ndash; 布局 &ndash;&gt;
+       <encoder>
+         &lt;!&ndash;格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符&ndash;&gt;
+         <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+         <charset>UTF-8</charset>
+       </encoder>
+       <append>false</append>
+     </appender>
+
+     <logger name="TunnelLogger" level="debug" additivity="true">
+       <appender-ref ref="TunnelLogFile"/>
+     </logger>-->
+
+    <logger name="com.jiayue" level="info" additivity="true">
+        <appender-ref ref="logFile"/>
+    </logger>
+    <logger name="com.alibaba.druid.filter.stat.StatFilter" level="info" additivity="true">
+        <appender-ref ref="logFile"/>
+    </logger>
+
+
+    <logger name="org" level="info" additivity="true">
+        <appender-ref ref="logFile"/>
+    </logger>
+
+    <root level="info">
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>

+ 237 - 0
wps-system/pom.xml

@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>wps</artifactId>
+        <groupId>com.jiayue</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>wps-system</artifactId>
+
+    <description>
+        wps-system系统模块
+    </description>
+
+    <dependencies>
+
+        <!-- Spring框架基本的核心工具 -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
+        <!-- SpringWeb模块 -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <!-- spring security 安全认证 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <!-- pagehelper 分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 自定义验证注解 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!--常用工具类 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- JSON工具类 -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <!-- io常用工具类 -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <!-- 文件上传工具类 -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+        </dependency>
+
+        <!-- excel工具 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <!-- yml解析器 -->
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+
+        <!-- Token生成与解析 -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+
+
+        <!-- Jaxb -->
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+
+        <!-- redis 缓存操作 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!-- pool 对象池 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+        </dependency>
+
+        <!-- servlet包 -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-extension</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+
+        <!--velocity代码生成使用模板 -->
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+        </dependency>
+
+        <!--commons-collections-->
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+
+        <!-- 定时任务 -->
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.mchange</groupId>
+                    <artifactId>c3p0</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- SpringBoot Web容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- web 容器使用 undertow 性能更强 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+
+        <!-- SpringBoot 拦截器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- 阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- Mysql驱动包 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- 验证码 -->
+        <dependency>
+            <groupId>com.github.penggle</groupId>
+            <artifactId>kaptcha</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>javax.servlet-api</artifactId>
+                    <groupId>javax.servlet</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- 获取系统信息 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+        </dependency>
+
+        <!-- swagger3-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 27 - 0
wps-system/src/main/java/com/jiayue/common/annotation/DataScope.java

@@ -0,0 +1,27 @@
+package com.jiayue.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 数据权限过滤注解
+ *
+ * @author L.ym
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope {
+    /**
+     * 组织表的别名
+     */
+    String unitAlias() default "";
+
+    /**
+     * 用户表的别名
+     */
+    String userAlias() default "";
+}

+ 24 - 0
wps-system/src/main/java/com/jiayue/common/annotation/DataSource.java

@@ -0,0 +1,24 @@
+package com.jiayue.common.annotation;
+
+import com.jiayue.common.enums.DataSourceType;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义多数据源切换注解
+ *
+ * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
+ *
+ * @author jy
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+    /**
+     * 切换数据源名称
+     */
+    public DataSourceType value() default DataSourceType.MASTER;
+}

+ 175 - 0
wps-system/src/main/java/com/jiayue/common/annotation/Excel.java

@@ -0,0 +1,175 @@
+package com.jiayue.common.annotation;
+
+import com.jiayue.common.utils.poi.ExcelHandlerAdapter;
+
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+
+/**
+ * 自定义导出Excel数据注解
+ *
+ * @author jy
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel {
+    /**
+     * 导出时在excel中排序
+     */
+    int sort() default Integer.MAX_VALUE;
+
+    /**
+     * 导出到Excel中的名字.
+     */
+    String name() default "";
+
+    /**
+     * 日期格式, 如: yyyy-MM-dd
+     */
+    String dateFormat() default "";
+
+    /**
+     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
+     */
+    String dictType() default "";
+
+    /**
+     * 读取内容转表达式 (如: 0=男,1=女,2=未知)
+     */
+    String readConverterExp() default "";
+
+    /**
+     * 分隔符,读取字符串组内容
+     */
+    String separator() default ",";
+
+    /**
+     * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
+     */
+    int scale() default -1;
+
+    /**
+     * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
+     */
+    int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+    /**
+     * 导出时在excel中每个列的高度 单位为字符
+     */
+    double height() default 14;
+
+    /**
+     * 导出时在excel中每个列的宽 单位为字符
+     */
+    double width() default 16;
+
+    /**
+     * 文字后缀,如% 90 变成90%
+     */
+    String suffix() default "";
+
+    /**
+     * 当值为空时,字段的默认值
+     */
+    String defaultValue() default "";
+
+    /**
+     * 提示信息
+     */
+    String prompt() default "";
+
+    /**
+     * 设置只能选择不能输入的列内容.
+     */
+    String[] combo() default {};
+
+    /**
+     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
+     */
+    boolean isExport() default true;
+
+    /**
+     * 另一个类中的属性名称,支持多级获取,以小数点隔开
+     */
+    String targetAttr() default "";
+
+    /**
+     * 是否自动统计数据,在最后追加一行统计数据总和
+     */
+    boolean isStatistics() default false;
+
+    /**
+     * 导出类型(0数字 1字符串)
+     */
+    ColumnType cellType() default ColumnType.STRING;
+
+    /**
+     * 导出字体颜色
+     */
+    IndexedColors color() default IndexedColors.BLACK;
+
+    /**
+     * 导出字段对齐方式
+     */
+    HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+    /**
+     * 自定义数据处理器
+     */
+    Class<?> handler() default ExcelHandlerAdapter.class;
+
+    /**
+     * 自定义数据处理器参数
+     */
+    String[] args() default {};
+
+    enum Align {
+        AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
+        private final int value;
+
+        Align(int value) {
+            this.value = value;
+        }
+
+        public int value() {
+            return this.value;
+        }
+    }
+
+    /**
+     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
+     */
+    Type type() default Type.ALL;
+
+    enum Type {
+        ALL(0), EXPORT(1), IMPORT(2);
+        private final int value;
+
+        Type(int value) {
+            this.value = value;
+        }
+
+        public int value() {
+            return this.value;
+        }
+    }
+
+    enum ColumnType {
+        NUMERIC(0), STRING(1), IMAGE(2);
+        private final int value;
+
+        ColumnType(int value) {
+            this.value = value;
+        }
+
+        public int value() {
+            return this.value;
+        }
+    }
+}

+ 18 - 0
wps-system/src/main/java/com/jiayue/common/annotation/Excels.java

@@ -0,0 +1,18 @@
+package com.jiayue.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel注解集
+ *
+ * @author jy
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+    Excel[] value();
+}

+ 45 - 0
wps-system/src/main/java/com/jiayue/common/annotation/Log.java

@@ -0,0 +1,45 @@
+package com.jiayue.common.annotation;
+
+import com.jiayue.common.enums.BusinessType;
+import com.jiayue.common.enums.OperatorType;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义操作日志记录注解
+ *
+ * @author jy
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log {
+    /**
+     * 模块
+     */
+    public String title() default "";
+
+    /**
+     * 功能
+     */
+    public BusinessType businessType() default BusinessType.OTHER;
+
+    /**
+     * 操作人类别
+     */
+    public OperatorType operatorType() default OperatorType.MANAGE;
+
+    /**
+     * 是否保存请求的参数
+     */
+    public boolean isSaveRequestData() default true;
+
+    /**
+     * 是否保存响应的参数
+     */
+    public boolean isSaveResponseData() default true;
+}

+ 40 - 0
wps-system/src/main/java/com/jiayue/common/annotation/RateLimiter.java

@@ -0,0 +1,40 @@
+package com.jiayue.common.annotation;
+
+import com.jiayue.common.constant.Global;
+import com.jiayue.common.enums.LimitType;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 限流注解
+ *
+ * @author jy
+ **/
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RateLimiter {
+    /**
+     * 限流key
+     */
+    String key() default Global.RATE_LIMIT_KEY;
+
+    /**
+     * 限流时间,单位秒
+     */
+    int time() default 60;
+
+    /**
+     * 限流次数
+     */
+    int count() default 100;
+
+    /**
+     * 限流类型
+     */
+    LimitType limitType() default LimitType.DEFAULT;
+}

+ 29 - 0
wps-system/src/main/java/com/jiayue/common/annotation/RepeatSubmit.java

@@ -0,0 +1,29 @@
+package com.jiayue.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义注解防止表单重复提交
+ *
+ * @author jy
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit {
+    /**
+     * 间隔时间(ms),小于此时间视为重复提交
+     */
+    int interval() default 5000;
+
+    /**
+     * 提示消息
+     */
+    String message() default "不允许重复提交,请稍候再试";
+}

+ 131 - 0
wps-system/src/main/java/com/jiayue/common/config/ElfConfig.java

@@ -0,0 +1,131 @@
+package com.jiayue.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author jy
+ */
+@Component
+@ConfigurationProperties(prefix = "elf")
+public class ElfConfig {
+    /**
+     * 项目名称
+     */
+    private String name;
+
+    /**
+     * 版本
+     */
+    private String version;
+
+    /**
+     * 版权年份
+     */
+    private String copyrightYear;
+
+    /**
+     * 实例演示开关
+     */
+    private boolean demoEnabled;
+
+    /**
+     * 上传路径
+     */
+    private static String profile;
+
+    /**
+     * 获取地址开关
+     */
+    private static boolean addressEnabled;
+
+    /** 验证码类型 */
+    private static String captchaType;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getCopyrightYear() {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear) {
+        this.copyrightYear = copyrightYear;
+    }
+
+    public boolean isDemoEnabled() {
+        return demoEnabled;
+    }
+
+    public void setDemoEnabled(boolean demoEnabled) {
+        this.demoEnabled = demoEnabled;
+    }
+
+    public static String getProfile() {
+        return profile;
+    }
+
+    public void setProfile(String profile) {
+        ElfConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled() {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled) {
+        ElfConfig.addressEnabled = addressEnabled;
+    }
+
+    public static String getCaptchaType() {
+        return captchaType;
+    }
+
+    public void setCaptchaType(String captchaType) {
+        ElfConfig.captchaType = captchaType;
+    }
+
+
+    /**
+     * 获取导入上传路径
+     */
+    public static String getImportPath() {
+        return getProfile() + "/import";
+    }
+
+    /**
+     * 获取头像上传路径
+     */
+    public static String getAvatarPath() {
+        return getProfile() + "/avatar";
+    }
+
+    /**
+     * 获取下载路径
+     */
+    public static String getDownloadPath() {
+        return getProfile() + "/download/";
+    }
+
+    /**
+     * 获取上传路径
+     */
+    public static String getUploadPath() {
+        return getProfile() + "/upload";
+    }
+}

+ 186 - 0
wps-system/src/main/java/com/jiayue/common/constant/GenConstants.java

@@ -0,0 +1,186 @@
+package com.jiayue.common.constant;
+
+/**
+ * 代码生成通用常量
+ *
+ * @author jy
+ */
+public class GenConstants {
+    /**
+     * 单表(增删改查)
+     */
+    public static final String TPL_CRUD = "crud";
+
+    /**
+     * 树表(增删改查)
+     */
+    public static final String TPL_TREE = "tree";
+
+    /**
+     * 主子表(增删改查)
+     */
+    public static final String TPL_SUB = "sub";
+
+    /**
+     * 树编码字段
+     */
+    public static final String TREE_CODE = "treeCode";
+
+    /**
+     * 树父编码字段
+     */
+    public static final String TREE_PARENT_CODE = "treeParentCode";
+
+    /**
+     * 树名称字段
+     */
+    public static final String TREE_NAME = "treeName";
+
+    /**
+     * 上级菜单ID字段
+     */
+    public static final String PARENT_MENU_ID = "parentMenuId";
+
+    /**
+     * 上级菜单名称字段
+     */
+    public static final String PARENT_MENU_NAME = "parentMenuName";
+
+    /**
+     * 数据库字符串类型
+     */
+    public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
+
+    /**
+     * 数据库文本类型
+     */
+    public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
+
+    /**
+     * 数据库时间类型
+     */
+    public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
+
+    /**
+     * 数据库数字类型
+     */
+    public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
+            "bit", "bigint", "float", "double", "decimal"};
+
+    /**
+     * 页面不需要编辑字段
+     */
+    public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"};
+
+    /**
+     * 页面不需要显示的列表字段
+     */
+    public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time"};
+
+    /**
+     * 页面不需要查询字段
+     */
+    public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time", "remark"};
+
+    /**
+     * Entity基类字段
+     */
+    public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"};
+
+    /**
+     * Tree基类字段
+     */
+    public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"};
+
+    /**
+     * 文本框
+     */
+    public static final String HTML_INPUT = "input";
+
+    /**
+     * 文本域
+     */
+    public static final String HTML_TEXTAREA = "textarea";
+
+    /**
+     * 下拉框
+     */
+    public static final String HTML_SELECT = "select";
+
+    /**
+     * 单选框
+     */
+    public static final String HTML_RADIO = "radio";
+
+    /**
+     * 复选框
+     */
+    public static final String HTML_CHECKBOX = "checkbox";
+
+    /**
+     * 日期控件
+     */
+    public static final String HTML_DATETIME = "datetime";
+
+    /**
+     * 图片上传控件
+     */
+    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+    /**
+     * 文件上传控件
+     */
+    public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+    /**
+     * 富文本控件
+     */
+    public static final String HTML_EDITOR = "editor";
+
+    /**
+     * 字符串类型
+     */
+    public static final String TYPE_STRING = "String";
+
+    /**
+     * 整型
+     */
+    public static final String TYPE_INTEGER = "Integer";
+
+    /**
+     * 长整型
+     */
+    public static final String TYPE_LONG = "Long";
+
+    /**
+     * 浮点型
+     */
+    public static final String TYPE_DOUBLE = "Double";
+
+    /**
+     * 高精度计算类型
+     */
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /**
+     * 时间类型
+     */
+    public static final String TYPE_DATE = "Date";
+
+    /**
+     * 模糊查询
+     */
+    public static final String QUERY_LIKE = "LIKE";
+
+    /**
+     * 相等查询
+     */
+    public static final String QUERY_EQ = "EQ";
+
+    /**
+     * 需要
+     */
+    public static final String REQUIRE = "1";
+}

+ 176 - 0
wps-system/src/main/java/com/jiayue/common/constant/Global.java

@@ -0,0 +1,176 @@
+package com.jiayue.common.constant;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * 通用常量信息
+ *
+ * @author L.ym
+ */
+public class Global {
+
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 通用成功标识
+     */
+    public static final String SUCCESS = "0";
+
+    /**
+     * 通用失败标识
+     */
+    public static final String FAIL = "1";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 验证码 redis key
+     */
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 登录用户 redis key
+     */
+    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 防重提交 redis key
+     */
+    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+    /**
+     * 限流 redis key
+     */
+    public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 令牌
+     */
+    public static final String TOKEN = "token";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * 用户ID
+     */
+    public static final String JWT_USERID = "userid";
+
+    /**
+     * 用户名称
+     */
+    public static final String JWT_USERNAME = Claims.SUBJECT;
+
+    /**
+     * 用户头像
+     */
+    public static final String JWT_AVATAR = "avatar";
+
+    /**
+     * 创建时间
+     */
+    public static final String JWT_CREATED = "created";
+
+    /**
+     * 用户权限
+     */
+    public static final String JWT_AUTHORITIES = "authorities";
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * RMI 远程方法调用
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAPS 远程方法调用
+     */
+    public static final String[] LOOKUP_LDAPS = {"ldap:", "ldaps:"};
+
+    /**
+     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+     */
+    public static final String[] JOB_WHITELIST_STR = {"com.jiayue"};
+
+    /**
+     * 定时任务违规的字符
+     */
+    public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", "org.springframework", "org.apache", "com.jiayue.common.utils.file"};
+
+    /**
+     * 默认值
+     **/
+    public static final String DEFAULT = "default";
+
+    /**
+     * 不适用 N/A
+     **/
+    public static final String NOT_APPLICABLE = "N/A";
+
+    /**
+     * 特殊标识
+     **/
+    public static final String SPECIAL_ID = "icelake";
+}

+ 89 - 0
wps-system/src/main/java/com/jiayue/common/constant/HttpStatus.java

@@ -0,0 +1,89 @@
+package com.jiayue.common.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author jy
+ */
+public class HttpStatus
+{
+    /**
+     * 操作成功
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 对象创建成功
+     */
+    public static final int CREATED = 201;
+
+    /**
+     * 请求已经被接受
+     */
+    public static final int ACCEPTED = 202;
+
+    /**
+     * 操作已经执行成功,但是没有返回数据
+     */
+    public static final int NO_CONTENT = 204;
+
+    /**
+     * 资源已被移除
+     */
+    public static final int MOVED_PERM = 301;
+
+    /**
+     * 重定向
+     */
+    public static final int SEE_OTHER = 303;
+
+    /**
+     * 资源没有被修改
+     */
+    public static final int NOT_MODIFIED = 304;
+
+    /**
+     * 参数列表错误(缺少,格式不匹配)
+     */
+    public static final int BAD_REQUEST = 400;
+
+    /**
+     * 未授权
+     */
+    public static final int UNAUTHORIZED = 401;
+
+    /**
+     * 访问受限,授权过期
+     */
+    public static final int FORBIDDEN = 403;
+
+    /**
+     * 资源,服务未找到
+     */
+    public static final int NOT_FOUND = 404;
+
+    /**
+     * 不允许的http方法
+     */
+    public static final int BAD_METHOD = 405;
+
+    /**
+     * 资源冲突,或者资源被锁
+     */
+    public static final int CONFLICT = 409;
+
+    /**
+     * 不支持的数据,媒体类型
+     */
+    public static final int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 系统内部错误
+     */
+    public static final int ERROR = 500;
+
+    /**
+     * 接口未实现
+     */
+    public static final int NOT_IMPLEMENTED = 501;
+}

+ 56 - 0
wps-system/src/main/java/com/jiayue/common/constant/ScheduleConstants.java

@@ -0,0 +1,56 @@
+package com.jiayue.common.constant;
+
+/**
+ * 任务调度通用常量
+ *
+ * @author jy
+ */
+public class ScheduleConstants {
+    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+    /**
+     * 执行目标key
+     */
+    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+    /**
+     * 默认
+     */
+    public static final String MISFIRE_DEFAULT = "0";
+
+    /**
+     * 立即触发执行
+     */
+    public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+    /**
+     * 触发一次执行
+     */
+    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+    /**
+     * 不触发立即执行
+     */
+    public static final String MISFIRE_DO_NOTHING = "3";
+
+    public enum Status {
+        /**
+         * 正常
+         */
+        NORMAL("0"),
+        /**
+         * 暂停
+         */
+        PAUSE("1");
+
+        private String value;
+
+        Status(String value) {
+            this.value = value;
+        }
+
+        public String getValue() {
+            return value;
+        }
+    }
+}

+ 111 - 0
wps-system/src/main/java/com/jiayue/common/constant/UserConstants.java

@@ -0,0 +1,111 @@
+package com.jiayue.common.constant;
+
+/**
+ * 用户常量信息
+ *
+ * @author jy
+ */
+public class UserConstants {
+    /**
+     * 平台内系统用户的唯一标志
+     */
+    public static final String SYS_USER = "SYS_USER";
+
+    /**
+     * 正常状态
+     */
+    public static final String NORMAL = "0";
+
+    /**
+     * 异常状态
+     */
+    public static final String EXCEPTION = "1";
+
+    /**
+     * 用户封禁状态
+     */
+    public static final String USER_DISABLE = "1";
+
+    /**
+     * 角色封禁状态
+     */
+    public static final String ROLE_DISABLE = "1";
+
+    /**
+     * 组织单元正常状态
+     */
+    public static final String UNIT_NORMAL = "0";
+
+    /**
+     * 组织单元停用状态
+     */
+    public static final String UNIT_DISABLE = "1";
+
+    /**
+     * 字典正常状态
+     */
+    public static final String DICT_NORMAL = "0";
+
+    /**
+     * 是否为系统默认(是)
+     */
+    public static final String YES = "Y";
+
+    /**
+     * 是否菜单外链(是)
+     */
+    public static final String YES_FRAME = "0";
+
+    /**
+     * 是否菜单外链(否)
+     */
+    public static final String NO_FRAME = "1";
+
+    /**
+     * 菜单类型(目录)
+     */
+    public static final String TYPE_DIR = "M";
+
+    /**
+     * 菜单类型(菜单)
+     */
+    public static final String TYPE_MENU = "C";
+
+    /**
+     * 菜单类型(按钮)
+     */
+    public static final String TYPE_BUTTON = "F";
+
+    /**
+     * Layout组件标识
+     */
+    public final static String LAYOUT = "Layout";
+
+    /**
+     * ParentView组件标识
+     */
+    public final static String PARENT_VIEW = "ParentView";
+
+    /**
+     * InnerLink组件标识
+     */
+    public final static String INNER_LINK = "InnerLink";
+
+    /**
+     * 校验返回结果码
+     */
+    public final static String UNIQUE = "0";
+    public final static String NOT_UNIQUE = "1";
+
+    /**
+     * 用户名长度限制
+     */
+    public static final int USERNAME_MIN_LENGTH = 2;
+    public static final int USERNAME_MAX_LENGTH = 20;
+
+    /**
+     * 密码长度限制
+     */
+    public static final int PASSWORD_MIN_LENGTH = 5;
+    public static final int PASSWORD_MAX_LENGTH = 20;
+}

+ 169 - 0
wps-system/src/main/java/com/jiayue/common/core/controller/BaseController.java

@@ -0,0 +1,169 @@
+package com.jiayue.common.core.controller;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.jiayue.common.constant.HttpStatus;
+import com.jiayue.common.core.domain.AjaxResult;
+import com.jiayue.common.core.domain.model.LoginUser;
+import com.jiayue.common.core.page.PageDomain;
+import com.jiayue.common.core.page.TableDataInfo;
+import com.jiayue.common.core.page.TableSupport;
+import com.jiayue.common.utils.DateUtil;
+import com.jiayue.common.utils.PageUtils;
+import com.jiayue.common.utils.SecurityUtils;
+import com.jiayue.common.utils.sql.SqlUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * web层通用数据处理
+ *
+ * @author jy
+ */
+public class BaseController {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 将前台传递过来的日期格式的字符串,自动转化为Date类型
+     */
+    @InitBinder
+    public void initBinder(WebDataBinder binder) {
+        // Date 类型转换
+        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
+            @Override
+            public void setAsText(String text) {
+                setValue(DateUtil.parse(text));
+            }
+        });
+    }
+
+    /**
+     * 设置请求分页数据
+     */
+    protected void startPage() {
+        PageUtils.startPage();
+    }
+
+    /**
+     * 设置请求排序数据
+     */
+    protected void startOrderBy() {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (StrUtil.isNotEmpty(pageDomain.getOrderBy())) {
+            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+            PageHelper.orderBy(orderBy);
+        }
+    }
+
+    /**
+     * 清理分页的线程变量
+     */
+    protected void clearPage() {
+        PageUtils.clearPage();
+    }
+
+    /**
+     * 响应请求分页数据
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected TableDataInfo getDataTable(List<?> list) {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
+
+    /**
+     * 返回成功
+     */
+    public AjaxResult success() {
+        return AjaxResult.success();
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error() {
+        return AjaxResult.error();
+    }
+
+    /**
+     * 返回成功消息
+     */
+    public AjaxResult success(String message) {
+        return AjaxResult.success(message);
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public AjaxResult error(String message) {
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param rows 影响行数
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(int rows) {
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param result 结果
+     * @return 操作结果
+     */
+    protected AjaxResult toAjax(boolean result) {
+        return result ? success() : error();
+    }
+
+    /**
+     * 页面跳转
+     */
+    public String redirect(String url) {
+        return StrUtil.format("redirect:{}", url);
+    }
+
+    /**
+     * 获取用户缓存信息
+     */
+    public LoginUser getLoginUser() {
+        return SecurityUtils.getLoginUser();
+    }
+
+    /**
+     * 获取登录用户id
+     */
+    public Long getUserId() {
+        return getLoginUser().getUserId();
+    }
+
+    /**
+     * 获取登录组织单元id
+     */
+    public Long getUnitId() {
+        return getLoginUser().getUnitId();
+    }
+
+    /**
+     * 获取登录用户名
+     */
+    public String getUsername() {
+        return getLoginUser().getUsername();
+    }
+}

+ 154 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/AjaxResult.java

@@ -0,0 +1,154 @@
+package com.jiayue.common.core.domain;
+
+import com.jiayue.common.constant.HttpStatus;
+
+import java.util.HashMap;
+
+import cn.hutool.core.util.ObjectUtil;
+
+/**
+ * 操作消息提醒
+ *
+ * @author jy
+ */
+public class AjaxResult extends HashMap<String, Object> {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 状态码
+     */
+    public static final String CODE_TAG = "code";
+
+    /**
+     * 返回内容
+     */
+    public static final String MSG_TAG = "msg";
+
+    /**
+     * 数据对象
+     */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public AjaxResult() {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     */
+    public AjaxResult(int code, String msg) {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     * @param data 数据对象
+     */
+    public AjaxResult(int code, String msg, Object data) {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (ObjectUtil.isNotNull(data)) {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @return 成功消息
+     */
+    public static AjaxResult success() {
+        return AjaxResult.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     *
+     * @return 成功消息
+     */
+    public static AjaxResult success(Object data) {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg) {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg  返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg, Object data) {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     */
+    public static AjaxResult error() {
+        return AjaxResult.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg) {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg  返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg, Object data) {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult error(int code, String msg) {
+        return new AjaxResult(code, msg, null);
+    }
+
+    /**
+     * 方便链式调用
+     *
+     * @param key   键
+     * @param value 值
+     * @return 数据对象
+     */
+    @Override
+    public AjaxResult put(String key, Object value) {
+        super.put(key, value);
+        return this;
+    }
+}

+ 82 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/AuditEntity.java

@@ -0,0 +1,82 @@
+package com.jiayue.common.core.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * Entity 审计信息
+ *
+ * @author L.ym
+ * @date 2020-12-23
+ **/
+public class AuditEntity extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

+ 47 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/BaseEntity.java

@@ -0,0 +1,47 @@
+package com.jiayue.common.core.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Entity基类
+ *
+ * @author L.ym
+ */
+public class BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 搜索值
+     */
+    @TableField(exist = false)
+    private String searchValue;
+
+    /**
+     * 请求参数
+     */
+    @TableField(exist = false)
+    private Map<String, Object> params;
+
+    public String getSearchValue() {
+        return searchValue;
+    }
+
+    public void setSearchValue(String searchValue) {
+        this.searchValue = searchValue;
+    }
+
+    public Map<String, Object> getParams() {
+        if (params == null) {
+            params = new HashMap<>();
+        }
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params) {
+        this.params = params;
+    }
+}

+ 78 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/TreeEntity.java

@@ -0,0 +1,78 @@
+package com.jiayue.common.core.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree基类
+ *
+ * @author jy
+ */
+public class TreeEntity extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 父菜单名称
+     */
+    private String parentName;
+
+    /**
+     * 父菜单ID
+     */
+    private Long parentId;
+
+    /**
+     * 显示顺序
+     */
+    private Integer orderNum;
+
+    /**
+     * 祖级列表
+     */
+    private String ancestors;
+
+    /**
+     * 子组织单元
+     */
+    private List<?> children = new ArrayList<>();
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public Integer getOrderNum() {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum) {
+        this.orderNum = orderNum;
+    }
+
+    public String getAncestors() {
+        return ancestors;
+    }
+
+    public void setAncestors(String ancestors) {
+        this.ancestors = ancestors;
+    }
+
+    public List<?> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<?> children) {
+        this.children = children;
+    }
+}

+ 74 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/TreeSelect.java

@@ -0,0 +1,74 @@
+package com.jiayue.common.core.domain;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.jiayue.common.core.domain.entity.SysMenu;
+import com.jiayue.common.core.domain.entity.SysUnit;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Treeselect树结构实体类
+ *
+ * @author L.ym
+ */
+public class TreeSelect implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 节点ID
+     */
+    private Long id;
+
+    /**
+     * 节点名称
+     */
+    private String label;
+
+    /**
+     * 子节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<TreeSelect> children;
+
+    public TreeSelect() {
+
+    }
+
+    public TreeSelect(SysUnit unit) {
+        this.id = unit.getUnitId();
+        this.label = unit.getUnitName();
+        this.children = unit.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    public TreeSelect(SysMenu menu) {
+        this.id = menu.getMenuId();
+        this.label = menu.getMenuName();
+        this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public List<TreeSelect> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<TreeSelect> children) {
+        this.children = children;
+    }
+}

+ 176 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysDictData.java

@@ -0,0 +1,176 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.jiayue.common.annotation.Excel;
+import com.jiayue.common.annotation.Excel.ColumnType;
+import com.jiayue.common.constant.UserConstants;
+import com.jiayue.common.core.domain.AuditEntity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+/**
+ * 字典数据表 sys_dict_data
+ *
+ * @author jy
+ */
+public class SysDictData extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 字典编码
+     */
+    @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
+    private Long dictCode;
+
+    /**
+     * 字典排序
+     */
+    @Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
+    private Long dictSort;
+
+    /**
+     * 字典标签
+     */
+    @Excel(name = "字典标签")
+    private String dictLabel;
+
+    /**
+     * 字典键值
+     */
+    @Excel(name = "字典键值")
+    private String dictValue;
+
+    /**
+     * 字典类型
+     */
+    @Excel(name = "字典类型")
+    private String dictType;
+
+    /**
+     * 样式属性(其他样式扩展)
+     */
+    private String cssClass;
+
+    /**
+     * 表格字典样式
+     */
+    private String listClass;
+
+    /**
+     * 是否默认(Y是 N否)
+     */
+    @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
+    private String isDefault;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    public Long getDictCode() {
+        return dictCode;
+    }
+
+    public void setDictCode(Long dictCode) {
+        this.dictCode = dictCode;
+    }
+
+    public Long getDictSort() {
+        return dictSort;
+    }
+
+    public void setDictSort(Long dictSort) {
+        this.dictSort = dictSort;
+    }
+
+    @NotBlank(message = "字典标签不能为空")
+    @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
+    public String getDictLabel() {
+        return dictLabel;
+    }
+
+    public void setDictLabel(String dictLabel) {
+        this.dictLabel = dictLabel;
+    }
+
+    @NotBlank(message = "字典键值不能为空")
+    @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
+    public String getDictValue() {
+        return dictValue;
+    }
+
+    public void setDictValue(String dictValue) {
+        this.dictValue = dictValue;
+    }
+
+    @NotBlank(message = "字典类型不能为空")
+    @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
+    public String getDictType() {
+        return dictType;
+    }
+
+    public void setDictType(String dictType) {
+        this.dictType = dictType;
+    }
+
+    @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    public void setCssClass(String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+    public String getListClass() {
+        return listClass;
+    }
+
+    public void setListClass(String listClass) {
+        this.listClass = listClass;
+    }
+
+    public boolean getDefault() {
+        return UserConstants.YES.equals(this.isDefault);
+    }
+
+    public String getIsDefault() {
+        return isDefault;
+    }
+
+    public void setIsDefault(String isDefault) {
+        this.isDefault = isDefault;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("dictCode", getDictCode())
+                .append("dictSort", getDictSort())
+                .append("dictLabel", getDictLabel())
+                .append("dictValue", getDictValue())
+                .append("dictType", getDictType())
+                .append("cssClass", getCssClass())
+                .append("listClass", getListClass())
+                .append("isDefault", getIsDefault())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}

+ 97 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysDictType.java

@@ -0,0 +1,97 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.jiayue.common.annotation.Excel;
+import com.jiayue.common.annotation.Excel.ColumnType;
+import com.jiayue.common.core.domain.AuditEntity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+/**
+ * 字典类型表 sys_dict_type
+ *
+ * @author jy
+ */
+public class SysDictType extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 字典主键
+     */
+    @Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
+    private Long dictId;
+
+    /**
+     * 字典名称
+     */
+    @Excel(name = "字典名称")
+    private String dictName;
+
+    /**
+     * 字典类型
+     */
+    @Excel(name = "字典类型")
+    private String dictType;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    public Long getDictId() {
+        return dictId;
+    }
+
+    public void setDictId(Long dictId) {
+        this.dictId = dictId;
+    }
+
+    @NotBlank(message = "字典名称不能为空")
+    @Size(max = 100, message = "字典类型名称长度不能超过100个字符")
+    public String getDictName() {
+        return dictName;
+    }
+
+    public void setDictName(String dictName) {
+        this.dictName = dictName;
+    }
+
+    @NotBlank(message = "字典类型不能为空")
+    @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
+    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下划线)")
+    public String getDictType() {
+        return dictType;
+    }
+
+    public void setDictType(String dictType) {
+        this.dictType = dictType;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("dictId", getDictId())
+                .append("dictName", getDictName())
+                .append("dictType", getDictType())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}

+ 261 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysMenu.java

@@ -0,0 +1,261 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.jiayue.common.core.domain.AuditEntity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * 菜单权限表 sys_menu
+ *
+ * @author jy
+ */
+public class SysMenu extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 菜单ID
+     */
+    private Long menuId;
+
+    /**
+     * 菜单名称
+     */
+    private String menuName;
+
+    /**
+     * 父菜单名称
+     */
+    private String parentName;
+
+    /**
+     * 父菜单ID
+     */
+    private Long parentId;
+
+    /**
+     * 显示顺序
+     */
+    private Integer orderNum;
+
+    /**
+     * 路由地址
+     */
+    private String path;
+
+    /**
+     * 组件路径
+     */
+    private String component;
+
+    /**
+     * 路由参数
+     */
+    private String query;
+
+    /**
+     * 是否为外链(0是 1否)
+     */
+    private String isFrame;
+
+    /**
+     * 是否缓存(0缓存 1不缓存)
+     */
+    private String isCache;
+
+    /**
+     * 类型(M目录 C菜单 F按钮)
+     */
+    private String menuType;
+
+    /**
+     * 显示状态(0显示 1隐藏)
+     */
+    private String visible;
+
+    /**
+     * 菜单状态(0显示 1隐藏)
+     */
+    private String status;
+
+    /**
+     * 权限字符串
+     */
+    private String perms;
+
+    /**
+     * 菜单图标
+     */
+    private String icon;
+
+    /**
+     * 子菜单
+     */
+    private List<SysMenu> children = new ArrayList<>();
+
+    public Long getMenuId() {
+        return menuId;
+    }
+
+    public void setMenuId(Long menuId) {
+        this.menuId = menuId;
+    }
+
+    @NotBlank(message = "菜单名称不能为空")
+    @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
+    public String getMenuName() {
+        return menuName;
+    }
+
+    public void setMenuName(String menuName) {
+        this.menuName = menuName;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    @NotNull(message = "显示顺序不能为空")
+    public Integer getOrderNum() {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum) {
+        this.orderNum = orderNum;
+    }
+
+    @Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    @Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
+    public String getComponent() {
+        return component;
+    }
+
+    public void setComponent(String component) {
+        this.component = component;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    public String getIsFrame() {
+        return isFrame;
+    }
+
+    public void setIsFrame(String isFrame) {
+        this.isFrame = isFrame;
+    }
+
+    public String getIsCache() {
+        return isCache;
+    }
+
+    public void setIsCache(String isCache) {
+        this.isCache = isCache;
+    }
+
+    @NotBlank(message = "菜单类型不能为空")
+    public String getMenuType() {
+        return menuType;
+    }
+
+    public void setMenuType(String menuType) {
+        this.menuType = menuType;
+    }
+
+    public String getVisible() {
+        return visible;
+    }
+
+    public void setVisible(String visible) {
+        this.visible = visible;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
+    public String getPerms() {
+        return perms;
+    }
+
+    public void setPerms(String perms) {
+        this.perms = perms;
+    }
+
+    public String getIcon() {
+        return icon;
+    }
+
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+
+    public List<SysMenu> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<SysMenu> children) {
+        this.children = children;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("menuId", getMenuId())
+                .append("menuName", getMenuName())
+                .append("parentId", getParentId())
+                .append("orderNum", getOrderNum())
+                .append("path", getPath())
+                .append("component", getComponent())
+                .append("isFrame", getIsFrame())
+                .append("IsCache", getIsCache())
+                .append("menuType", getMenuType())
+                .append("visible", getVisible())
+                .append("status ", getStatus())
+                .append("perms", getPerms())
+                .append("icon", getIcon())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}

+ 232 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysRole.java

@@ -0,0 +1,232 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.jiayue.common.annotation.Excel;
+import com.jiayue.common.annotation.Excel.ColumnType;
+import com.jiayue.common.core.domain.AuditEntity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+/**
+ * 角色表 sys_role
+ *
+ * @author L.ym
+ */
+public class SysRole extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 角色ID
+     */
+    @Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
+    private Long roleId;
+
+    /**
+     * 角色名称
+     */
+    @Excel(name = "角色名称")
+    private String roleName;
+
+    /**
+     * 角色权限
+     */
+    @Excel(name = "角色权限")
+    private String roleKey;
+
+    /**
+     * 角色排序
+     */
+    @Excel(name = "角色排序")
+    private String roleSort;
+
+    /**
+     * 数据范围
+     * 1:所有数据权限;
+     * 2:自定义数据权限;
+     * 3:本组织单元数据权限;
+     * 4:本组织单元及以下数据权限
+     * 5:仅本人数据权限
+     */
+    @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本组织单元数据权限,4=本组织单元及以下数据权限,5=仅本人数据权限")
+    private String dataScope;
+
+    /**
+     * 菜单树选择项是否关联显示
+     * 0:父子不互相关联显示
+     * 1:父子互相关联显示
+     */
+    private boolean menuCheckStrictly;
+
+    /**
+     * 组织单元树选择项是否关联显示
+     * 0:父子不互相关联显示
+     * 1:父子互相关联显示
+     */
+    private boolean unitCheckStrictly;
+
+    /**
+     * 角色状态(0正常 1停用)
+     */
+    @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    /**
+     * 用户是否存在此角色标识 默认不存在
+     */
+    private boolean flag = false;
+
+    /**
+     * 菜单组
+     */
+    private Long[] menuIds;
+
+    /**
+     * 组织单元组(数据权限)
+     */
+    private Long[] unitIds;
+
+    public SysRole() {
+
+    }
+
+    public SysRole(Long roleId) {
+        this.roleId = roleId;
+    }
+
+    public Long getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId) {
+        this.roleId = roleId;
+    }
+
+    public boolean isAdmin() {
+        return isAdmin(this.roleId);
+    }
+
+    public static boolean isAdmin(Long roleId) {
+        return roleId != null && 1L == roleId;
+    }
+
+    @NotBlank(message = "角色名称不能为空")
+    @Size(max = 30, message = "角色名称长度不能超过30个字符")
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    @NotBlank(message = "权限字符不能为空")
+    @Size(max = 100, message = "权限字符长度不能超过100个字符")
+    public String getRoleKey() {
+        return roleKey;
+    }
+
+    public void setRoleKey(String roleKey) {
+        this.roleKey = roleKey;
+    }
+
+    @NotBlank(message = "显示顺序不能为空")
+    public String getRoleSort() {
+        return roleSort;
+    }
+
+    public void setRoleSort(String roleSort) {
+        this.roleSort = roleSort;
+    }
+
+    public String getDataScope() {
+        return dataScope;
+    }
+
+    public void setDataScope(String dataScope) {
+        this.dataScope = dataScope;
+    }
+
+    public boolean isMenuCheckStrictly() {
+        return menuCheckStrictly;
+    }
+
+    public void setMenuCheckStrictly(boolean menuCheckStrictly) {
+        this.menuCheckStrictly = menuCheckStrictly;
+    }
+
+    public boolean isUnitCheckStrictly() {
+        return unitCheckStrictly;
+    }
+
+    public void setUnitCheckStrictly(boolean unitCheckStrictly) {
+        this.unitCheckStrictly = unitCheckStrictly;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public boolean isFlag() {
+        return flag;
+    }
+
+    public void setFlag(boolean flag) {
+        this.flag = flag;
+    }
+
+    public Long[] getMenuIds() {
+        return menuIds;
+    }
+
+    public void setMenuIds(Long[] menuIds) {
+        this.menuIds = menuIds;
+    }
+
+    public Long[] getUnitIds() {
+        return unitIds;
+    }
+
+    public void setUnitIds(Long[] unitIds) {
+        this.unitIds = unitIds;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("roleId", getRoleId())
+                .append("roleName", getRoleName())
+                .append("roleKey", getRoleKey())
+                .append("roleSort", getRoleSort())
+                .append("dataScope", getDataScope())
+                .append("menuCheckStrictly", isMenuCheckStrictly())
+                .append("unitCheckStrictly", isUnitCheckStrictly())
+                .append("status", getStatus())
+                .append("delFlag", getDelFlag())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}

+ 235 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysUnit.java

@@ -0,0 +1,235 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.jiayue.common.core.domain.AuditEntity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * 组织单元表 sys_unit
+ *
+ * @author L.ym
+ * @date 2020-12-24
+ **/
+public class SysUnit extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 组织单元ID
+     */
+    private Long unitId;
+
+    /**
+     * 父组织单元ID
+     */
+    private Long parentId;
+
+    /**
+     * 祖级列表
+     */
+    private String ancestors;
+
+    /**
+     * 组织单元编号
+     **/
+    private String unitNo;
+
+    /**
+     * 组织单元名称
+     */
+    private String unitName;
+
+    /**
+     * 组织维度类别
+     **/
+    private String unitCategory;
+
+    /**
+     * 显示顺序
+     */
+    private Integer orderNum;
+
+    /**
+     * 负责人
+     */
+    private String leader;
+
+    /**
+     * 联系电话
+     */
+    private String phone;
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 组织单元状态:0正常,1停用
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    /**
+     * 父组织单元名称
+     */
+    private String parentName;
+
+    /**
+     * 子组织单元
+     */
+    private List<SysUnit> children = new ArrayList<>();
+
+    public Long getUnitId() {
+        return unitId;
+    }
+
+    public void setUnitId(Long unitId) {
+        this.unitId = unitId;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getAncestors() {
+        return ancestors;
+    }
+
+    public void setAncestors(String ancestors) {
+        this.ancestors = ancestors;
+    }
+
+    public String getUnitNo() {
+        return unitNo;
+    }
+
+    public void setUnitNo(String unitNo) {
+        this.unitNo = unitNo;
+    }
+
+    @NotBlank(message = "组织单元名称不能为空")
+    @Size(max = 64, message = "组织单元名称长度不能超过64个字符")
+    public String getUnitName() {
+        return unitName;
+    }
+
+    public void setUnitName(String unitName) {
+        this.unitName = unitName;
+    }
+
+    public String getUnitCategory() {
+        return unitCategory;
+    }
+
+    public void setUnitCategory(String unitCategory) {
+        this.unitCategory = unitCategory;
+    }
+
+    @NotNull(message = "显示顺序不能为空")
+    public Integer getOrderNum() {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum) {
+        this.orderNum = orderNum;
+    }
+
+    public String getLeader() {
+        return leader;
+    }
+
+    public void setLeader(String leader) {
+        this.leader = leader;
+    }
+
+    @Size(max = 11, message = "联系电话长度不能超过11个字符")
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    @Email(message = "邮箱格式不正确")
+    @Size(max = 64, message = "邮箱长度不能超过64个字符")
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public List<SysUnit> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<SysUnit> children) {
+        this.children = children;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("unitId", getUnitId())
+                .append("parentId", getParentId())
+                .append("ancestors", getAncestors())
+                .append("unitNo", getUnitNo())
+                .append("unitName", getUnitName())
+                .append("unitCategory", getUnitCategory())
+                .append("orderNum", getOrderNum())
+                .append("leader", getLeader())
+                .append("phone", getPhone())
+                .append("email", getEmail())
+                .append("status", getStatus())
+                .append("delFlag", getDelFlag())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .toString();
+    }
+}

+ 342 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/entity/SysUser.java

@@ -0,0 +1,342 @@
+package com.jiayue.common.core.domain.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.jiayue.common.annotation.Excel;
+import com.jiayue.common.annotation.Excel.ColumnType;
+import com.jiayue.common.annotation.Excel.Type;
+import com.jiayue.common.annotation.Excels;
+import com.jiayue.common.core.domain.AuditEntity;
+import com.jiayue.common.xxs.Xss;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+/**
+ * 用户对象 sys_user
+ *
+ * @author jy
+ */
+public class SysUser extends AuditEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
+    private Long userId;
+
+    /**
+     * 组织单元ID
+     */
+    @Excel(name = "组织单元编号", type = Type.IMPORT)
+    private Long unitId;
+
+    /**
+     * 用户账号
+     */
+    @Excel(name = "登录名称")
+    private String userName;
+
+    /**
+     * 用户昵称
+     */
+    @Excel(name = "用户名称")
+    private String nickName;
+
+    /**
+     * 用户邮箱
+     */
+    @Excel(name = "用户邮箱")
+    private String email;
+
+    /**
+     * 手机号码
+     */
+    @Excel(name = "手机号码")
+    private String phonenumber;
+
+    /**
+     * 用户性别
+     */
+    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
+    private String sex;
+
+    /**
+     * 用户头像
+     */
+    private String avatar;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 盐加密
+     */
+    private String salt;
+
+    /**
+     * 帐号状态(0正常 1停用)
+     */
+    @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    /**
+     * 最后登录IP
+     */
+    @Excel(name = "最后登录IP", type = Type.EXPORT)
+    private String loginIp;
+
+    /**
+     * 最后登录时间
+     */
+    @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+    private Date loginDate;
+
+    /**
+     * 组织单元对象
+     */
+    @Excels({
+            @Excel(name = "组织单元名称", targetAttr = "unitName", type = Type.EXPORT),
+            @Excel(name = "组织单元负责人", targetAttr = "leader", type = Type.EXPORT)
+    })
+    private SysUnit unit;
+
+    /**
+     * 角色对象
+     */
+    private List<SysRole> roles;
+
+    /**
+     * 角色组
+     */
+    private Long[] roleIds;
+
+    /**
+     * 岗位组
+     */
+    private Long[] postIds;
+
+    /**
+     * 角色ID
+     */
+    private Long roleId;
+
+    public SysUser() {
+
+    }
+
+    public SysUser(Long userId) {
+        this.userId = userId;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public boolean isAdmin() {
+        return isAdmin(this.userId);
+    }
+
+    public static boolean isAdmin(Long userId) {
+        return userId != null && 1L == userId;
+    }
+
+    public Long getUnitId() {
+        return unitId;
+    }
+
+    public void setUnitId(Long unitId) {
+        this.unitId = unitId;
+    }
+
+    @Xss(message = "用户昵称不能包含脚本字符")
+    @Size(max = 30, message = "用户昵称长度不能超过30个字符")
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    @Xss(message = "用户账号不能包含脚本字符")
+    @NotBlank(message = "用户账号不能为空")
+    @Size(max = 30, message = "用户账号长度不能超过30个字符")
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    @Email(message = "邮箱格式不正确")
+    @Size(max = 50, message = "邮箱长度不能超过50个字符")
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    @Size(max = 11, message = "手机号码长度不能超过11个字符")
+    public String getPhonenumber() {
+        return phonenumber;
+    }
+
+    public void setPhonenumber(String phonenumber) {
+        this.phonenumber = phonenumber;
+    }
+
+    public String getSex() {
+        return sex;
+    }
+
+    public void setSex(String sex) {
+        this.sex = sex;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    @JsonIgnore
+    @JsonProperty
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getSalt() {
+        return salt;
+    }
+
+    public void setSalt(String salt) {
+        this.salt = salt;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getLoginIp() {
+        return loginIp;
+    }
+
+    public void setLoginIp(String loginIp) {
+        this.loginIp = loginIp;
+    }
+
+    public Date getLoginDate() {
+        return loginDate;
+    }
+
+    public void setLoginDate(Date loginDate) {
+        this.loginDate = loginDate;
+    }
+
+    public SysUnit getUnit() {
+        return unit;
+    }
+
+    public void setUnit(SysUnit unit) {
+        this.unit = unit;
+    }
+
+    public List<SysRole> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(List<SysRole> roles) {
+        this.roles = roles;
+    }
+
+    public Long[] getRoleIds() {
+        return roleIds;
+    }
+
+    public void setRoleIds(Long[] roleIds) {
+        this.roleIds = roleIds;
+    }
+
+    public Long[] getPostIds() {
+        return postIds;
+    }
+
+    public void setPostIds(Long[] postIds) {
+        this.postIds = postIds;
+    }
+
+    public Long getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(Long roleId) {
+        this.roleId = roleId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("userId", getUserId())
+                .append("unitId", getUnitId())
+                .append("userName", getUserName())
+                .append("nickName", getNickName())
+                .append("email", getEmail())
+                .append("phonenumber", getPhonenumber())
+                .append("sex", getSex())
+                .append("avatar", getAvatar())
+                .append("password", getPassword())
+                .append("salt", getSalt())
+                .append("status", getStatus())
+                .append("delFlag", getDelFlag())
+                .append("loginIp", getLoginIp())
+                .append("loginDate", getLoginDate())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("remark", getRemark())
+                .append("unit", getUnit())
+                .toString();
+    }
+}

+ 69 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/model/LoginBody.java

@@ -0,0 +1,69 @@
+package com.jiayue.common.core.domain.model;
+
+/**
+ * 用户登录对象
+ *
+ * @author jy
+ */
+public class LoginBody
+{
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 用户密码
+     */
+    private String password;
+
+    /**
+     * 验证码
+     */
+    private String code;
+
+    /**
+     * 唯一标识
+     */
+    private String uuid;
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public void setUsername(String username)
+    {
+        this.username = username;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public void setPassword(String password)
+    {
+        this.password = password;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getUuid()
+    {
+        return uuid;
+    }
+
+    public void setUuid(String uuid)
+    {
+        this.uuid = uuid;
+    }
+}

+ 268 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/model/LoginUser.java

@@ -0,0 +1,268 @@
+package com.jiayue.common.core.domain.model;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.jiayue.common.core.domain.entity.SysUser;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ *
+ * @author jy
+ */
+public class LoginUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 组织单元ID
+     */
+    private Long unitId;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+    /**
+     * 用户信息
+     */
+    private SysUser user;
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUnitId()
+    {
+        return unitId;
+    }
+
+    public void setUnitId(Long unitId)
+    {
+        this.unitId = unitId;
+    }
+
+    public String getToken()
+    {
+        return token;
+    }
+
+    public void setToken(String token)
+    {
+        this.token = token;
+    }
+
+    public LoginUser()
+    {
+    }
+
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public LoginUser(Long userId, Long unitId, SysUser user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.unitId = unitId;
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    @JSONField(serialize = false)
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserName();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     *
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     *
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     *
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+    public SysUser getUser()
+    {
+        return user;
+    }
+
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+}

+ 10 - 0
wps-system/src/main/java/com/jiayue/common/core/domain/model/RegisterBody.java

@@ -0,0 +1,10 @@
+package com.jiayue.common.core.domain.model;
+
+/**
+ * 用户注册对象
+ *
+ * @author jy
+ **/
+public class RegisterBody extends LoginBody {
+
+}

+ 92 - 0
wps-system/src/main/java/com/jiayue/common/core/page/PageDomain.java

@@ -0,0 +1,92 @@
+package com.jiayue.common.core.page;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 分页数据
+ *
+ * @author jy
+ */
+public class PageDomain {
+    /**
+     * 当前记录起始索引
+     */
+    private Integer pageNum;
+
+    /**
+     * 每页显示记录数
+     */
+    private Integer pageSize;
+
+    /**
+     * 排序列
+     */
+    private String orderByColumn;
+
+    /**
+     * 排序的方向desc或者asc
+     */
+    private String isAsc = "asc";
+
+    /**
+     * 分页参数合理化
+     */
+    private Boolean reasonable = true;
+
+    public String getOrderBy() {
+        if (StrUtil.isEmpty(orderByColumn)) {
+            return "";
+        }
+        //TODO 注:原方法toUnderScoreCase
+        return StrUtil.toUnderlineCase(orderByColumn) + " " + isAsc;
+    }
+
+    public Integer getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(Integer pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public Integer getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public String getOrderByColumn() {
+        return orderByColumn;
+    }
+
+    public void setOrderByColumn(String orderByColumn) {
+        this.orderByColumn = orderByColumn;
+    }
+
+    public String getIsAsc() {
+        return isAsc;
+    }
+
+    public void setIsAsc(String isAsc) {
+        final String descending = "descending";
+        // 兼容前端排序类型:倒序排列
+        if (descending.equals(isAsc)) {
+            this.isAsc = "desc";
+        }
+    }
+
+    public Boolean getReasonable() {
+        if (ObjectUtil.isNull(reasonable)) {
+            return Boolean.TRUE;
+        }
+        return reasonable;
+    }
+
+    public void setReasonable(Boolean reasonable) {
+        this.reasonable = reasonable;
+    }
+
+}

+ 85 - 0
wps-system/src/main/java/com/jiayue/common/core/page/TableDataInfo.java

@@ -0,0 +1,85 @@
+package com.jiayue.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ *
+ * @author jy
+ */
+public class TableDataInfo implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 总记录数 */
+    private long total;
+
+    /** 列表数据 */
+    private List<?> rows;
+
+    /** 消息状态码 */
+    private int code;
+
+    /** 消息内容 */
+    private String msg;
+
+    /**
+     * 表格数据对象
+     */
+    public TableDataInfo()
+    {
+    }
+
+    /**
+     * 分页
+     *
+     * @param list 列表数据
+     * @param total 总记录数
+     */
+    public TableDataInfo(List<?> list, int total)
+    {
+        this.rows = list;
+        this.total = total;
+    }
+
+    public long getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public List<?> getRows()
+    {
+        return rows;
+    }
+
+    public void setRows(List<?> rows)
+    {
+        this.rows = rows;
+    }
+
+    public int getCode()
+    {
+        return code;
+    }
+
+    public void setCode(int code)
+    {
+        this.code = code;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+}

+ 53 - 0
wps-system/src/main/java/com/jiayue/common/core/page/TableSupport.java

@@ -0,0 +1,53 @@
+package com.jiayue.common.core.page;
+
+import com.jiayue.common.core.text.Convert;
+import com.jiayue.common.utils.ServletUtils;
+
+/**
+ * 表格数据处理
+ *
+ * @author jy
+ */
+public class TableSupport {
+    /**
+     * 当前记录起始索引
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 分页参数合理化
+     */
+    public static final String REASONABLE = "reasonable";
+
+    /**
+     * 封装分页对象
+     */
+    public static PageDomain getPageDomain() {
+        PageDomain pageDomain = new PageDomain();
+        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+        return pageDomain;
+    }
+
+    public static PageDomain buildPageRequest() {
+        return getPageDomain();
+    }
+}

+ 228 - 0
wps-system/src/main/java/com/jiayue/common/core/redis/RedisCache.java

@@ -0,0 +1,228 @@
+package com.jiayue.common.core.redis;
+
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * spring redis 工具类
+ *
+ * @author jy
+ **/
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+@AllArgsConstructor
+public class RedisCache {
+    public final RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key   缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key      缓存的键值
+     * @param value    缓存的值
+     * @param timeout  时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout) {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @param unit    时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key) {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public long deleteObject(final Collection collection) {
+        return redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key      缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList) {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key) {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key     缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext()) {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key   Redis键
+     * @param hKey  Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key  Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey) {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 删除Hash中的数据
+     *
+     * @param key   Redis键
+     * @param hKey  Hash键
+     */
+    public void delCacheMapValue(final String key, final String hKey) {
+        HashOperations hashOperations = redisTemplate.opsForHash();
+        hashOperations.delete(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key   Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+}

+ 91 - 0
wps-system/src/main/java/com/jiayue/common/core/text/CharsetKit.java

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

+ 854 - 0
wps-system/src/main/java/com/jiayue/common/core/text/Convert.java

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

+ 77 - 0
wps-system/src/main/java/com/jiayue/common/core/text/StrFormatter.java

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

+ 20 - 0
wps-system/src/main/java/com/jiayue/common/enums/BusinessStatus.java

@@ -0,0 +1,20 @@
+package com.jiayue.common.enums;
+
+/**
+ * 操作状态
+ *
+ * @author jy
+ *
+ */
+public enum BusinessStatus
+{
+    /**
+     * 成功
+     */
+    SUCCESS,
+
+    /**
+     * 失败
+     */
+    FAIL,
+}

+ 59 - 0
wps-system/src/main/java/com/jiayue/common/enums/BusinessType.java

@@ -0,0 +1,59 @@
+package com.jiayue.common.enums;
+
+/**
+ * 业务操作类型
+ *
+ * @author jy
+ */
+public enum BusinessType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 新增
+     */
+    INSERT,
+
+    /**
+     * 修改
+     */
+    UPDATE,
+
+    /**
+     * 删除
+     */
+    DELETE,
+
+    /**
+     * 授权
+     */
+    GRANT,
+
+    /**
+     * 导出
+     */
+    EXPORT,
+
+    /**
+     * 导入
+     */
+    IMPORT,
+
+    /**
+     * 强退
+     */
+    FORCE,
+
+    /**
+     * 生成代码
+     */
+    GENCODE,
+
+    /**
+     * 清空数据
+     */
+    CLEAN,
+}

+ 19 - 0
wps-system/src/main/java/com/jiayue/common/enums/DataSourceType.java

@@ -0,0 +1,19 @@
+package com.jiayue.common.enums;
+
+/**
+ * 数据源
+ *
+ * @author jy
+ */
+public enum DataSourceType
+{
+    /**
+     * 主库
+     */
+    MASTER,
+
+    /**
+     * 从库
+     */
+    SLAVE
+}

+ 18 - 0
wps-system/src/main/java/com/jiayue/common/enums/LimitType.java

@@ -0,0 +1,18 @@
+package com.jiayue.common.enums;
+
+/**
+ * 限流类型
+ *
+ * @author jy
+ **/
+public enum LimitType {
+    /**
+     * 默认策略全局限流
+     */
+    DEFAULT,
+
+    /**
+     * 根据请求者IP进行限流
+     */
+    IP
+}

+ 24 - 0
wps-system/src/main/java/com/jiayue/common/enums/OperatorType.java

@@ -0,0 +1,24 @@
+package com.jiayue.common.enums;
+
+/**
+ * 操作人类别
+ *
+ * @author jy
+ */
+public enum OperatorType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 后台用户
+     */
+    MANAGE,
+
+    /**
+     * 手机端用户
+     */
+    MOBILE
+}

+ 30 - 0
wps-system/src/main/java/com/jiayue/common/enums/UserStatus.java

@@ -0,0 +1,30 @@
+package com.jiayue.common.enums;
+
+/**
+ * 用户状态
+ *
+ * @author jy
+ */
+public enum UserStatus
+{
+    OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
+
+    private final String code;
+    private final String info;
+
+    UserStatus(String code, String info)
+    {
+        this.code = code;
+        this.info = info;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String getInfo()
+    {
+        return info;
+    }
+}

+ 15 - 0
wps-system/src/main/java/com/jiayue/common/exception/DemoModeException.java

@@ -0,0 +1,15 @@
+package com.jiayue.common.exception;
+
+/**
+ * 演示模式异常
+ *
+ * @author jy
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}

+ 52 - 0
wps-system/src/main/java/com/jiayue/common/exception/GlobalException.java

@@ -0,0 +1,52 @@
+package com.jiayue.common.exception;
+
+/**
+ * 全局异常
+ *
+ * @author jy
+ **/
+public class GlobalException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 错误提示
+     */
+    private String message;
+
+    /**
+     * 错误明细,内部调试错误
+     *
+     * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+     */
+    private String detailMessage;
+
+    /**
+     * 空构造方法,避免反序列化问题
+     */
+    public GlobalException() {
+    }
+
+    public GlobalException(String message) {
+        this.message = message;
+    }
+
+    public String getDetailMessage() {
+        return detailMessage;
+    }
+
+    public GlobalException setDetailMessage(String detailMessage) {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public GlobalException setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+}

+ 65 - 0
wps-system/src/main/java/com/jiayue/common/exception/ServiceException.java

@@ -0,0 +1,65 @@
+package com.jiayue.common.exception;
+
+/**
+ * 业务异常
+ *
+ * @author jy
+ **/
+public class ServiceException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 错误码
+     */
+    private Integer code;
+
+    /**
+     * 错误提示
+     */
+    private String message;
+
+    /**
+     * 错误明细,内部调试错误
+     *
+     * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+     */
+    private String detailMessage;
+
+    /**
+     * 空构造方法,避免反序列化问题
+     */
+    public ServiceException() {
+    }
+
+    public ServiceException(String message) {
+        this.message = message;
+    }
+
+    public ServiceException(String message, Integer code) {
+        this.message = message;
+        this.code = code;
+    }
+
+    public String getDetailMessage() {
+        return detailMessage;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public ServiceException setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage) {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}

+ 26 - 0
wps-system/src/main/java/com/jiayue/common/exception/UtilException.java

@@ -0,0 +1,26 @@
+package com.jiayue.common.exception;
+
+/**
+ * 工具类异常
+ *
+ * @author jy
+ */
+public class UtilException extends RuntimeException
+{
+    private static final long serialVersionUID = 8247610319171014183L;
+
+    public UtilException(Throwable e)
+    {
+        super(e.getMessage(), e);
+    }
+
+    public UtilException(String message)
+    {
+        super(message);
+    }
+
+    public UtilException(String message, Throwable throwable)
+    {
+        super(message, throwable);
+    }
+}

+ 85 - 0
wps-system/src/main/java/com/jiayue/common/exception/base/BaseException.java

@@ -0,0 +1,85 @@
+package com.jiayue.common.exception.base;
+
+import com.jiayue.common.utils.MessageUtils;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 基础异常
+ *
+ * @author jy
+ */
+public class BaseException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 所属模块
+     */
+    private String module;
+
+    /**
+     * 错误码
+     */
+    private String code;
+
+    /**
+     * 错误码对应的参数
+     */
+    private Object[] args;
+
+    /**
+     * 错误消息
+     */
+    private String defaultMessage;
+
+    public BaseException(String module, String code, Object[] args, String defaultMessage) {
+        this.module = module;
+        this.code = code;
+        this.args = args;
+        this.defaultMessage = defaultMessage;
+    }
+
+    public BaseException(String module, String code, Object[] args) {
+        this(module, code, args, null);
+    }
+
+    public BaseException(String module, String defaultMessage) {
+        this(module, null, null, defaultMessage);
+    }
+
+    public BaseException(String code, Object[] args) {
+        this(null, code, args, null);
+    }
+
+    public BaseException(String defaultMessage) {
+        this(null, null, null, defaultMessage);
+    }
+
+    @Override
+    public String getMessage() {
+        String message = null;
+        if (!StrUtil.isEmpty(code)) {
+            message = MessageUtils.message(code, args);
+        }
+        if (message == null) {
+            message = defaultMessage;
+        }
+        return message;
+    }
+
+    public String getModule() {
+        return module;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public Object[] getArgs() {
+        return args;
+    }
+
+    public String getDefaultMessage() {
+        return defaultMessage;
+    }
+}

+ 17 - 0
wps-system/src/main/java/com/jiayue/common/exception/file/FileException.java

@@ -0,0 +1,17 @@
+package com.jiayue.common.exception.file;
+
+import com.jiayue.common.exception.base.BaseException;
+
+/**
+ * 文件信息异常类
+ *
+ * @author jy
+ */
+public class FileException extends BaseException {
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args) {
+        super("file", code, args, null);
+    }
+
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/file/FileNameLengthLimitExceededException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.file;
+
+/**
+ * 文件名称超长限制异常类
+ *
+ * @author jy
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength)
+    {
+        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
+    }
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/file/FileSizeLimitExceededException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.file;
+
+/**
+ * 文件名大小限制异常类
+ *
+ * @author jy
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize)
+    {
+        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
+    }
+}

+ 69 - 0
wps-system/src/main/java/com/jiayue/common/exception/file/InvalidExtensionException.java

@@ -0,0 +1,69 @@
+package com.jiayue.common.exception.file;
+
+import org.apache.commons.fileupload.FileUploadException;
+
+import java.util.Arrays;
+
+/**
+ * 文件上传 异常类
+ *
+ * @author jy
+ */
+public class InvalidExtensionException extends FileUploadException {
+    private static final long serialVersionUID = 1L;
+
+    private String[] allowedExtension;
+    private String extension;
+    private String filename;
+
+    public InvalidExtensionException(String[] allowedExtension, String extension, String filename) {
+        super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
+        this.allowedExtension = allowedExtension;
+        this.extension = extension;
+        this.filename = filename;
+    }
+
+    public String[] getAllowedExtension() {
+        return allowedExtension;
+    }
+
+    public String getExtension() {
+        return extension;
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+
+    public static class InvalidImageExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidFlashExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidMediaExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidVideoExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+}

+ 34 - 0
wps-system/src/main/java/com/jiayue/common/exception/job/TaskException.java

@@ -0,0 +1,34 @@
+package com.jiayue.common.exception.job;
+
+/**
+ * 计划策略异常
+ *
+ * @author jy
+ */
+public class TaskException extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    private Code code;
+
+    public TaskException(String msg, Code code)
+    {
+        this(msg, code, null);
+    }
+
+    public TaskException(String msg, Code code, Exception nestedEx)
+    {
+        super(msg, nestedEx);
+        this.code = code;
+    }
+
+    public Code getCode()
+    {
+        return code;
+    }
+
+    public enum Code
+    {
+        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+    }
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/user/CaptchaException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.user;
+
+/**
+ * 验证码错误异常类
+ *
+ * @author jy
+ */
+public class CaptchaException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException()
+    {
+        super("user.jcaptcha.error", null);
+    }
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/user/CaptchaExpireException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.user;
+
+/**
+ * 验证码失效异常类
+ *
+ * @author jy
+ */
+public class CaptchaExpireException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaExpireException()
+    {
+        super("user.jcaptcha.expire", null);
+    }
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/user/UserException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.user;
+
+import com.jiayue.common.exception.base.BaseException;
+
+/**
+ * 用户信息异常类
+ *
+ * @author jy
+ */
+public class UserException extends BaseException {
+    private static final long serialVersionUID = 1L;
+
+    public UserException(String code, Object[] args) {
+        super("user", code, args, null);
+    }
+}

+ 16 - 0
wps-system/src/main/java/com/jiayue/common/exception/user/UserPasswordNotMatchException.java

@@ -0,0 +1,16 @@
+package com.jiayue.common.exception.user;
+
+/**
+ * 用户密码不正确或不符合规范异常类
+ *
+ * @author jy
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}

+ 47 - 0
wps-system/src/main/java/com/jiayue/common/filter/RepeatableFilter.java

@@ -0,0 +1,47 @@
+package com.jiayue.common.filter;
+
+import org.springframework.http.MediaType;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * Repeatable 过滤器
+ *
+ * @author jy
+ */
+public class RepeatableFilter implements Filter {
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+        ServletRequest requestWrapper = null;
+        if (request instanceof HttpServletRequest
+                && StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
+            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+        }
+        if (null == requestWrapper) {
+            chain.doFilter(request, response);
+        } else {
+            chain.doFilter(requestWrapper, response);
+        }
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

+ 67 - 0
wps-system/src/main/java/com/jiayue/common/filter/RepeatedlyRequestWrapper.java

@@ -0,0 +1,67 @@
+package com.jiayue.common.filter;
+
+import com.jiayue.common.utils.http.HttpHelper;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * 构建可重复读取inputStream的request
+ *
+ * @author jy
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
+    private final byte[] body;
+
+    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
+        super(request);
+        request.setCharacterEncoding("UTF-8");
+        response.setCharacterEncoding("UTF-8");
+
+        body = HttpHelper.getBodyString(request).getBytes("UTF-8");
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+        return new ServletInputStream() {
+            @Override
+            public int read() throws IOException {
+                return bais.read();
+            }
+
+            @Override
+            public int available() throws IOException {
+                return body.length;
+            }
+
+            @Override
+            public boolean isFinished() {
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+
+            }
+        };
+    }
+}

+ 69 - 0
wps-system/src/main/java/com/jiayue/common/filter/XssFilter.java

@@ -0,0 +1,69 @@
+package com.jiayue.common.filter;
+
+import org.springframework.http.HttpMethod;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 防止XSS攻击的过滤器
+ *
+ * @author jy
+ */
+public class XssFilter implements Filter {
+    /**
+     * 排除链接
+     */
+    private List<String> excludes = new ArrayList<>();
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        String tempExcludes = filterConfig.getInitParameter("excludes");
+        if (StrUtil.isNotEmpty(tempExcludes)) {
+            String[] url = tempExcludes.split(",");
+            for (int i = 0; url != null && i < url.length; i++) {
+                excludes.add(url[i]);
+            }
+        }
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        if (handleExcludeURL(req, resp)) {
+            chain.doFilter(request, response);
+            return;
+        }
+        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
+        String url = request.getServletPath();
+        String method = request.getMethod();
+        // GET DELETE 不过滤
+        if (method == null || method.matches(HttpMethod.GET.name()) || method.matches(HttpMethod.DELETE.name())) {
+            return true;
+        }
+        return StrUtil.containsAny(url, excludes.toArray(new String[excludes.size()]));
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

+ 98 - 0
wps-system/src/main/java/com/jiayue/common/filter/XssHttpServletRequestWrapper.java

@@ -0,0 +1,98 @@
+package com.jiayue.common.filter;
+
+import com.jiayue.common.utils.html.EscapeUtil;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * XSS过滤处理
+ *
+ * @author jy
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+    /**
+     * @param request
+     */
+    public XssHttpServletRequestWrapper(HttpServletRequest request) {
+        super(request);
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+        String[] values = super.getParameterValues(name);
+        if (values != null) {
+            int length = values.length;
+            String[] escapeValues = new String[length];
+            for (int i = 0; i < length; i++) {
+                // 防xss攻击和过滤前后空格
+                escapeValues[i] = EscapeUtil.clean(values[i]).trim();
+            }
+            return escapeValues;
+        }
+        return super.getParameterValues(name);
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        // 非json类型,直接返回
+        if (!isJsonRequest()) {
+            return super.getInputStream();
+        }
+
+        // 为空,直接返回
+        String json = IOUtils.toString(super.getInputStream(), "utf-8");
+        if (StrUtil.isEmpty(json)) {
+            return super.getInputStream();
+        }
+
+        // xss过滤
+        json = EscapeUtil.clean(json).trim();
+        byte[] jsonBytes = json.getBytes("utf-8");
+        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
+        return new ServletInputStream() {
+            @Override
+            public boolean isFinished() {
+                return true;
+            }
+
+            @Override
+            public boolean isReady() {
+                return true;
+            }
+
+            @Override
+            public int available() throws IOException {
+                return jsonBytes.length;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+            }
+
+            @Override
+            public int read() throws IOException {
+                return bis.read();
+            }
+        };
+    }
+
+    /**
+     * 是否是Json请求
+     */
+    public boolean isJsonRequest() {
+        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
+        return StrUtil.startWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+    }
+}

+ 113 - 0
wps-system/src/main/java/com/jiayue/common/utils/Arith.java

@@ -0,0 +1,113 @@
+package com.jiayue.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 精确的浮点数运算
+ *
+ * @author jy
+ */
+public class Arith {
+
+    /**
+     * 默认除法运算精度
+     */
+    private static final int DEF_DIV_SCALE = 10;
+
+    /**
+     * 这个类不能实例化
+     */
+    private Arith() {
+    }
+
+    /**
+     * 提供精确的加法运算。
+     *
+     * @param v1 被加数
+     * @param v2 加数
+     * @return 两个参数的和
+     */
+    public static double add(double v1, double v2) {
+        BigDecimal b1 = BigDecimal.valueOf(v1);
+        BigDecimal b2 = BigDecimal.valueOf(v2);
+        return b1.add(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的减法运算。
+     *
+     * @param v1 被减数
+     * @param v2 减数
+     * @return 两个参数的差
+     */
+    public static double sub(double v1, double v2) {
+        BigDecimal b1 = BigDecimal.valueOf(v1);
+        BigDecimal b2 = BigDecimal.valueOf(v2);
+        return b1.subtract(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的乘法运算。
+     *
+     * @param v1 被乘数
+     * @param v2 乘数
+     * @return 两个参数的积
+     */
+    public static double mul(double v1, double v2) {
+        BigDecimal b1 = BigDecimal.valueOf(v1);
+        BigDecimal b2 = BigDecimal.valueOf(v2);
+        return b1.multiply(b2).doubleValue();
+    }
+
+    /**
+     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
+     * 小数点以后10位,以后的数字四舍五入。
+     *
+     * @param v1 被除数
+     * @param v2 除数
+     * @return 两个参数的商
+     */
+    public static double div(double v1, double v2) {
+        return div(v1, v2, DEF_DIV_SCALE);
+    }
+
+    /**
+     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
+     * 定精度,以后的数字四舍五入。
+     *
+     * @param v1    被除数
+     * @param v2    除数
+     * @param scale 表示表示需要精确到小数点以后几位。
+     * @return 两个参数的商
+     */
+    public static double div(double v1, double v2, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b1 = BigDecimal.valueOf(v1);
+        BigDecimal b2 = BigDecimal.valueOf(v2);
+        if (b1.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO.doubleValue();
+        }
+        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    /**
+     * 提供精确的小数位四舍五入处理。
+     *
+     * @param v     需要四舍五入的数字
+     * @param scale 小数点后保留几位
+     * @return 四舍五入后的结果
+     */
+    public static double round(double v, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b = BigDecimal.valueOf(v);
+        BigDecimal one = BigDecimal.ONE;
+        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+}

+ 70 - 0
wps-system/src/main/java/com/jiayue/common/utils/DateUtil.java

@@ -0,0 +1,70 @@
+package com.jiayue.common.utils;
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+
+import cn.hutool.core.date.DatePattern;
+import lombok.experimental.UtilityClass;
+
+/**
+ * 日期工具
+ *
+ * @author L.ym
+ * @date 2020-12-29
+ **/
+@UtilityClass
+public class DateUtil extends cn.hutool.core.date.DateUtil {
+
+    /**
+     * 获取当前日期时间,无符号
+     *
+     * @return java.lang.String
+     **/
+    public String nowOfPure() {
+        return format(date(), DatePattern.PURE_DATETIME_FORMAT);
+    }
+
+    /**
+     * LocalDate转Date
+     *
+     * @param localDate LocalDate参数
+     * @return java.util.Date
+     **/
+    public Date asDate(LocalDate localDate) {
+        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
+    }
+
+    /**
+     * LocalDateTime转Date
+     *
+     * @param localDateTime LocalDateTime参数
+     * @return java.util.Date
+     **/
+    public Date asDate(LocalDateTime localDateTime) {
+        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+    }
+
+    /**
+     * Date转LocalDate
+     *
+     * @param date Date参数
+     * @return java.time.LocalDate
+     **/
+    public LocalDate asLocalDate(Date date) {
+        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
+    }
+
+    /**
+     * Date转LocalDateTime
+     *
+     * @param date Date参数
+     * @return java.time.LocalDateTime
+     **/
+    public LocalDateTime asLocalDateTime(Date date) {
+        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
+    }
+
+}

+ 160 - 0
wps-system/src/main/java/com/jiayue/common/utils/DictUtils.java

@@ -0,0 +1,160 @@
+package com.jiayue.common.utils;
+
+import com.jiayue.common.constant.Global;
+import com.jiayue.common.core.domain.entity.SysDictData;
+import com.jiayue.common.core.redis.RedisCache;
+import com.jiayue.common.utils.spring.SpringUtils;
+
+import java.util.Collection;
+import java.util.List;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 字典工具类
+ *
+ * @author jy
+ */
+public class DictUtils {
+    /**
+     * 分隔符
+     */
+    public static final String SEPARATOR = ",";
+
+    /**
+     * 设置字典缓存
+     *
+     * @param key       参数键
+     * @param dictDatas 字典数据列表
+     */
+    public static void setDictCache(String key, List<SysDictData> dictDatas) {
+        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+    }
+
+    /**
+     * 获取字典缓存
+     *
+     * @param key 参数键
+     * @return dictDatas 字典数据列表
+     */
+    @SuppressWarnings("unchecked")
+    public static List<SysDictData> getDictCache(String key) {
+        Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+        if (ObjectUtil.isNotNull(cacheObj)) {
+            return (List<SysDictData>) cacheObj;
+        }
+        return null;
+    }
+
+    /**
+     * 根据字典类型和字典值获取字典标签
+     *
+     * @param dictType  字典类型
+     * @param dictValue 字典值
+     * @return 字典标签
+     */
+    public static String getDictLabel(String dictType, String dictValue) {
+        return getDictLabel(dictType, dictValue, SEPARATOR);
+    }
+
+    /**
+     * 根据字典类型和字典标签获取字典值
+     *
+     * @param dictType  字典类型
+     * @param dictLabel 字典标签
+     * @return 字典值
+     */
+    public static String getDictValue(String dictType, String dictLabel) {
+        return getDictValue(dictType, dictLabel, SEPARATOR);
+    }
+
+    /**
+     * 根据字典类型和字典值获取字典标签
+     *
+     * @param dictType  字典类型
+     * @param dictValue 字典值
+     * @param separator 分隔符
+     * @return 字典标签
+     */
+    public static String getDictLabel(String dictType, String dictValue, String separator) {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> dataList = getDictCache(dictType);
+
+        if (StrUtil.containsAny(separator, dictValue) && ObjectUtil.isNotEmpty(dataList)) {
+            for (SysDictData dict : dataList) {
+                for (String value : dictValue.split(separator)) {
+                    if (value.equals(dict.getDictValue())) {
+                        propertyString.append(dict.getDictLabel()).append(separator);
+                        break;
+                    }
+                }
+            }
+        } else {
+            for (SysDictData dict : dataList) {
+                if (dictValue.equals(dict.getDictValue())) {
+                    return dict.getDictLabel();
+                }
+            }
+        }
+        return StrUtil.removeAll(propertyString.toString(), separator);
+    }
+
+    /**
+     * 根据字典类型和字典标签获取字典值
+     *
+     * @param dictType  字典类型
+     * @param dictLabel 字典标签
+     * @param separator 分隔符
+     * @return 字典值
+     */
+    public static String getDictValue(String dictType, String dictLabel, String separator) {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> dataList = getDictCache(dictType);
+
+        if (StrUtil.containsAny(separator, dictLabel) && ObjectUtil.isNotEmpty(dataList)) {
+            for (SysDictData dict : dataList) {
+                for (String label : dictLabel.split(separator)) {
+                    if (label.equals(dict.getDictLabel())) {
+                        propertyString.append(dict.getDictValue()).append(separator);
+                        break;
+                    }
+                }
+            }
+        } else {
+            for (SysDictData dict : dataList) {
+                if (dictLabel.equals(dict.getDictLabel())) {
+                    return dict.getDictValue();
+                }
+            }
+        }
+        return StrUtil.removeAll(propertyString.toString(), separator);
+    }
+
+    /**
+     * 删除指定字典缓存
+     *
+     * @param key 字典键
+     */
+    public static void removeDictCache(String key) {
+        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
+    }
+
+    /**
+     * 清空字典缓存
+     */
+    public static void clearDictCache() {
+        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(Global.SYS_DICT_KEY + "*");
+        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+    }
+
+    /**
+     * 设置cache key
+     *
+     * @param configKey 参数键
+     * @return 缓存键key
+     */
+    public static String getCacheKey(String configKey) {
+        return Global.SYS_DICT_KEY + configKey;
+    }
+}

+ 35 - 0
wps-system/src/main/java/com/jiayue/common/utils/ExceptionUtil.java

@@ -0,0 +1,35 @@
+package com.jiayue.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 错误信息处理类
+ *
+ * @author jy
+ */
+public class ExceptionUtil {
+    /**
+     * 获取exception的详细错误信息。
+     */
+    public static String getExceptionMessage(Throwable e) {
+        StringWriter sw = new StringWriter();
+        e.printStackTrace(new PrintWriter(sw, true));
+        return sw.toString();
+    }
+
+    public static String getRootErrorMessage(Exception e) {
+        Throwable root = cn.hutool.core.exceptions.ExceptionUtil.getRootCause(e);
+        root = (root == null ? e : root);
+        if (root == null) {
+            return StrUtil.EMPTY;
+        }
+        String msg = root.getMessage();
+        if (msg == null) {
+            return StrUtil.NULL;
+        }
+        return StrUtil.nullToEmpty(msg);
+    }
+}

+ 18 - 0
wps-system/src/main/java/com/jiayue/common/utils/LogUtils.java

@@ -0,0 +1,18 @@
+package com.jiayue.common.utils;
+
+/**
+ * 处理并记录日志文件
+ *
+ * @author jy
+ */
+public class LogUtils
+{
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+}

+ 26 - 0
wps-system/src/main/java/com/jiayue/common/utils/MessageUtils.java

@@ -0,0 +1,26 @@
+package com.jiayue.common.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import com.jiayue.common.utils.spring.SpringUtils;
+
+/**
+ * 获取i18n资源文件
+ *
+ * @author jy
+ */
+public class MessageUtils
+{
+    /**
+     * 根据消息键和参数 获取消息 委托给spring messageSource
+     *
+     * @param code 消息键
+     * @param args 参数
+     * @return 获取国际化翻译值
+     */
+    public static String message(String code, Object... args)
+    {
+        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
+        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+    }
+}

+ 32 - 0
wps-system/src/main/java/com/jiayue/common/utils/PageUtils.java

@@ -0,0 +1,32 @@
+package com.jiayue.common.utils;
+
+import com.github.pagehelper.PageHelper;
+import com.jiayue.common.core.page.PageDomain;
+import com.jiayue.common.core.page.TableSupport;
+import com.jiayue.common.utils.sql.SqlUtil;
+
+/**
+ * 分页工具类
+ *
+ * @author jy
+ **/
+public class PageUtils extends PageHelper {
+    /**
+     * 设置请求分页数据
+     */
+    public static void startPage() {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+        Boolean reasonable = pageDomain.getReasonable();
+        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+    }
+
+    /**
+     * 清理分页的线程变量
+     */
+    public static void clearPage() {
+        PageHelper.clearPage();
+    }
+}

+ 100 - 0
wps-system/src/main/java/com/jiayue/common/utils/SecurityUtils.java

@@ -0,0 +1,100 @@
+package com.jiayue.common.utils;
+
+import com.jiayue.common.constant.HttpStatus;
+import com.jiayue.common.core.domain.model.LoginUser;
+import com.jiayue.common.exception.ServiceException;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * 安全服务工具类
+ *
+ * @author jy
+ */
+public class SecurityUtils {
+    /**
+     * 用户ID
+     **/
+    public static Long getUserId() {
+        try {
+            return getLoginUser().getUserId();
+        } catch (Exception e) {
+            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取组织单元ID
+     **/
+    public static Long getUnitId() {
+        try {
+            return getLoginUser().getUnitId();
+        } catch (Exception e) {
+            throw new ServiceException("获取组织单元ID异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取用户账户
+     **/
+    public static String getUsername() {
+        try {
+            return getLoginUser().getUsername();
+        } catch (Exception e) {
+            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取用户
+     **/
+    public static LoginUser getLoginUser() {
+        try {
+            return (LoginUser) getAuthentication().getPrincipal();
+        } catch (Exception e) {
+            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取Authentication
+     */
+    public static Authentication getAuthentication() {
+        return SecurityContextHolder.getContext().getAuthentication();
+    }
+
+    /**
+     * 生成BCryptPasswordEncoder密码
+     *
+     * @param password 密码
+     * @return 加密字符串
+     */
+    public static String encryptPassword(String password) {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.encode(password);
+    }
+
+    /**
+     * 判断密码是否相同
+     *
+     * @param rawPassword     真实密码
+     * @param encodedPassword 加密后字符
+     * @return 结果
+     */
+    public static boolean matchesPassword(String rawPassword, String encodedPassword) {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.matches(rawPassword, encodedPassword);
+    }
+
+    /**
+     * 是否为管理员
+     *
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public static boolean isAdmin(Long userId) {
+        return userId != null && 1L == userId;
+    }
+}

+ 130 - 0
wps-system/src/main/java/com/jiayue/common/utils/ServletUtils.java

@@ -0,0 +1,130 @@
+package com.jiayue.common.utils;
+
+import com.jiayue.common.core.text.Convert;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 客户端工具类
+ *
+ * @author jy
+ */
+public class ServletUtils {
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name) {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue) {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name) {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue) {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name) {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue) {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest() {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse() {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession() {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes() {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     *
+     * @param response 渲染对象
+     * @param string   待渲染的字符串
+     */
+    public static void renderString(HttpServletResponse response, String string) {
+        try {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request) {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json")) {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StrUtil.containsAnyIgnoreCase(uri, ".json", ".xml")) {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StrUtil.containsAnyIgnoreCase(ajax, "json", "xml");
+    }
+}

+ 100 - 0
wps-system/src/main/java/com/jiayue/common/utils/Threads.java

@@ -0,0 +1,100 @@
+package com.jiayue.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 线程相关工具类.
+ *
+ * @author jy
+ */
+public class Threads
+{
+    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
+
+    /**
+     * sleep等待,单位为毫秒
+     */
+    public static void sleep(long milliseconds)
+    {
+        try
+        {
+            Thread.sleep(milliseconds);
+        }
+        catch (InterruptedException e)
+        {
+            return;
+        }
+    }
+
+    /**
+     * 停止线程池
+     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
+     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
+     * 如果仍然超時,則強制退出.
+     * 另对在shutdown时线程本身被调用中断做了处理.
+     */
+    public static void shutdownAndAwaitTermination(ExecutorService pool)
+    {
+        if (pool != null && !pool.isShutdown())
+        {
+            pool.shutdown();
+            try
+            {
+                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                {
+                    pool.shutdownNow();
+                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                    {
+                        logger.info("Pool did not terminate");
+                    }
+                }
+            }
+            catch (InterruptedException ie)
+            {
+                pool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    /**
+     * 打印线程异常信息
+     */
+    public static void printException(Runnable r, Throwable t)
+    {
+        if (t == null && r instanceof Future<?>)
+        {
+            try
+            {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone())
+                {
+                    future.get();
+                }
+            }
+            catch (CancellationException ce)
+            {
+                t = ce;
+            }
+            catch (ExecutionException ee)
+            {
+                t = ee.getCause();
+            }
+            catch (InterruptedException ie)
+            {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null)
+        {
+            logger.error(t.getMessage(), t);
+        }
+    }
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است