Przeglądaj źródła

update 更改包名为 org.dromara
update 更改文档地址为 plus-doc.dromara.org

疯狂的狮子li 2 lat temu
rodzic
commit
df38aad2b5
100 zmienionych plików z 1249 dodań i 4760 usunięć
  1. 18 17
      README.md
  2. 6 6
      pom.xml
  3. 6 6
      ruoyi-admin/pom.xml
  4. 0 23
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  5. 0 18
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
  6. 0 153
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
  7. 0 135
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
  8. 0 32
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/IndexController.java
  9. 0 25
      ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/CaptchaVo.java
  10. 0 25
      ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java
  11. 0 15
      ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginVo.java
  12. 0 22
      ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/TenantListVo.java
  13. 0 390
      ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
  14. 0 106
      ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java
  15. 23 0
      ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java
  16. 18 0
      ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java
  17. 153 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
  18. 135 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java
  19. 32 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java
  20. 25 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/CaptchaVo.java
  21. 25 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/LoginTenantVo.java
  22. 15 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/LoginVo.java
  23. 22 0
      ruoyi-admin/src/main/java/org/dromara/web/domain/vo/TenantListVo.java
  24. 391 0
      ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java
  25. 106 0
      ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java
  26. 9 9
      ruoyi-admin/src/main/resources/application.yml
  27. 0 45
      ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
  28. 0 70
      ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
  29. 0 72
      ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
  30. 0 54
      ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
  31. 45 0
      ruoyi-admin/src/test/java/org/dromara/test/AssertUnitTest.java
  32. 70 0
      ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java
  33. 72 0
      ruoyi-admin/src/test/java/org/dromara/test/ParamUnitTest.java
  34. 54 0
      ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java
  35. 1 1
      ruoyi-common/pom.xml
  36. 22 22
      ruoyi-common/ruoyi-common-bom/pom.xml
  37. 1 1
      ruoyi-common/ruoyi-common-core/pom.xml
  38. 0 16
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java
  39. 0 54
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java
  40. 0 49
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java
  41. 0 57
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java
  42. 0 39
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java
  43. 0 30
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java
  44. 0 25
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
  45. 0 63
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java
  46. 0 81
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
  47. 0 39
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GlobalConstants.java
  48. 0 93
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java
  49. 0 45
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java
  50. 0 132
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java
  51. 0 110
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java
  52. 0 38
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java
  53. 0 62
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java
  54. 0 35
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/EmailLoginBody.java
  55. 0 48
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
  56. 0 123
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
  57. 0 17
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
  58. 0 34
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java
  59. 0 27
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java
  60. 0 32
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java
  61. 0 44
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java
  62. 0 30
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/TenantStatus.java
  63. 0 30
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java
  64. 0 37
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java
  65. 0 17
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java
  66. 0 53
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java
  67. 0 67
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
  68. 0 26
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java
  69. 0 79
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
  70. 0 21
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java
  71. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java
  72. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java
  73. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java
  74. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java
  75. 0 20
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
  76. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java
  77. 0 19
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java
  78. 0 41
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java
  79. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/ConfigService.java
  80. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DeptService.java
  81. 0 57
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DictService.java
  82. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/OssService.java
  83. 0 18
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/UserService.java
  84. 0 168
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java
  85. 0 92
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MapstructUtils.java
  86. 0 28
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java
  87. 0 193
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
  88. 0 62
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
  89. 0 254
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java
  90. 0 321
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
  91. 0 75
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java
  92. 0 35
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java
  93. 0 28
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java
  94. 0 43
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
  95. 0 40
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java
  96. 0 33
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java
  97. 0 67
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/RegionUtils.java
  98. 0 56
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java
  99. 0 57
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java
  100. 0 9
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/AddGroup.java

+ 18 - 17
README.md

@@ -5,7 +5,7 @@
 ## 平台简介
 
 [![码云Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/dromara/RuoYi-Vue-Plus)
-[![GitHub](https://img.shields.io/github/stars/JavaLionLi/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/dromara/RuoYi-Vue-Plus)
+[![GitHub](https://img.shields.io/github/stars/dromara/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/dromara/RuoYi-Vue-Plus)
 [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
 [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
 <br>
@@ -19,7 +19,7 @@
 > 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
 活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
 
-> 系统演示: [传送门](https://javalionli.gitee.io/plus-doc/#/common/demo_system)
+> 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system)
 
 > 前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
 
@@ -27,7 +27,7 @@
 
 | 功能          | 本框架                                                                                                               | RuoYi                                                                              |
 |-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
-| 前端项目        | 基于vue3-element-admin开源项目重写<br/>Vue3 + TS + ElementPlus                                                            | 基于Vue2/Vue3 + JS                                                                   | 
+| 前端项目        | 采用 Vue3 + TS + ElementPlus 重写                                                                                     | 基于Vue2/Vue3 + JS                                                                   | 
 | 后端项目结构      | 采用插件化 + 扩展包形式 结构解耦 易于扩展                                                                                           | 模块相互注入耦合严重难以扩展                                                                     | 
 | 后端代码风格      | 严格遵守Alibaba规范与项目统一配置的代码格式化                                                                                        | 代码书写与常规结构不同阅读障碍大                                                                   |
 | Web容器       | 采用 Undertow 基于 XNIO 的高性能容器                                                                                        | 采用 Tomcat                                                                          |
@@ -51,6 +51,7 @@
 | WebSocket协议 | 基于 Spring 封装的 WebSocket 协议 扩展了Token鉴权与分布式会话同步 不再只是基于单机的废物                                                         | 无                                                                                  |
 | 序列化         | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                                    | 采用 fastjson bugjson 远近闻名                                                           | 
 | 分布式幂等       | 参考美团GTIS防重系统简化实现(细节可看文档)                                                                                          | 手动编写注解基于aop实现                                                                      |
+| 分布式锁        | 采用 Lock4j 底层基于 Redisson                                                                                           | 无                                                                                  |
 | 分布式任务调度     | 采用 Xxl-Job 天生支持分布式 统一的管理中心                                                                                        | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造                                                   | 
 | 文件存储        | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储                                                     | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应                                                    |
 | 云存储         | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家                                                                          | 不支持                                                                                |
@@ -101,17 +102,17 @@
 
 使用框架前请仔细阅读文档重点注意事项
 <br>
->[初始化项目 必看](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/init)
->>[https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/init](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/init)
+>[初始化项目 必看](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init)
+>>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init)
 >
->[专栏与视频 入门必看](https://javalionli.gitee.io/plus-doc/#/common/column)
->>[https://javalionli.gitee.io/plus-doc/#/common/column](https://javalionli.gitee.io/plus-doc/#/common/column)
+>[专栏与视频 入门必看](https://plus-doc.dromara.org/#/common/column)
+>>[https://plus-doc.dromara.org/#/common/column](https://plus-doc.dromara.org/#/common/column)
 >
->[部署项目 必看](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/deploy)
->>[https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/deploy](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/quickstart/deploy)
+>[部署项目 必看](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy)
+>>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy)
 > 
->[参考文档 Wiki](https://javalionli.gitee.io/plus-doc)
->>[https://javalionli.gitee.io/plus-doc](https://javalionli.gitee.io/plus-doc)
+>[参考文档 Wiki](https://plus-doc.dromara.org)
+>>[https://plus-doc.dromara.org](https://plus-doc.dromara.org)
 
 ## 软件架构图
 
@@ -119,7 +120,7 @@
 
 ## 如何参与贡献
 
-[参与贡献的方式 https://javalionli.gitee.io/plus-doc/#/common/contribution](https://javalionli.gitee.io/plus-doc/#/common/contribution)
+[参与贡献的方式 https://plus-doc.dromara.org/#/common/contribution](https://plus-doc.dromara.org/#/common/contribution)
 
 ### 其他
 
@@ -127,16 +128,16 @@
 * GitHub 地址 [RuoYi-Vue-Plus](https://github.com/dromara/RuoYi-Vue-Plus)
 * 微服务 分支 [RuoYi-Cloud-Plus](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus)
 * 前端项目 地址 [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
-* 用户扩展项目 [扩展项目列表](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/extend-project/list)
+* 用户扩展项目 [扩展项目列表](https://plus-doc.dromara.org/#/ruoyi-vue-plus/extend-project/list)
 
 ## 加群与捐献
->[加群与捐献](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/other/group_chat)
->>[https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/other/group_chat](https://javalionli.gitee.io/plus-doc/#/ruoyi-vue-plus/other/group_chat)
+>[加群与捐献](https://plus-doc.dromara.org/#/ruoyi-vue-plus/other/group_chat)
+>>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/other/group_chat](https://plus-doc.dromara.org/#/ruoyi-vue-plus/other/group_chat)
 
 ## 捐献作者
 作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭  
-<img src="https://images.gitee.com/uploads/images/2022/0218/213734_b1b8197f_1766278.jpeg" width="300px" height="450px" />
-<img src="https://images.gitee.com/uploads/images/2021/0525/101713_3d18b119_1766278.jpeg" width="300px" height="450px" />
+<img src="https://foruda.gitee.com/images/1678975784848381069/d8661ed9_1766278.png" width="300px" height="450px" />
+<img src="https://foruda.gitee.com/images/1678975801230205215/6f96229d_1766278.png" width="300px" height="450px" />
 
 ## 演示图例
 

+ 6 - 6
pom.xml

@@ -4,7 +4,7 @@
          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.ruoyi</groupId>
+    <groupId>org.dromara</groupId>
     <artifactId>ruoyi-vue-plus</artifactId>
     <version>${revision}</version>
 
@@ -113,7 +113,7 @@
 
             <!-- common 的依赖配置-->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-bom</artifactId>
                 <version>${revision}</version>
                 <type>pom</type>
@@ -312,25 +312,25 @@
             </dependency>
 
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-system</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-job</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-generator</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-demo</artifactId>
                 <version>${revision}</version>
             </dependency>

+ 6 - 6
ruoyi-admin/pom.xml

@@ -4,7 +4,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
+        <groupId>org.dromara</groupId>
         <version>${revision}</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
@@ -40,29 +40,29 @@
         </dependency>
 
         <dependency>
-            <groupId>com.ruoyi</groupId>
+            <groupId>org.dromara</groupId>
             <artifactId>ruoyi-common-doc</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>com.ruoyi</groupId>
+            <groupId>org.dromara</groupId>
             <artifactId>ruoyi-system</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>com.ruoyi</groupId>
+            <groupId>org.dromara</groupId>
             <artifactId>ruoyi-job</artifactId>
         </dependency>
 
         <!-- 代码生成-->
         <dependency>
-            <groupId>com.ruoyi</groupId>
+            <groupId>org.dromara</groupId>
             <artifactId>ruoyi-generator</artifactId>
         </dependency>
 
         <!--  demo模块  -->
         <dependency>
-            <groupId>com.ruoyi</groupId>
+            <groupId>org.dromara</groupId>
             <artifactId>ruoyi-demo</artifactId>
         </dependency>
 

+ 0 - 23
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java

@@ -1,23 +0,0 @@
-package com.ruoyi;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
-
-/**
- * 启动程序
- *
- * @author ruoyi
- */
-
-@SpringBootApplication
-public class RuoYiApplication {
-
-    public static void main(String[] args) {
-        SpringApplication application = new SpringApplication(RuoYiApplication.class);
-        application.setApplicationStartup(new BufferingApplicationStartup(2048));
-        application.run(args);
-        System.out.println("(♥◠‿◠)ノ゙  RuoYi-Vue-Plus启动成功   ლ(´ڡ`ლ)゙");
-    }
-
-}

+ 0 - 18
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java

@@ -1,18 +0,0 @@
-package com.ruoyi;
-
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
-
-/**
- * web容器中进行部署
- *
- * @author ruoyi
- */
-public class RuoYiServletInitializer extends SpringBootServletInitializer {
-
-    @Override
-    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
-        return application.sources(RuoYiApplication.class);
-    }
-
-}

+ 0 - 153
ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java

@@ -1,153 +0,0 @@
-package com.ruoyi.web.controller;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import cn.hutool.core.collection.CollUtil;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.domain.model.EmailLoginBody;
-import com.ruoyi.common.core.domain.model.LoginBody;
-import com.ruoyi.common.core.domain.model.RegisterBody;
-import com.ruoyi.common.core.domain.model.SmsLoginBody;
-import com.ruoyi.common.core.utils.MapstructUtils;
-import com.ruoyi.common.core.utils.StreamUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.tenant.helper.TenantHelper;
-import com.ruoyi.system.domain.bo.SysTenantBo;
-import com.ruoyi.system.domain.vo.SysTenantVo;
-import com.ruoyi.system.service.ISysConfigService;
-import com.ruoyi.system.service.ISysTenantService;
-import com.ruoyi.web.domain.vo.LoginTenantVo;
-import com.ruoyi.web.domain.vo.LoginVo;
-import com.ruoyi.web.domain.vo.TenantListVo;
-import com.ruoyi.web.service.SysLoginService;
-import com.ruoyi.web.service.SysRegisterService;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.validation.constraints.NotBlank;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.net.URL;
-import java.util.List;
-
-/**
- * 认证
- *
- * @author Lion Li
- */
-@SaIgnore
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/auth")
-public class AuthController {
-
-    private final SysLoginService loginService;
-    private final SysRegisterService registerService;
-    private final ISysConfigService configService;
-    private final ISysTenantService tenantService;
-
-    /**
-     * 登录方法
-     *
-     * @param body 登录信息
-     * @return 结果
-     */
-    @PostMapping("/login")
-    public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
-        LoginVo loginVo = new LoginVo();
-        // 生成令牌
-        String token = loginService.login(
-                body.getTenantId(),
-                body.getUsername(), body.getPassword(),
-                body.getCode(), body.getUuid());
-        loginVo.setToken(token);
-        return R.ok(loginVo);
-    }
-
-    /**
-     * 短信登录
-     *
-     * @param body 登录信息
-     * @return 结果
-     */
-    @PostMapping("/smsLogin")
-    public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody body) {
-        LoginVo loginVo = new LoginVo();
-        // 生成令牌
-        String token = loginService.smsLogin(body.getTenantId(), body.getPhonenumber(), body.getSmsCode());
-        loginVo.setToken(token);
-        return R.ok(loginVo);
-    }
-
-    /**
-     * 邮件登录
-     *
-     * @param body 登录信息
-     * @return 结果
-     */
-    @PostMapping("/emailLogin")
-    public R<LoginVo> emailLogin(@Validated @RequestBody EmailLoginBody body) {
-        LoginVo loginVo = new LoginVo();
-        // 生成令牌
-        String token = loginService.emailLogin(body.getTenantId(), body.getEmail(), body.getEmailCode());
-        loginVo.setToken(token);
-        return R.ok(loginVo);
-    }
-
-    /**
-     * 小程序登录(示例)
-     *
-     * @param xcxCode 小程序code
-     * @return 结果
-     */
-    @PostMapping("/xcxLogin")
-    public R<LoginVo> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
-        LoginVo loginVo = new LoginVo();
-        // 生成令牌
-        String token = loginService.xcxLogin(xcxCode);
-        loginVo.setToken(token);
-        return R.ok(loginVo);
-    }
-
-    /**
-     * 退出登录
-     */
-    @PostMapping("/logout")
-    public R<Void> logout() {
-        loginService.logout();
-        return R.ok("退出成功");
-    }
-
-    /**
-     * 用户注册
-     */
-    @PostMapping("/register")
-    public R<Void> register(@Validated @RequestBody RegisterBody user) {
-        if (!configService.selectRegisterEnabled(user.getTenantId())) {
-            return R.fail("当前系统没有开启注册功能!");
-        }
-        registerService.register(user);
-        return R.ok();
-    }
-
-    /**
-     * 登录页面租户下拉框
-     *
-     * @return 租户列表
-     */
-    @GetMapping("/tenant/list")
-    public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
-        List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
-        List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
-        // 获取域名
-        String host = new URL(request.getRequestURL().toString()).getHost();
-        // 根据域名进行筛选
-        List<TenantListVo> list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host));
-        // 返回对象
-        LoginTenantVo vo = new LoginTenantVo();
-        vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
-        vo.setTenantEnabled(TenantHelper.isEnable());
-        return R.ok(vo);
-    }
-
-}

+ 0 - 135
ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java

@@ -1,135 +0,0 @@
-package com.ruoyi.web.controller;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.RandomUtil;
-import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.utils.SpringUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.core.utils.reflect.ReflectUtils;
-import com.ruoyi.common.mail.config.properties.MailProperties;
-import com.ruoyi.common.mail.utils.MailUtils;
-import com.ruoyi.common.redis.utils.RedisUtils;
-import com.ruoyi.common.sms.config.properties.SmsProperties;
-import com.ruoyi.common.sms.core.SmsTemplate;
-import com.ruoyi.common.sms.entity.SmsResult;
-import com.ruoyi.common.web.config.properties.CaptchaProperties;
-import com.ruoyi.common.web.enums.CaptchaType;
-import com.ruoyi.web.domain.vo.CaptchaVo;
-import jakarta.validation.constraints.NotBlank;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.expression.Expression;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 验证码操作处理
- *
- * @author Lion Li
- */
-@SaIgnore
-@Slf4j
-@Validated
-@RequiredArgsConstructor
-@RestController
-public class CaptchaController {
-
-    private final CaptchaProperties captchaProperties;
-    private final SmsProperties smsProperties;
-    private final MailProperties mailProperties;
-
-    /**
-     * 短信验证码
-     *
-     * @param phonenumber 用户手机号
-     */
-    @GetMapping("/sms/code")
-    public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
-        if (!smsProperties.getEnabled()) {
-            return R.fail("当前系统没有开启短信功能!");
-        }
-        String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
-        String code = RandomUtil.randomNumbers(4);
-        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
-        // 验证码模板id 自行处理 (查数据库或写死均可)
-        String templateId = "";
-        Map<String, String> map = new HashMap<>(1);
-        map.put("code", code);
-        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
-        SmsResult result = smsTemplate.send(phonenumber, templateId, map);
-        if (!result.isSuccess()) {
-            log.error("验证码短信发送异常 => {}", result);
-            return R.fail(result.getMessage());
-        }
-        return R.ok();
-    }
-
-    /**
-     * 邮箱验证码
-     *
-     * @param email 邮箱
-     */
-    @GetMapping("/email/code")
-    public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
-        if (!mailProperties.getEnabled()) {
-            return R.fail("当前系统没有开启邮箱功能!");
-        }
-        String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
-        String code = RandomUtil.randomNumbers(4);
-        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
-        try {
-            MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
-        } catch (Exception e) {
-            log.error("验证码短信发送异常 => {}", e.getMessage());
-            return R.fail(e.getMessage());
-        }
-        return R.ok();
-    }
-
-    /**
-     * 生成验证码
-     */
-    @GetMapping("/code")
-    public R<CaptchaVo> getCode() {
-        CaptchaVo captchaVo = new CaptchaVo();
-        boolean captchaEnabled = captchaProperties.getEnable();
-        if (!captchaEnabled) {
-            captchaVo.setCaptchaEnabled(false);
-            return R.ok(captchaVo);
-        }
-        // 保存验证码信息
-        String uuid = IdUtil.simpleUUID();
-        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid;
-        // 生成验证码
-        CaptchaType captchaType = captchaProperties.getType();
-        boolean isMath = CaptchaType.MATH == captchaType;
-        Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
-        CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
-        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
-        captcha.setGenerator(codeGenerator);
-        captcha.createCode();
-        String code = captcha.getCode();
-        if (isMath) {
-            ExpressionParser parser = new SpelExpressionParser();
-            Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
-            code = exp.getValue(String.class);
-        }
-        RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
-        captchaVo.setUuid(uuid);
-        captchaVo.setImg(captcha.getImageBase64());
-        return R.ok(captchaVo);
-    }
-
-}

+ 0 - 32
ruoyi-admin/src/main/java/com/ruoyi/web/controller/IndexController.java

@@ -1,32 +0,0 @@
-package com.ruoyi.web.controller;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import com.ruoyi.common.core.config.RuoYiConfig;
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 首页
- *
- * @author Lion Li
- */
-@SaIgnore
-@RequiredArgsConstructor
-@RestController
-public class IndexController {
-
-    /**
-     * 系统基础配置
-     */
-    private final RuoYiConfig ruoyiConfig;
-
-    /**
-     * 访问首页,提示语
-     */
-    @GetMapping("/")
-    public String index() {
-        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
-    }
-}

+ 0 - 25
ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/CaptchaVo.java

@@ -1,25 +0,0 @@
-package com.ruoyi.web.domain.vo;
-
-import lombok.Data;
-
-/**
- * 验证码信息
- *
- * @author Michelle.Chung
- */
-@Data
-public class CaptchaVo {
-
-    /**
-     * 是否开启验证码
-     */
-    private Boolean captchaEnabled = true;
-
-    private String uuid;
-
-    /**
-     * 验证码图片
-     */
-    private String img;
-
-}

+ 0 - 25
ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java

@@ -1,25 +0,0 @@
-package com.ruoyi.web.domain.vo;
-
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * 登录租户对象
- *
- * @author Michelle.Chung
- */
-@Data
-public class LoginTenantVo {
-
-    /**
-     * 租户开关
-     */
-    private Boolean tenantEnabled;
-
-    /**
-     * 租户对象列表
-     */
-    private List<TenantListVo> voList;
-
-}

+ 0 - 15
ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginVo.java

@@ -1,15 +0,0 @@
-package com.ruoyi.web.domain.vo;
-
-import lombok.Data;
-
-/**
- * 登录验证信息
- *
- * @author Michelle.Chung
- */
-@Data
-public class LoginVo {
-
-    private String token;
-
-}

+ 0 - 22
ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/TenantListVo.java

@@ -1,22 +0,0 @@
-package com.ruoyi.web.domain.vo;
-
-import com.ruoyi.system.domain.vo.SysTenantVo;
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-
-/**
- * 租户列表
- *
- * @author Lion Li
- */
-@Data
-@AutoMapper(target = SysTenantVo.class)
-public class TenantListVo {
-
-    private String tenantId;
-
-    private String companyName;
-
-    private String domain;
-
-}

+ 0 - 390
ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java

@@ -1,390 +0,0 @@
-package com.ruoyi.web.service;
-
-import cn.dev33.satoken.exception.NotLoginException;
-import cn.dev33.satoken.secure.BCrypt;
-import cn.dev33.satoken.stp.StpUtil;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.constant.TenantConstants;
-import com.ruoyi.common.core.domain.dto.RoleDTO;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.domain.model.XcxLoginUser;
-import com.ruoyi.common.core.enums.DeviceType;
-import com.ruoyi.common.core.enums.LoginType;
-import com.ruoyi.common.core.enums.TenantStatus;
-import com.ruoyi.common.core.enums.UserStatus;
-import com.ruoyi.common.core.exception.user.CaptchaException;
-import com.ruoyi.common.core.exception.user.CaptchaExpireException;
-import com.ruoyi.common.core.exception.user.UserException;
-import com.ruoyi.common.core.utils.*;
-import com.ruoyi.common.log.event.LogininforEvent;
-import com.ruoyi.common.redis.utils.RedisUtils;
-import com.ruoyi.common.satoken.utils.LoginHelper;
-import com.ruoyi.common.tenant.exception.TenantException;
-import com.ruoyi.common.tenant.helper.TenantHelper;
-import com.ruoyi.common.web.config.properties.CaptchaProperties;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.system.domain.vo.SysTenantVo;
-import com.ruoyi.system.domain.vo.SysUserVo;
-import com.ruoyi.system.mapper.SysUserMapper;
-import com.ruoyi.system.service.ISysPermissionService;
-import com.ruoyi.system.service.ISysTenantService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-
-import java.time.Duration;
-import java.util.Date;
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * 登录校验方法
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Slf4j
-@Service
-public class SysLoginService {
-
-    private final SysUserMapper userMapper;
-    private final CaptchaProperties captchaProperties;
-    private final ISysPermissionService permissionService;
-    private final ISysTenantService tenantService;
-
-    @Value("${user.password.maxRetryCount}")
-    private Integer maxRetryCount;
-
-    @Value("${user.password.lockTime}")
-    private Integer lockTime;
-
-    /**
-     * 登录验证
-     *
-     * @param username 用户名
-     * @param password 密码
-     * @param code     验证码
-     * @param uuid     唯一标识
-     * @return 结果
-     */
-    public String login(String tenantId, String username, String password, String code, String uuid) {
-        boolean captchaEnabled = captchaProperties.getEnable();
-        // 验证码开关
-        if (captchaEnabled) {
-            validateCaptcha(tenantId, username, code, uuid);
-        }
-        // 校验租户
-        checkTenant(tenantId);
-
-        SysUserVo user = loadUserByUsername(tenantId, username);
-        checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
-        // 此处可根据登录用户的数据不同 自行创建 loginUser
-        LoginUser loginUser = buildLoginUser(user);
-        // 生成token
-        LoginHelper.loginByDevice(loginUser, DeviceType.PC);
-
-        recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId());
-        return StpUtil.getTokenValue();
-    }
-
-    public String smsLogin(String tenantId, String phonenumber, String smsCode) {
-        // 校验租户
-        checkTenant(tenantId);
-        // 通过手机号查找用户
-        SysUserVo user = loadUserByPhonenumber(tenantId, phonenumber);
-
-        checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
-        // 此处可根据登录用户的数据不同 自行创建 loginUser
-        LoginUser loginUser = buildLoginUser(user);
-        // 生成token
-        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
-
-        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId());
-        return StpUtil.getTokenValue();
-    }
-
-    public String emailLogin(String tenantId, String email, String emailCode) {
-        // 校验租户
-        checkTenant(tenantId);
-        // 通过手机号查找用户
-        SysUserVo user = loadUserByEmail(tenantId, email);
-
-        checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode));
-        // 此处可根据登录用户的数据不同 自行创建 loginUser
-        LoginUser loginUser = buildLoginUser(user);
-        // 生成token
-        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
-
-        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId());
-        return StpUtil.getTokenValue();
-    }
-
-
-    public String xcxLogin(String xcxCode) {
-        // xcxCode 为 小程序调用 wx.login 授权后获取
-        // todo 以下自行实现
-        // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
-        String openid = "";
-        SysUserVo user = loadUserByOpenid(openid);
-        // 校验租户
-        checkTenant(user.getTenantId());
-
-        // 此处可根据登录用户的数据不同 自行创建 loginUser
-        XcxLoginUser loginUser = new XcxLoginUser();
-        loginUser.setTenantId(user.getTenantId());
-        loginUser.setUserId(user.getUserId());
-        loginUser.setUsername(user.getUserName());
-        loginUser.setUserType(user.getUserType());
-        loginUser.setOpenid(openid);
-        // 生成token
-        LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
-
-        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId());
-        return StpUtil.getTokenValue();
-    }
-
-    /**
-     * 退出登录
-     */
-    public void logout() {
-        try {
-            LoginUser loginUser = LoginHelper.getLoginUser();
-            if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
-                // 超级管理员 登出清除动态租户
-                TenantHelper.clearDynamic();
-            }
-            StpUtil.logout();
-            recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
-        } catch (NotLoginException ignored) {
-        }
-    }
-
-    /**
-     * 记录登录信息
-     *
-     * @param tenantId 租户ID
-     * @param username 用户名
-     * @param status   状态
-     * @param message  消息内容
-     */
-    private void recordLogininfor(String tenantId, String username, String status, String message) {
-        LogininforEvent logininforEvent = new LogininforEvent();
-        logininforEvent.setTenantId(tenantId);
-        logininforEvent.setUsername(username);
-        logininforEvent.setStatus(status);
-        logininforEvent.setMessage(message);
-        logininforEvent.setRequest(ServletUtils.getRequest());
-        SpringUtils.context().publishEvent(logininforEvent);
-    }
-
-    /**
-     * 校验短信验证码
-     */
-    private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
-        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
-        if (StringUtils.isBlank(code)) {
-            recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        return code.equals(smsCode);
-    }
-
-    /**
-     * 校验邮箱验证码
-     */
-    private boolean validateEmailCode(String tenantId, String email, String emailCode) {
-        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email);
-        if (StringUtils.isBlank(code)) {
-            recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        return code.equals(emailCode);
-    }
-
-    /**
-     * 校验验证码
-     *
-     * @param username 用户名
-     * @param code     验证码
-     * @param uuid     唯一标识
-     */
-    public void validateCaptcha(String tenantId, String username, String code, String uuid) {
-        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
-        String captcha = RedisUtils.getCacheObject(verifyKey);
-        RedisUtils.deleteObject(verifyKey);
-        if (captcha == null) {
-            recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        if (!code.equalsIgnoreCase(captcha)) {
-            recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
-            throw new CaptchaException();
-        }
-    }
-
-    private SysUserVo loadUserByUsername(String tenantId, String username) {
-        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-                .select(SysUser::getUserName, SysUser::getStatus)
-                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
-                .eq(SysUser::getUserName, username));
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", username);
-            throw new UserException("user.not.exists", username);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", username);
-            throw new UserException("user.blocked", username);
-        }
-        if (TenantHelper.isEnable()) {
-            return userMapper.selectTenantUserByUserName(username, tenantId);
-        }
-        return userMapper.selectUserByUserName(username);
-    }
-
-    private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
-        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-                .select(SysUser::getPhonenumber, SysUser::getStatus)
-                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
-                .eq(SysUser::getPhonenumber, phonenumber));
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", phonenumber);
-            throw new UserException("user.not.exists", phonenumber);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", phonenumber);
-            throw new UserException("user.blocked", phonenumber);
-        }
-        if (TenantHelper.isEnable()) {
-            return userMapper.selectTenantUserByPhonenumber(phonenumber, tenantId);
-        }
-        return userMapper.selectUserByPhonenumber(phonenumber);
-    }
-
-    private SysUserVo loadUserByEmail(String tenantId, String email) {
-        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-            .select(SysUser::getPhonenumber, SysUser::getStatus)
-            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
-            .eq(SysUser::getEmail, email));
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", email);
-            throw new UserException("user.not.exists", email);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", email);
-            throw new UserException("user.blocked", email);
-        }
-        if (TenantHelper.isEnable()) {
-            return userMapper.selectTenantUserByEmail(email, tenantId);
-        }
-        return userMapper.selectUserByEmail(email);
-    }
-
-    private SysUserVo loadUserByOpenid(String openid) {
-        // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
-        // todo 自行实现 userService.selectUserByOpenid(openid);
-        SysUserVo user = new SysUserVo();
-        if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", openid);
-            // todo 用户不存在 业务逻辑自行实现
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", openid);
-            // todo 用户已被停用 业务逻辑自行实现
-        }
-        return user;
-    }
-
-    /**
-     * 构建登录用户
-     */
-    private LoginUser buildLoginUser(SysUserVo user) {
-        LoginUser loginUser = new LoginUser();
-        loginUser.setTenantId(user.getTenantId());
-        loginUser.setUserId(user.getUserId());
-        loginUser.setDeptId(user.getDeptId());
-        loginUser.setUsername(user.getUserName());
-        loginUser.setUserType(user.getUserType());
-        loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId()));
-        loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId()));
-        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
-        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
-        loginUser.setRoles(roles);
-        return loginUser;
-    }
-
-    /**
-     * 记录登录信息
-     *
-     * @param userId 用户ID
-     */
-    public void recordLoginInfo(Long userId) {
-        SysUser sysUser = new SysUser();
-        sysUser.setUserId(userId);
-        sysUser.setLoginIp(ServletUtils.getClientIP());
-        sysUser.setLoginDate(DateUtils.getNowDate());
-        sysUser.setUpdateBy(userId);
-        userMapper.updateById(sysUser);
-    }
-
-    /**
-     * 登录校验
-     */
-    private void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
-        String errorKey = GlobalConstants.PWD_ERR_CNT_KEY + username;
-        String loginFail = Constants.LOGIN_FAIL;
-
-        // 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
-        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
-        // 锁定时间内登录 则踢出
-        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
-            recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
-            throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
-        }
-
-        if (supplier.get()) {
-            // 是否第一次
-            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
-            // 达到规定错误次数 则锁定登录
-            if (errorNumber.equals(maxRetryCount)) {
-                RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
-                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
-                throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
-            } else {
-                // 未达到规定错误次数 则递增
-                RedisUtils.setCacheObject(errorKey, errorNumber);
-                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
-                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
-            }
-        }
-
-        // 登录成功 清空错误次数
-        RedisUtils.deleteObject(errorKey);
-    }
-
-    private void checkTenant(String tenantId) {
-        if (!TenantHelper.isEnable()) {
-            return;
-        }
-        if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
-            return;
-        }
-        SysTenantVo tenant = tenantService.queryByTenantId(tenantId);
-        if (ObjectUtil.isNull(tenant)) {
-            log.info("登录租户:{} 不存在.", tenantId);
-            throw new TenantException("tenant.not.exists");
-        } else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
-            log.info("登录租户:{} 已被停用.", tenantId);
-            throw new TenantException("tenant.blocked");
-        } else if (ObjectUtil.isNotNull(tenant.getExpireTime())
-                && new Date().after(tenant.getExpireTime())) {
-            log.info("登录租户:{} 已超过有效期.", tenantId);
-            throw new TenantException("tenant.expired");
-        }
-    }
-
-}

+ 0 - 106
ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java

@@ -1,106 +0,0 @@
-package com.ruoyi.web.service;
-
-import cn.dev33.satoken.secure.BCrypt;
-import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.domain.model.RegisterBody;
-import com.ruoyi.common.core.enums.UserType;
-import com.ruoyi.common.core.exception.user.CaptchaException;
-import com.ruoyi.common.core.exception.user.CaptchaExpireException;
-import com.ruoyi.common.core.exception.user.UserException;
-import com.ruoyi.common.core.utils.MessageUtils;
-import com.ruoyi.common.core.utils.ServletUtils;
-import com.ruoyi.common.core.utils.SpringUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.log.event.LogininforEvent;
-import com.ruoyi.common.redis.utils.RedisUtils;
-import com.ruoyi.common.web.config.properties.CaptchaProperties;
-import com.ruoyi.system.domain.bo.SysUserBo;
-import com.ruoyi.system.service.ISysUserService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-/**
- * 注册校验方法
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysRegisterService {
-
-    private final ISysUserService userService;
-    private final CaptchaProperties captchaProperties;
-
-    /**
-     * 注册
-     */
-    public void register(RegisterBody registerBody) {
-        String tenantId = registerBody.getTenantId();
-        String username = registerBody.getUsername();
-        String password = registerBody.getPassword();
-        // 校验用户类型是否存在
-        String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
-
-        boolean captchaEnabled = captchaProperties.getEnable();
-        // 验证码开关
-        if (captchaEnabled) {
-            validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
-        }
-        SysUserBo sysUser = new SysUserBo();
-        sysUser.setUserName(username);
-        sysUser.setNickName(username);
-        sysUser.setPassword(BCrypt.hashpw(password));
-        sysUser.setUserType(userType);
-
-        if (!userService.checkUserNameUnique(sysUser)) {
-            throw new UserException("user.register.save.error", username);
-        }
-        boolean regFlag = userService.registerUser(sysUser, tenantId);
-        if (!regFlag) {
-            throw new UserException("user.register.error");
-        }
-        recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
-    }
-
-    /**
-     * 校验验证码
-     *
-     * @param username 用户名
-     * @param code     验证码
-     * @param uuid     唯一标识
-     */
-    public void validateCaptcha(String tenantId, String username, String code, String uuid) {
-        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
-        String captcha = RedisUtils.getCacheObject(verifyKey);
-        RedisUtils.deleteObject(verifyKey);
-        if (captcha == null) {
-            recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        if (!code.equalsIgnoreCase(captcha)) {
-            recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
-            throw new CaptchaException();
-        }
-    }
-
-    /**
-     * 记录登录信息
-     *
-     * @param tenantId 租户ID
-     * @param username 用户名
-     * @param status   状态
-     * @param message  消息内容
-     * @return
-     */
-    private void recordLogininfor(String tenantId, String username, String status, String message) {
-        LogininforEvent logininforEvent = new LogininforEvent();
-        logininforEvent.setTenantId(tenantId);
-        logininforEvent.setUsername(username);
-        logininforEvent.setStatus(status);
-        logininforEvent.setMessage(message);
-        logininforEvent.setRequest(ServletUtils.getRequest());
-        SpringUtils.context().publishEvent(logininforEvent);
-    }
-
-}

+ 23 - 0
ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java

@@ -0,0 +1,23 @@
+package org.dromara;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
+
+/**
+ * 启动程序
+ *
+ * @author Lion Li
+ */
+
+@SpringBootApplication
+public class DromaraApplication {
+
+    public static void main(String[] args) {
+        SpringApplication application = new SpringApplication(DromaraApplication.class);
+        application.setApplicationStartup(new BufferingApplicationStartup(2048));
+        application.run(args);
+        System.out.println("(♥◠‿◠)ノ゙  RuoYi-Vue-Plus启动成功   ლ(´ڡ`ლ)゙");
+    }
+
+}

+ 18 - 0
ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java

@@ -0,0 +1,18 @@
+package org.dromara;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ *
+ * @author Lion Li
+ */
+public class DromaraServletInitializer extends SpringBootServletInitializer {
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        return application.sources(DromaraApplication.class);
+    }
+
+}

+ 153 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java

@@ -0,0 +1,153 @@
+package org.dromara.web.controller;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.core.collection.CollUtil;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.domain.model.EmailLoginBody;
+import org.dromara.common.core.domain.model.LoginBody;
+import org.dromara.common.core.domain.model.RegisterBody;
+import org.dromara.common.core.domain.model.SmsLoginBody;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.system.domain.bo.SysTenantBo;
+import org.dromara.system.domain.vo.SysTenantVo;
+import org.dromara.system.service.ISysConfigService;
+import org.dromara.system.service.ISysTenantService;
+import org.dromara.web.domain.vo.LoginTenantVo;
+import org.dromara.web.domain.vo.LoginVo;
+import org.dromara.web.domain.vo.TenantListVo;
+import org.dromara.web.service.SysLoginService;
+import org.dromara.web.service.SysRegisterService;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URL;
+import java.util.List;
+
+/**
+ * 认证
+ *
+ * @author Lion Li
+ */
+@SaIgnore
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/auth")
+public class AuthController {
+
+    private final SysLoginService loginService;
+    private final SysRegisterService registerService;
+    private final ISysConfigService configService;
+    private final ISysTenantService tenantService;
+
+    /**
+     * 登录方法
+     *
+     * @param body 登录信息
+     * @return 结果
+     */
+    @PostMapping("/login")
+    public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
+        LoginVo loginVo = new LoginVo();
+        // 生成令牌
+        String token = loginService.login(
+                body.getTenantId(),
+                body.getUsername(), body.getPassword(),
+                body.getCode(), body.getUuid());
+        loginVo.setToken(token);
+        return R.ok(loginVo);
+    }
+
+    /**
+     * 短信登录
+     *
+     * @param body 登录信息
+     * @return 结果
+     */
+    @PostMapping("/smsLogin")
+    public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody body) {
+        LoginVo loginVo = new LoginVo();
+        // 生成令牌
+        String token = loginService.smsLogin(body.getTenantId(), body.getPhonenumber(), body.getSmsCode());
+        loginVo.setToken(token);
+        return R.ok(loginVo);
+    }
+
+    /**
+     * 邮件登录
+     *
+     * @param body 登录信息
+     * @return 结果
+     */
+    @PostMapping("/emailLogin")
+    public R<LoginVo> emailLogin(@Validated @RequestBody EmailLoginBody body) {
+        LoginVo loginVo = new LoginVo();
+        // 生成令牌
+        String token = loginService.emailLogin(body.getTenantId(), body.getEmail(), body.getEmailCode());
+        loginVo.setToken(token);
+        return R.ok(loginVo);
+    }
+
+    /**
+     * 小程序登录(示例)
+     *
+     * @param xcxCode 小程序code
+     * @return 结果
+     */
+    @PostMapping("/xcxLogin")
+    public R<LoginVo> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
+        LoginVo loginVo = new LoginVo();
+        // 生成令牌
+        String token = loginService.xcxLogin(xcxCode);
+        loginVo.setToken(token);
+        return R.ok(loginVo);
+    }
+
+    /**
+     * 退出登录
+     */
+    @PostMapping("/logout")
+    public R<Void> logout() {
+        loginService.logout();
+        return R.ok("退出成功");
+    }
+
+    /**
+     * 用户注册
+     */
+    @PostMapping("/register")
+    public R<Void> register(@Validated @RequestBody RegisterBody user) {
+        if (!configService.selectRegisterEnabled(user.getTenantId())) {
+            return R.fail("当前系统没有开启注册功能!");
+        }
+        registerService.register(user);
+        return R.ok();
+    }
+
+    /**
+     * 登录页面租户下拉框
+     *
+     * @return 租户列表
+     */
+    @GetMapping("/tenant/list")
+    public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
+        List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
+        List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
+        // 获取域名
+        String host = new URL(request.getRequestURL().toString()).getHost();
+        // 根据域名进行筛选
+        List<TenantListVo> list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host));
+        // 返回对象
+        LoginTenantVo vo = new LoginTenantVo();
+        vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
+        vo.setTenantEnabled(TenantHelper.isEnable());
+        return R.ok(vo);
+    }
+
+}

+ 135 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java

@@ -0,0 +1,135 @@
+package org.dromara.web.controller;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.captcha.AbstractCaptcha;
+import cn.hutool.captcha.generator.CodeGenerator;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.RandomUtil;
+import org.dromara.common.core.constant.Constants;
+import org.dromara.common.core.constant.GlobalConstants;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.SpringUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.core.utils.reflect.ReflectUtils;
+import org.dromara.common.mail.config.properties.MailProperties;
+import org.dromara.common.mail.utils.MailUtils;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.common.sms.config.properties.SmsProperties;
+import org.dromara.common.sms.core.SmsTemplate;
+import org.dromara.common.sms.entity.SmsResult;
+import org.dromara.common.web.config.properties.CaptchaProperties;
+import org.dromara.common.web.enums.CaptchaType;
+import org.dromara.web.domain.vo.CaptchaVo;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 验证码操作处理
+ *
+ * @author Lion Li
+ */
+@SaIgnore
+@Slf4j
+@Validated
+@RequiredArgsConstructor
+@RestController
+public class CaptchaController {
+
+    private final CaptchaProperties captchaProperties;
+    private final SmsProperties smsProperties;
+    private final MailProperties mailProperties;
+
+    /**
+     * 短信验证码
+     *
+     * @param phonenumber 用户手机号
+     */
+    @GetMapping("/sms/code")
+    public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
+        if (!smsProperties.getEnabled()) {
+            return R.fail("当前系统没有开启短信功能!");
+        }
+        String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
+        String code = RandomUtil.randomNumbers(4);
+        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
+        // 验证码模板id 自行处理 (查数据库或写死均可)
+        String templateId = "";
+        Map<String, String> map = new HashMap<>(1);
+        map.put("code", code);
+        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
+        SmsResult result = smsTemplate.send(phonenumber, templateId, map);
+        if (!result.isSuccess()) {
+            log.error("验证码短信发送异常 => {}", result);
+            return R.fail(result.getMessage());
+        }
+        return R.ok();
+    }
+
+    /**
+     * 邮箱验证码
+     *
+     * @param email 邮箱
+     */
+    @GetMapping("/email/code")
+    public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
+        if (!mailProperties.getEnabled()) {
+            return R.fail("当前系统没有开启邮箱功能!");
+        }
+        String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
+        String code = RandomUtil.randomNumbers(4);
+        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
+        try {
+            MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
+        } catch (Exception e) {
+            log.error("验证码短信发送异常 => {}", e.getMessage());
+            return R.fail(e.getMessage());
+        }
+        return R.ok();
+    }
+
+    /**
+     * 生成验证码
+     */
+    @GetMapping("/code")
+    public R<CaptchaVo> getCode() {
+        CaptchaVo captchaVo = new CaptchaVo();
+        boolean captchaEnabled = captchaProperties.getEnable();
+        if (!captchaEnabled) {
+            captchaVo.setCaptchaEnabled(false);
+            return R.ok(captchaVo);
+        }
+        // 保存验证码信息
+        String uuid = IdUtil.simpleUUID();
+        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid;
+        // 生成验证码
+        CaptchaType captchaType = captchaProperties.getType();
+        boolean isMath = CaptchaType.MATH == captchaType;
+        Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
+        CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
+        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
+        captcha.setGenerator(codeGenerator);
+        captcha.createCode();
+        String code = captcha.getCode();
+        if (isMath) {
+            ExpressionParser parser = new SpelExpressionParser();
+            Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
+            code = exp.getValue(String.class);
+        }
+        RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
+        captchaVo.setUuid(uuid);
+        captchaVo.setImg(captcha.getImageBase64());
+        return R.ok(captchaVo);
+    }
+
+}

+ 32 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java

@@ -0,0 +1,32 @@
+package org.dromara.web.controller;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import org.dromara.common.core.config.RuoYiConfig;
+import org.dromara.common.core.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 首页
+ *
+ * @author Lion Li
+ */
+@SaIgnore
+@RequiredArgsConstructor
+@RestController
+public class IndexController {
+
+    /**
+     * 系统基础配置
+     */
+    private final RuoYiConfig ruoyiConfig;
+
+    /**
+     * 访问首页,提示语
+     */
+    @GetMapping("/")
+    public String index() {
+        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
+    }
+}

+ 25 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/CaptchaVo.java

@@ -0,0 +1,25 @@
+package org.dromara.web.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 验证码信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class CaptchaVo {
+
+    /**
+     * 是否开启验证码
+     */
+    private Boolean captchaEnabled = true;
+
+    private String uuid;
+
+    /**
+     * 验证码图片
+     */
+    private String img;
+
+}

+ 25 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/LoginTenantVo.java

@@ -0,0 +1,25 @@
+package org.dromara.web.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 登录租户对象
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class LoginTenantVo {
+
+    /**
+     * 租户开关
+     */
+    private Boolean tenantEnabled;
+
+    /**
+     * 租户对象列表
+     */
+    private List<TenantListVo> voList;
+
+}

+ 15 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/LoginVo.java

@@ -0,0 +1,15 @@
+package org.dromara.web.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 登录验证信息
+ *
+ * @author Michelle.Chung
+ */
+@Data
+public class LoginVo {
+
+    private String token;
+
+}

+ 22 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/TenantListVo.java

@@ -0,0 +1,22 @@
+package org.dromara.web.domain.vo;
+
+import org.dromara.system.domain.vo.SysTenantVo;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+/**
+ * 租户列表
+ *
+ * @author Lion Li
+ */
+@Data
+@AutoMapper(target = SysTenantVo.class)
+public class TenantListVo {
+
+    private String tenantId;
+
+    private String companyName;
+
+    private String domain;
+
+}

+ 391 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java

@@ -0,0 +1,391 @@
+package org.dromara.web.service;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.secure.BCrypt;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.dromara.common.core.constant.Constants;
+import org.dromara.common.core.constant.GlobalConstants;
+import org.dromara.common.core.constant.TenantConstants;
+import org.dromara.common.core.domain.dto.RoleDTO;
+import org.dromara.common.core.domain.model.LoginUser;
+import org.dromara.common.core.domain.model.XcxLoginUser;
+import org.dromara.common.core.enums.DeviceType;
+import org.dromara.common.core.enums.LoginType;
+import org.dromara.common.core.enums.TenantStatus;
+import org.dromara.common.core.enums.UserStatus;
+import org.dromara.common.core.exception.user.CaptchaException;
+import org.dromara.common.core.exception.user.CaptchaExpireException;
+import org.dromara.common.core.exception.user.UserException;
+import org.dromara.common.core.utils.*;
+import org.dromara.common.log.event.LogininforEvent;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.tenant.exception.TenantException;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.common.web.config.properties.CaptchaProperties;
+import org.dromara.system.domain.SysUser;
+import org.dromara.system.domain.vo.SysTenantVo;
+import org.dromara.system.domain.vo.SysUserVo;
+import org.dromara.system.mapper.SysUserMapper;
+import org.dromara.system.service.ISysPermissionService;
+import org.dromara.system.service.ISysTenantService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.Duration;
+import java.util.Date;
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * 登录校验方法
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Slf4j
+@Service
+public class SysLoginService {
+
+    private final SysUserMapper userMapper;
+    private final CaptchaProperties captchaProperties;
+    private final ISysPermissionService permissionService;
+    private final ISysTenantService tenantService;
+
+    @Value("${user.password.maxRetryCount}")
+    private Integer maxRetryCount;
+
+    @Value("${user.password.lockTime}")
+    private Integer lockTime;
+
+    /**
+     * 登录验证
+     *
+     * @param username 用户名
+     * @param password 密码
+     * @param code     验证码
+     * @param uuid     唯一标识
+     * @return 结果
+     */
+    public String login(String tenantId, String username, String password, String code, String uuid) {
+        boolean captchaEnabled = captchaProperties.getEnable();
+        // 验证码开关
+        if (captchaEnabled) {
+            validateCaptcha(tenantId, username, code, uuid);
+        }
+        // 校验租户
+        checkTenant(tenantId);
+
+        SysUserVo user = loadUserByUsername(tenantId, username);
+        checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
+        // 此处可根据登录用户的数据不同 自行创建 loginUser
+        LoginUser loginUser = buildLoginUser(user);
+        // 生成token
+        LoginHelper.loginByDevice(loginUser, DeviceType.PC);
+
+        recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId());
+        return StpUtil.getTokenValue();
+    }
+
+    public String smsLogin(String tenantId, String phonenumber, String smsCode) {
+        // 校验租户
+        checkTenant(tenantId);
+        // 通过手机号查找用户
+        SysUserVo user = loadUserByPhonenumber(tenantId, phonenumber);
+
+        checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
+        // 此处可根据登录用户的数据不同 自行创建 loginUser
+        LoginUser loginUser = buildLoginUser(user);
+        // 生成token
+        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
+
+        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId());
+        return StpUtil.getTokenValue();
+    }
+
+    public String emailLogin(String tenantId, String email, String emailCode) {
+        // 校验租户
+        checkTenant(tenantId);
+        // 通过手机号查找用户
+        SysUserVo user = loadUserByEmail(tenantId, email);
+
+        checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode));
+        // 此处可根据登录用户的数据不同 自行创建 loginUser
+        LoginUser loginUser = buildLoginUser(user);
+        // 生成token
+        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
+
+        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId());
+        return StpUtil.getTokenValue();
+    }
+
+
+    public String xcxLogin(String xcxCode) {
+        // xcxCode 为 小程序调用 wx.login 授权后获取
+        // todo 以下自行实现
+        // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
+        String openid = "";
+        SysUserVo user = loadUserByOpenid(openid);
+        // 校验租户
+        checkTenant(user.getTenantId());
+
+        // 此处可根据登录用户的数据不同 自行创建 loginUser
+        XcxLoginUser loginUser = new XcxLoginUser();
+        loginUser.setTenantId(user.getTenantId());
+        loginUser.setUserId(user.getUserId());
+        loginUser.setUsername(user.getUserName());
+        loginUser.setUserType(user.getUserType());
+        loginUser.setOpenid(openid);
+        // 生成token
+        LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
+
+        recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId());
+        return StpUtil.getTokenValue();
+    }
+
+    /**
+     * 退出登录
+     */
+    public void logout() {
+        try {
+            LoginUser loginUser = LoginHelper.getLoginUser();
+            if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
+                // 超级管理员 登出清除动态租户
+                TenantHelper.clearDynamic();
+            }
+            StpUtil.logout();
+            recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
+        } catch (NotLoginException ignored) {
+        }
+    }
+
+    /**
+     * 记录登录信息
+     *
+     * @param tenantId 租户ID
+     * @param username 用户名
+     * @param status   状态
+     * @param message  消息内容
+     */
+    private void recordLogininfor(String tenantId, String username, String status, String message) {
+        LogininforEvent logininforEvent = new LogininforEvent();
+        logininforEvent.setTenantId(tenantId);
+        logininforEvent.setUsername(username);
+        logininforEvent.setStatus(status);
+        logininforEvent.setMessage(message);
+        logininforEvent.setRequest(ServletUtils.getRequest());
+        SpringUtils.context().publishEvent(logininforEvent);
+    }
+
+    /**
+     * 校验短信验证码
+     */
+    private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
+        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
+        if (StringUtils.isBlank(code)) {
+            recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        return code.equals(smsCode);
+    }
+
+    /**
+     * 校验邮箱验证码
+     */
+    private boolean validateEmailCode(String tenantId, String email, String emailCode) {
+        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email);
+        if (StringUtils.isBlank(code)) {
+            recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        return code.equals(emailCode);
+    }
+
+    /**
+     * 校验验证码
+     *
+     * @param username 用户名
+     * @param code     验证码
+     * @param uuid     唯一标识
+     */
+    public void validateCaptcha(String tenantId, String username, String code, String uuid) {
+        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
+        String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
+        if (captcha == null) {
+            recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha)) {
+            recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
+            throw new CaptchaException();
+        }
+    }
+
+    private SysUserVo loadUserByUsername(String tenantId, String username) {
+        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                .select(SysUser::getUserName, SysUser::getStatus)
+                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
+                .eq(SysUser::getUserName, username));
+        if (ObjectUtil.isNull(user)) {
+            log.info("登录用户:{} 不存在.", username);
+            throw new UserException("user.not.exists", username);
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("登录用户:{} 已被停用.", username);
+            throw new UserException("user.blocked", username);
+        }
+        if (TenantHelper.isEnable()) {
+            return userMapper.selectTenantUserByUserName(username, tenantId);
+        }
+        return userMapper.selectUserByUserName(username);
+    }
+
+    private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
+        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                .select(SysUser::getPhonenumber, SysUser::getStatus)
+                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
+                .eq(SysUser::getPhonenumber, phonenumber));
+        if (ObjectUtil.isNull(user)) {
+            log.info("登录用户:{} 不存在.", phonenumber);
+            throw new UserException("user.not.exists", phonenumber);
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("登录用户:{} 已被停用.", phonenumber);
+            throw new UserException("user.blocked", phonenumber);
+        }
+        if (TenantHelper.isEnable()) {
+            return userMapper.selectTenantUserByPhonenumber(phonenumber, tenantId);
+        }
+        return userMapper.selectUserByPhonenumber(phonenumber);
+    }
+
+    private SysUserVo loadUserByEmail(String tenantId, String email) {
+        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+            .select(SysUser::getPhonenumber, SysUser::getStatus)
+            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
+            .eq(SysUser::getEmail, email));
+        if (ObjectUtil.isNull(user)) {
+            log.info("登录用户:{} 不存在.", email);
+            throw new UserException("user.not.exists", email);
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("登录用户:{} 已被停用.", email);
+            throw new UserException("user.blocked", email);
+        }
+        if (TenantHelper.isEnable()) {
+            return userMapper.selectTenantUserByEmail(email, tenantId);
+        }
+        return userMapper.selectUserByEmail(email);
+    }
+
+    private SysUserVo loadUserByOpenid(String openid) {
+        // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
+        // todo 自行实现 userService.selectUserByOpenid(openid);
+        SysUserVo user = new SysUserVo();
+        if (ObjectUtil.isNull(user)) {
+            log.info("登录用户:{} 不存在.", openid);
+            // todo 用户不存在 业务逻辑自行实现
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("登录用户:{} 已被停用.", openid);
+            // todo 用户已被停用 业务逻辑自行实现
+        }
+        return user;
+    }
+
+    /**
+     * 构建登录用户
+     */
+    private LoginUser buildLoginUser(SysUserVo user) {
+        LoginUser loginUser = new LoginUser();
+        loginUser.setTenantId(user.getTenantId());
+        loginUser.setUserId(user.getUserId());
+        loginUser.setDeptId(user.getDeptId());
+        loginUser.setUsername(user.getUserName());
+        loginUser.setUserType(user.getUserType());
+        loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId()));
+        loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId()));
+        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
+        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
+        loginUser.setRoles(roles);
+        return loginUser;
+    }
+
+    /**
+     * 记录登录信息
+     *
+     * @param userId 用户ID
+     */
+    public void recordLoginInfo(Long userId) {
+        SysUser sysUser = new SysUser();
+        sysUser.setUserId(userId);
+        sysUser.setLoginIp(ServletUtils.getClientIP());
+        sysUser.setLoginDate(DateUtils.getNowDate());
+        sysUser.setUpdateBy(userId);
+        userMapper.updateById(sysUser);
+    }
+
+    /**
+     * 登录校验
+     */
+    private void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
+        String errorKey = GlobalConstants.PWD_ERR_CNT_KEY + username;
+        String loginFail = Constants.LOGIN_FAIL;
+
+        // 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
+        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
+        // 锁定时间内登录 则踢出
+        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
+            recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
+            throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
+        }
+
+        if (supplier.get()) {
+            // 是否第一次
+            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
+            // 达到规定错误次数 则锁定登录
+            if (errorNumber.equals(maxRetryCount)) {
+                RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
+                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
+                throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
+            } else {
+                // 未达到规定错误次数 则递增
+                RedisUtils.setCacheObject(errorKey, errorNumber);
+                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
+                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
+            }
+        }
+
+        // 登录成功 清空错误次数
+        RedisUtils.deleteObject(errorKey);
+    }
+
+    private void checkTenant(String tenantId) {
+        if (!TenantHelper.isEnable()) {
+            return;
+        }
+        if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
+            return;
+        }
+        SysTenantVo tenant = tenantService.queryByTenantId(tenantId);
+        if (ObjectUtil.isNull(tenant)) {
+            log.info("登录租户:{} 不存在.", tenantId);
+            throw new TenantException("tenant.not.exists");
+        } else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
+            log.info("登录租户:{} 已被停用.", tenantId);
+            throw new TenantException("tenant.blocked");
+        } else if (ObjectUtil.isNotNull(tenant.getExpireTime())
+                && new Date().after(tenant.getExpireTime())) {
+            log.info("登录租户:{} 已超过有效期.", tenantId);
+            throw new TenantException("tenant.expired");
+        }
+    }
+
+}

+ 106 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java

@@ -0,0 +1,106 @@
+package org.dromara.web.service;
+
+import cn.dev33.satoken.secure.BCrypt;
+import org.dromara.common.core.constant.Constants;
+import org.dromara.common.core.constant.GlobalConstants;
+import org.dromara.common.core.domain.model.RegisterBody;
+import org.dromara.common.core.enums.UserType;
+import org.dromara.common.core.exception.user.CaptchaException;
+import org.dromara.common.core.exception.user.CaptchaExpireException;
+import org.dromara.common.core.exception.user.UserException;
+import org.dromara.common.core.utils.MessageUtils;
+import org.dromara.common.core.utils.ServletUtils;
+import org.dromara.common.core.utils.SpringUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.log.event.LogininforEvent;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.common.web.config.properties.CaptchaProperties;
+import org.dromara.system.domain.bo.SysUserBo;
+import org.dromara.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 注册校验方法
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysRegisterService {
+
+    private final ISysUserService userService;
+    private final CaptchaProperties captchaProperties;
+
+    /**
+     * 注册
+     */
+    public void register(RegisterBody registerBody) {
+        String tenantId = registerBody.getTenantId();
+        String username = registerBody.getUsername();
+        String password = registerBody.getPassword();
+        // 校验用户类型是否存在
+        String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
+
+        boolean captchaEnabled = captchaProperties.getEnable();
+        // 验证码开关
+        if (captchaEnabled) {
+            validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
+        }
+        SysUserBo sysUser = new SysUserBo();
+        sysUser.setUserName(username);
+        sysUser.setNickName(username);
+        sysUser.setPassword(BCrypt.hashpw(password));
+        sysUser.setUserType(userType);
+
+        if (!userService.checkUserNameUnique(sysUser)) {
+            throw new UserException("user.register.save.error", username);
+        }
+        boolean regFlag = userService.registerUser(sysUser, tenantId);
+        if (!regFlag) {
+            throw new UserException("user.register.error");
+        }
+        recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
+    }
+
+    /**
+     * 校验验证码
+     *
+     * @param username 用户名
+     * @param code     验证码
+     * @param uuid     唯一标识
+     */
+    public void validateCaptcha(String tenantId, String username, String code, String uuid) {
+        String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
+        String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
+        if (captcha == null) {
+            recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha)) {
+            recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
+            throw new CaptchaException();
+        }
+    }
+
+    /**
+     * 记录登录信息
+     *
+     * @param tenantId 租户ID
+     * @param username 用户名
+     * @param status   状态
+     * @param message  消息内容
+     * @return
+     */
+    private void recordLogininfor(String tenantId, String username, String status, String message) {
+        LogininforEvent logininforEvent = new LogininforEvent();
+        logininforEvent.setTenantId(tenantId);
+        logininforEvent.setUsername(username);
+        logininforEvent.setStatus(status);
+        logininforEvent.setMessage(message);
+        logininforEvent.setRequest(ServletUtils.getRequest());
+        SpringUtils.context().publishEvent(logininforEvent);
+    }
+
+}

+ 9 - 9
ruoyi-admin/src/main/resources/application.yml

@@ -5,7 +5,7 @@ ruoyi:
   # 版本
   version: ${revision}
   # 版权年份
-  copyrightYear: 2022
+  copyrightYear: 2023
   # 实例演示开关
   demoEnabled: true
   # 获取ip地址开关
@@ -48,7 +48,7 @@ server:
 # 日志配置
 logging:
   level:
-    com.ruoyi: @logging.level@
+    org.dromara: @logging.level@
     org.springframework: warn
   config: classpath:logback.xml
 
@@ -151,11 +151,11 @@ tenant:
 mybatis-plus:
   # 不支持多包, 如有需要可在注解配置 或 提升扫包等级
   # 例如 com.**.**.mapper
-  mapperPackage: com.ruoyi.**.mapper
+  mapperPackage: org.dromara.**.mapper
   # 对应的 XML 文件位置
   mapperLocations: classpath*:mapper/**/*Mapper.xml
   # 实体扫描,多个package用逗号或者分号分隔
-  typeAliasesPackage: com.ruoyi.**.domain
+  typeAliasesPackage: org.dromara.**.domain
   # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
   checkConfigLocation: false
   configuration:
@@ -212,7 +212,7 @@ swagger:
     # 描述
     description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
     # 版本
-    version: '版本号: ${ruoyi-vue-plus.version}'
+    version: '版本号: ${ruoyi.version}'
     # 作者信息
     contact:
       name: Lion Li
@@ -236,13 +236,13 @@ springdoc:
   #这里定义了两个分组,可定义多个,也可以不定义
   group-configs:
     - group: 1.演示模块
-      packages-to-scan: com.ruoyi.demo
+      packages-to-scan: org.dromara.demo
     - group: 2.通用模块
-      packages-to-scan: com.ruoyi.web
+      packages-to-scan: org.dromara.web
     - group: 3.系统模块
-      packages-to-scan: com.ruoyi.system
+      packages-to-scan: org.dromara.system
     - group: 4.代码生成模块
-      packages-to-scan: com.ruoyi.generator
+      packages-to-scan: org.dromara.generator
 
 # 防止XSS攻击
 xss:

+ 0 - 45
ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java

@@ -1,45 +0,0 @@
-package com.ruoyi.test;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-/**
- * 断言单元测试案例
- *
- * @author Lion Li
- */
-@DisplayName("断言单元测试案例")
-public class AssertUnitTest {
-
-    @DisplayName("测试 assertEquals 方法")
-    @Test
-    public void testAssertEquals() {
-        Assertions.assertEquals("666", new String("666"));
-        Assertions.assertNotEquals("666", new String("666"));
-    }
-
-    @DisplayName("测试 assertSame 方法")
-    @Test
-    public void testAssertSame() {
-        Object obj = new Object();
-        Object obj1 = obj;
-        Assertions.assertSame(obj, obj1);
-        Assertions.assertNotSame(obj, obj1);
-    }
-
-    @DisplayName("测试 assertTrue 方法")
-    @Test
-    public void testAssertTrue() {
-        Assertions.assertTrue(true);
-        Assertions.assertFalse(true);
-    }
-
-    @DisplayName("测试 assertNull 方法")
-    @Test
-    public void testAssertNull() {
-        Assertions.assertNull(null);
-        Assertions.assertNotNull(null);
-    }
-
-}

+ 0 - 70
ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java

@@ -1,70 +0,0 @@
-package com.ruoyi.test;
-
-import com.ruoyi.common.core.config.RuoYiConfig;
-import org.junit.jupiter.api.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 单元测试案例
- *
- * @author Lion Li
- */
-@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
-@DisplayName("单元测试案例")
-public class DemoUnitTest {
-
-    @Autowired
-    private RuoYiConfig ruoYiConfig;
-
-    @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
-    @Test
-    public void testTest() {
-        System.out.println(ruoYiConfig);
-    }
-
-    @Disabled
-    @DisplayName("测试 @Disabled 注解")
-    @Test
-    public void testDisabled() {
-        System.out.println(ruoYiConfig);
-    }
-
-    @Timeout(value = 2L, unit = TimeUnit.SECONDS)
-    @DisplayName("测试 @Timeout 注解")
-    @Test
-    public void testTimeout() throws InterruptedException {
-        Thread.sleep(3000);
-        System.out.println(ruoYiConfig);
-    }
-
-
-    @DisplayName("测试 @RepeatedTest 注解")
-    @RepeatedTest(3)
-    public void testRepeatedTest() {
-        System.out.println(666);
-    }
-
-    @BeforeAll
-    public static void testBeforeAll() {
-        System.out.println("@BeforeAll ==================");
-    }
-
-    @BeforeEach
-    public void testBeforeEach() {
-        System.out.println("@BeforeEach ==================");
-    }
-
-    @AfterEach
-    public void testAfterEach() {
-        System.out.println("@AfterEach ==================");
-    }
-
-    @AfterAll
-    public static void testAfterAll() {
-        System.out.println("@AfterAll ==================");
-    }
-
-}

+ 0 - 72
ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java

@@ -1,72 +0,0 @@
-package com.ruoyi.test;
-
-import com.ruoyi.common.core.enums.UserType;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.junit.jupiter.params.provider.NullSource;
-import org.junit.jupiter.params.provider.ValueSource;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-
-/**
- * 带参数单元测试案例
- *
- * @author Lion Li
- */
-@DisplayName("带参数单元测试案例")
-public class ParamUnitTest {
-
-    @DisplayName("测试 @ValueSource 注解")
-    @ParameterizedTest
-    @ValueSource(strings = {"t1", "t2", "t3"})
-    public void testValueSource(String str) {
-        System.out.println(str);
-    }
-
-    @DisplayName("测试 @NullSource 注解")
-    @ParameterizedTest
-    @NullSource
-    public void testNullSource(String str) {
-        System.out.println(str);
-    }
-
-    @DisplayName("测试 @EnumSource 注解")
-    @ParameterizedTest
-    @EnumSource(UserType.class)
-    public void testEnumSource(UserType type) {
-        System.out.println(type.getUserType());
-    }
-
-    @DisplayName("测试 @MethodSource 注解")
-    @ParameterizedTest
-    @MethodSource("getParam")
-    public void testMethodSource(String str) {
-        System.out.println(str);
-    }
-
-    public static Stream<String> getParam() {
-        List<String> list = new ArrayList<>();
-        list.add("t1");
-        list.add("t2");
-        list.add("t3");
-        return list.stream();
-    }
-
-    @BeforeEach
-    public void testBeforeEach() {
-        System.out.println("@BeforeEach ==================");
-    }
-
-    @AfterEach
-    public void testAfterEach() {
-        System.out.println("@AfterEach ==================");
-    }
-
-
-}

+ 0 - 54
ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java

@@ -1,54 +0,0 @@
-package com.ruoyi.test;
-
-import org.junit.jupiter.api.*;
-import org.springframework.boot.test.context.SpringBootTest;
-
-/**
- * 标签单元测试案例
- *
- * @author Lion Li
- */
-@SpringBootTest
-@DisplayName("标签单元测试案例")
-public class TagUnitTest {
-
-    @Tag("dev")
-    @DisplayName("测试 @Tag dev")
-    @Test
-    public void testTagDev() {
-        System.out.println("dev");
-    }
-
-    @Tag("prod")
-    @DisplayName("测试 @Tag prod")
-    @Test
-    public void testTagProd() {
-        System.out.println("prod");
-    }
-
-    @Tag("local")
-    @DisplayName("测试 @Tag local")
-    @Test
-    public void testTagLocal() {
-        System.out.println("local");
-    }
-
-    @Tag("exclude")
-    @DisplayName("测试 @Tag exclude")
-    @Test
-    public void testTagExclude() {
-        System.out.println("exclude");
-    }
-
-    @BeforeEach
-    public void testBeforeEach() {
-        System.out.println("@BeforeEach ==================");
-    }
-
-    @AfterEach
-    public void testAfterEach() {
-        System.out.println("@AfterEach ==================");
-    }
-
-
-}

+ 45 - 0
ruoyi-admin/src/test/java/org/dromara/test/AssertUnitTest.java

@@ -0,0 +1,45 @@
+package org.dromara.test;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * 断言单元测试案例
+ *
+ * @author Lion Li
+ */
+@DisplayName("断言单元测试案例")
+public class AssertUnitTest {
+
+    @DisplayName("测试 assertEquals 方法")
+    @Test
+    public void testAssertEquals() {
+        Assertions.assertEquals("666", new String("666"));
+        Assertions.assertNotEquals("666", new String("666"));
+    }
+
+    @DisplayName("测试 assertSame 方法")
+    @Test
+    public void testAssertSame() {
+        Object obj = new Object();
+        Object obj1 = obj;
+        Assertions.assertSame(obj, obj1);
+        Assertions.assertNotSame(obj, obj1);
+    }
+
+    @DisplayName("测试 assertTrue 方法")
+    @Test
+    public void testAssertTrue() {
+        Assertions.assertTrue(true);
+        Assertions.assertFalse(true);
+    }
+
+    @DisplayName("测试 assertNull 方法")
+    @Test
+    public void testAssertNull() {
+        Assertions.assertNull(null);
+        Assertions.assertNotNull(null);
+    }
+
+}

+ 70 - 0
ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java

@@ -0,0 +1,70 @@
+package org.dromara.test;
+
+import org.dromara.common.core.config.RuoYiConfig;
+import org.junit.jupiter.api.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 单元测试案例
+ *
+ * @author Lion Li
+ */
+@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
+@DisplayName("单元测试案例")
+public class DemoUnitTest {
+
+    @Autowired
+    private RuoYiConfig ruoYiConfig;
+
+    @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
+    @Test
+    public void testTest() {
+        System.out.println(ruoYiConfig);
+    }
+
+    @Disabled
+    @DisplayName("测试 @Disabled 注解")
+    @Test
+    public void testDisabled() {
+        System.out.println(ruoYiConfig);
+    }
+
+    @Timeout(value = 2L, unit = TimeUnit.SECONDS)
+    @DisplayName("测试 @Timeout 注解")
+    @Test
+    public void testTimeout() throws InterruptedException {
+        Thread.sleep(3000);
+        System.out.println(ruoYiConfig);
+    }
+
+
+    @DisplayName("测试 @RepeatedTest 注解")
+    @RepeatedTest(3)
+    public void testRepeatedTest() {
+        System.out.println(666);
+    }
+
+    @BeforeAll
+    public static void testBeforeAll() {
+        System.out.println("@BeforeAll ==================");
+    }
+
+    @BeforeEach
+    public void testBeforeEach() {
+        System.out.println("@BeforeEach ==================");
+    }
+
+    @AfterEach
+    public void testAfterEach() {
+        System.out.println("@AfterEach ==================");
+    }
+
+    @AfterAll
+    public static void testAfterAll() {
+        System.out.println("@AfterAll ==================");
+    }
+
+}

+ 72 - 0
ruoyi-admin/src/test/java/org/dromara/test/ParamUnitTest.java

@@ -0,0 +1,72 @@
+package org.dromara.test;
+
+import org.dromara.common.core.enums.UserType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+/**
+ * 带参数单元测试案例
+ *
+ * @author Lion Li
+ */
+@DisplayName("带参数单元测试案例")
+public class ParamUnitTest {
+
+    @DisplayName("测试 @ValueSource 注解")
+    @ParameterizedTest
+    @ValueSource(strings = {"t1", "t2", "t3"})
+    public void testValueSource(String str) {
+        System.out.println(str);
+    }
+
+    @DisplayName("测试 @NullSource 注解")
+    @ParameterizedTest
+    @NullSource
+    public void testNullSource(String str) {
+        System.out.println(str);
+    }
+
+    @DisplayName("测试 @EnumSource 注解")
+    @ParameterizedTest
+    @EnumSource(UserType.class)
+    public void testEnumSource(UserType type) {
+        System.out.println(type.getUserType());
+    }
+
+    @DisplayName("测试 @MethodSource 注解")
+    @ParameterizedTest
+    @MethodSource("getParam")
+    public void testMethodSource(String str) {
+        System.out.println(str);
+    }
+
+    public static Stream<String> getParam() {
+        List<String> list = new ArrayList<>();
+        list.add("t1");
+        list.add("t2");
+        list.add("t3");
+        return list.stream();
+    }
+
+    @BeforeEach
+    public void testBeforeEach() {
+        System.out.println("@BeforeEach ==================");
+    }
+
+    @AfterEach
+    public void testAfterEach() {
+        System.out.println("@AfterEach ==================");
+    }
+
+
+}

+ 54 - 0
ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java

@@ -0,0 +1,54 @@
+package org.dromara.test;
+
+import org.junit.jupiter.api.*;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * 标签单元测试案例
+ *
+ * @author Lion Li
+ */
+@SpringBootTest
+@DisplayName("标签单元测试案例")
+public class TagUnitTest {
+
+    @Tag("dev")
+    @DisplayName("测试 @Tag dev")
+    @Test
+    public void testTagDev() {
+        System.out.println("dev");
+    }
+
+    @Tag("prod")
+    @DisplayName("测试 @Tag prod")
+    @Test
+    public void testTagProd() {
+        System.out.println("prod");
+    }
+
+    @Tag("local")
+    @DisplayName("测试 @Tag local")
+    @Test
+    public void testTagLocal() {
+        System.out.println("local");
+    }
+
+    @Tag("exclude")
+    @DisplayName("测试 @Tag exclude")
+    @Test
+    public void testTagExclude() {
+        System.out.println("exclude");
+    }
+
+    @BeforeEach
+    public void testBeforeEach() {
+        System.out.println("@BeforeEach ==================");
+    }
+
+    @AfterEach
+    public void testAfterEach() {
+        System.out.println("@AfterEach ==================");
+    }
+
+
+}

+ 1 - 1
ruoyi-common/pom.xml

@@ -4,7 +4,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
+        <groupId>org.dromara</groupId>
         <version>${revision}</version>
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 22 - 22
ruoyi-common/ruoyi-common-bom/pom.xml

@@ -4,7 +4,7 @@
          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.ruoyi</groupId>
+    <groupId>org.dromara</groupId>
     <artifactId>ruoyi-common-bom</artifactId>
     <version>${revision}</version>
     <packaging>pom</packaging>
@@ -21,147 +21,147 @@
         <dependencies>
             <!-- 核心模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-core</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 接口模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-doc</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- excel -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-excel</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 幂等 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-idempotent</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 调度模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-job</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 日志记录 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-log</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 邮件服务 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-mail</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 数据库服务 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-mybatis</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- OSS -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-oss</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 限流 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-ratelimiter</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 缓存服务 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-redis</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- satoken -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-satoken</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 安全模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-security</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 短信模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-sms</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- web服务 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-web</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 翻译模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-translation</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 脱敏模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-sensitive</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 序列化模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-json</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 数据库加解密模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-encrypt</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- 租户模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-tenant</artifactId>
                 <version>${revision}</version>
             </dependency>
 
             <!-- WebSocket模块 -->
             <dependency>
-                <groupId>com.ruoyi</groupId>
+                <groupId>org.dromara</groupId>
                 <artifactId>ruoyi-common-websocket</artifactId>
                 <version>${revision}</version>
             </dependency>

+ 1 - 1
ruoyi-common/ruoyi-common-core/pom.xml

@@ -3,7 +3,7 @@
          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>
-        <groupId>com.ruoyi</groupId>
+        <groupId>org.dromara</groupId>
         <artifactId>ruoyi-common</artifactId>
         <version>${revision}</version>
         <relativePath>../pom.xml</relativePath>

+ 0 - 16
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java

@@ -1,16 +0,0 @@
-package com.ruoyi.common.core.config;
-
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.EnableAspectJAutoProxy;
-
-/**
- * 程序注解配置
- *
- * @author Lion Li
- */
-@AutoConfiguration
-// 表示通过aop框架暴露该代理对象,AopContext能够访问
-@EnableAspectJAutoProxy(exposeProxy = true)
-public class ApplicationConfig {
-
-}

+ 0 - 54
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java

@@ -1,54 +0,0 @@
-package com.ruoyi.common.core.config;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.ruoyi.common.core.exception.ServiceException;
-import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-import org.springframework.scheduling.annotation.EnableAsync;
-
-import java.util.Arrays;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * 异步配置
- *
- * @author Lion Li
- */
-@EnableAsync(proxyTargetClass = true)
-@AutoConfiguration
-public class AsyncConfig implements AsyncConfigurer {
-
-    @Autowired
-    @Qualifier("scheduledExecutorService")
-    private ScheduledExecutorService scheduledExecutorService;
-
-    /**
-     * 自定义 @Async 注解使用系统线程池
-     */
-    @Override
-    public Executor getAsyncExecutor() {
-        return scheduledExecutorService;
-    }
-
-    /**
-     * 异步执行异常处理
-     */
-    @Override
-    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
-        return (throwable, method, objects) -> {
-            throwable.printStackTrace();
-            StringBuilder sb = new StringBuilder();
-            sb.append("Exception message - ").append(throwable.getMessage())
-                .append(", Method name - ").append(method.getName());
-            if (ArrayUtil.isNotEmpty(objects)) {
-                sb.append(", Parameter value - ").append(Arrays.toString(objects));
-            }
-            throw new ServiceException(sb.toString());
-        };
-    }
-
-}

+ 0 - 49
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java

@@ -1,49 +0,0 @@
-package com.ruoyi.common.core.config;
-
-import lombok.Data;
-import lombok.Getter;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 读取项目相关配置
- *
- * @author Lion Li
- */
-
-@Data
-@Component
-@ConfigurationProperties(prefix = "ruoyi")
-public class RuoYiConfig {
-
-    /**
-     * 项目名称
-     */
-    private String name;
-
-    /**
-     * 版本
-     */
-    private String version;
-
-    /**
-     * 版权年份
-     */
-    private String copyrightYear;
-
-    /**
-     * 实例演示开关
-     */
-    private boolean demoEnabled;
-
-    /**
-     * 获取地址开关
-     */
-    @Getter
-    private static boolean addressEnabled;
-
-    public void setAddressEnabled(boolean addressEnabled) {
-        RuoYiConfig.addressEnabled = addressEnabled;
-    }
-
-}

+ 0 - 57
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java

@@ -1,57 +0,0 @@
-package com.ruoyi.common.core.config;
-
-import com.ruoyi.common.core.config.properties.ThreadPoolProperties;
-import com.ruoyi.common.core.utils.Threads;
-import org.apache.commons.lang3.concurrent.BasicThreadFactory;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor;
-
-/**
- * 线程池配置
- *
- * @author Lion Li
- **/
-@AutoConfiguration
-@EnableConfigurationProperties(ThreadPoolProperties.class)
-public class ThreadPoolConfig {
-
-    /**
-     * 核心线程数 = cpu 核心数 + 1
-     */
-    private final int core = Runtime.getRuntime().availableProcessors() + 1;
-
-    @Bean(name = "threadPoolTaskExecutor")
-    @ConditionalOnProperty(prefix = "thread-pool", name = "enabled", havingValue = "true")
-    public ThreadPoolTaskExecutor threadPoolTaskExecutor(ThreadPoolProperties threadPoolProperties) {
-        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
-        executor.setCorePoolSize(core);
-        executor.setMaxPoolSize(core * 2);
-        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
-        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
-        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
-        return executor;
-    }
-
-    /**
-     * 执行周期性或定时任务
-     */
-    @Bean(name = "scheduledExecutorService")
-    protected ScheduledExecutorService scheduledExecutorService() {
-        return new ScheduledThreadPoolExecutor(core,
-            new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
-            new ThreadPoolExecutor.CallerRunsPolicy()) {
-            @Override
-            protected void afterExecute(Runnable r, Throwable t) {
-                super.afterExecute(r, t);
-                Threads.printException(r, t);
-            }
-        };
-    }
-}

+ 0 - 39
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java

@@ -1,39 +0,0 @@
-package com.ruoyi.common.core.config;
-
-import jakarta.validation.Validator;
-import org.hibernate.validator.HibernateValidator;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
-
-import java.util.Properties;
-
-/**
- * 校验框架配置类
- *
- * @author Lion Li
- */
-@AutoConfiguration
-public class ValidatorConfig {
-
-    /**
-     * 配置校验框架 快速返回模式
-     */
-    @Bean
-    public Validator validator(MessageSource messageSource) {
-        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
-        // 国际化
-        factoryBean.setValidationMessageSource(messageSource);
-        // 设置使用 HibernateValidator 校验器
-        factoryBean.setProviderClass(HibernateValidator.class);
-        Properties properties = new Properties();
-        // 设置 快速异常返回
-        properties.setProperty("hibernate.validator.fail_fast", "true");
-        factoryBean.setValidationProperties(properties);
-        // 加载配置
-        factoryBean.afterPropertiesSet();
-        return factoryBean.getValidator();
-    }
-
-}

+ 0 - 30
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java

@@ -1,30 +0,0 @@
-package com.ruoyi.common.core.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * 线程池 配置属性
- *
- * @author Lion Li
- */
-@Data
-@ConfigurationProperties(prefix = "thread-pool")
-public class ThreadPoolProperties {
-
-    /**
-     * 是否开启线程池
-     */
-    private boolean enabled;
-
-    /**
-     * 队列最大长度
-     */
-    private int queueCapacity;
-
-    /**
-     * 线程池维护线程所允许的空闲时间
-     */
-    private int keepAliveSeconds;
-
-}

+ 0 - 25
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java

@@ -1,25 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 缓存的key 常量
- *
- * @author Lion Li
- */
-public interface CacheConstants {
-
-    /**
-     * 在线用户 redis key
-     */
-    String ONLINE_TOKEN_KEY = "online_tokens:";
-
-    /**
-     * 参数管理 cache key
-     */
-    String SYS_CONFIG_KEY = "sys_config:";
-
-    /**
-     * 字典管理 cache key
-     */
-    String SYS_DICT_KEY = "sys_dict:";
-
-}

+ 0 - 63
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java

@@ -1,63 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 缓存组名称常量
- * <p>
- * key 格式为 cacheNames#ttl#maxIdleTime#maxSize
- * <p>
- * ttl 过期时间 如果设置为0则不过期 默认为0
- * maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0
- * maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0
- * <p>
- * 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500
- *
- * @author Lion Li
- */
-public interface CacheNames {
-
-    /**
-     * 演示案例
-     */
-    String DEMO_CACHE = "demo:cache#60s#10m#20";
-
-    /**
-     * 系统配置
-     */
-    String SYS_CONFIG = "sys_config";
-
-    /**
-     * 数据字典
-     */
-    String SYS_DICT = "sys_dict";
-
-    /**
-     * 租户
-     */
-    String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
-
-    /**
-     * 用户账户
-     */
-    String SYS_USER_NAME = "sys_user_name#30d";
-
-    /**
-     * 部门
-     */
-    String SYS_DEPT = "sys_dept#30d";
-
-    /**
-     * OSS内容
-     */
-    String SYS_OSS = "sys_oss#30d";
-
-    /**
-     * OSS配置
-     */
-    String SYS_OSS_CONFIG = "sys_oss_config";
-
-    /**
-     * 在线用户
-     */
-    String ONLINE_TOKEN = "online_tokens";
-
-}

+ 0 - 81
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java

@@ -1,81 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 通用常量信息
- *
- * @author ruoyi
- */
-public interface Constants {
-
-    /**
-     * UTF-8 字符集
-     */
-    String UTF8 = "UTF-8";
-
-    /**
-     * GBK 字符集
-     */
-    String GBK = "GBK";
-
-    /**
-     * www主域
-     */
-    String WWW = "www.";
-
-    /**
-     * http请求
-     */
-    String HTTP = "http://";
-
-    /**
-     * https请求
-     */
-    String HTTPS = "https://";
-
-    /**
-     * 通用成功标识
-     */
-    String SUCCESS = "0";
-
-    /**
-     * 通用失败标识
-     */
-    String FAIL = "1";
-
-    /**
-     * 登录成功
-     */
-    String LOGIN_SUCCESS = "Success";
-
-    /**
-     * 注销
-     */
-    String LOGOUT = "Logout";
-
-    /**
-     * 注册
-     */
-    String REGISTER = "Register";
-
-    /**
-     * 登录失败
-     */
-    String LOGIN_FAIL = "Error";
-
-    /**
-     * 验证码有效期(分钟)
-     */
-    Integer CAPTCHA_EXPIRATION = 2;
-
-    /**
-     * 令牌
-     */
-    String TOKEN = "token";
-
-    /**
-     * 顶级部门id
-     */
-    Long TOP_PARENT_ID = 0L;
-
-}
-

+ 0 - 39
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GlobalConstants.java

@@ -1,39 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 全局的key常量 (业务无关的key)
- *
- * @author Lion Li
- */
-public interface GlobalConstants {
-
-    /**
-     * 全局 redis key (业务无关的key)
-     */
-    String GLOBAL_REDIS_KEY = "global:";
-
-    /**
-     * 登录用户 redis key
-     */
-    String LOGIN_TOKEN_KEY = GLOBAL_REDIS_KEY + "Authorization:login:token:";
-
-    /**
-     * 验证码 redis key
-     */
-    String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
-
-    /**
-     * 防重提交 redis key
-     */
-    String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:";
-
-    /**
-     * 限流 redis key
-     */
-    String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:";
-
-    /**
-     * 登录账户密码错误次数 redis key
-     */
-    String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:";
-}

+ 0 - 93
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java

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

+ 0 - 45
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TenantConstants.java

@@ -1,45 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 租户常量信息
- *
- * @author Lion Li
- */
-public interface TenantConstants {
-
-    /**
-     * 租户正常状态
-     */
-    String NORMAL = "0";
-
-    /**
-     * 租户封禁状态
-     */
-    String DISABLE = "1";
-
-    /**
-     * 超级管理员ID
-     */
-    Long SUPER_ADMIN_ID = 1L;
-
-    /**
-     * 超级管理员角色 roleKey
-     */
-    String SUPER_ADMIN_ROLE_KEY = "superadmin";
-
-    /**
-     * 租户管理员角色 roleKey
-     */
-    String TENANT_ADMIN_ROLE_KEY = "admin";
-
-    /**
-     * 租户管理员角色名称
-     */
-    String TENANT_ADMIN_ROLE_NAME = "管理员";
-
-    /**
-     * 默认租户ID
-     */
-    String DEFAULT_TENANT_ID = "000000";
-
-}

+ 0 - 132
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java

@@ -1,132 +0,0 @@
-package com.ruoyi.common.core.constant;
-
-/**
- * 用户常量信息
- *
- * @author ruoyi
- */
-public interface UserConstants {
-
-    /**
-     * 平台内系统用户的唯一标志
-     */
-    String SYS_USER = "SYS_USER";
-
-    /**
-     * 正常状态
-     */
-    String NORMAL = "0";
-
-    /**
-     * 异常状态
-     */
-    String EXCEPTION = "1";
-
-    /**
-     * 用户正常状态
-     */
-    String USER_NORMAL = "0";
-
-    /**
-     * 用户封禁状态
-     */
-    String USER_DISABLE = "1";
-
-    /**
-     * 角色正常状态
-     */
-    String ROLE_NORMAL = "0";
-
-    /**
-     * 角色封禁状态
-     */
-    String ROLE_DISABLE = "1";
-
-    /**
-     * 部门正常状态
-     */
-    String DEPT_NORMAL = "0";
-
-    /**
-     * 部门停用状态
-     */
-    String DEPT_DISABLE = "1";
-
-    /**
-     * 字典正常状态
-     */
-    String DICT_NORMAL = "0";
-
-    /**
-     * 是否为系统默认(是)
-     */
-    String YES = "Y";
-
-    /**
-     * 是否菜单外链(是)
-     */
-    String YES_FRAME = "0";
-
-    /**
-     * 是否菜单外链(否)
-     */
-    String NO_FRAME = "1";
-
-    /**
-     * 菜单正常状态
-     */
-    String MENU_NORMAL = "0";
-
-    /**
-     * 菜单停用状态
-     */
-    String MENU_DISABLE = "1";
-
-    /**
-     * 菜单类型(目录)
-     */
-    String TYPE_DIR = "M";
-
-    /**
-     * 菜单类型(菜单)
-     */
-    String TYPE_MENU = "C";
-
-    /**
-     * 菜单类型(按钮)
-     */
-    String TYPE_BUTTON = "F";
-
-    /**
-     * Layout组件标识
-     */
-    String LAYOUT = "Layout";
-
-    /**
-     * ParentView组件标识
-     */
-    String PARENT_VIEW = "ParentView";
-
-    /**
-     * InnerLink组件标识
-     */
-    String INNER_LINK = "InnerLink";
-
-    /**
-     * 用户名长度限制
-     */
-    int USERNAME_MIN_LENGTH = 2;
-    int USERNAME_MAX_LENGTH = 20;
-
-    /**
-     * 密码长度限制
-     */
-    int PASSWORD_MIN_LENGTH = 5;
-    int PASSWORD_MAX_LENGTH = 20;
-
-    /**
-     * 超级管理员ID
-     */
-    Long SUPER_ADMIN_ID = 1L;
-
-}

+ 0 - 110
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java

@@ -1,110 +0,0 @@
-package com.ruoyi.common.core.domain;
-
-import com.ruoyi.common.core.constant.HttpStatus;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-
-/**
- * 响应信息主体
- *
- * @author Lion Li
- */
-@Data
-@NoArgsConstructor
-public class R<T> implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 成功
-     */
-    public static final int SUCCESS = 200;
-
-    /**
-     * 失败
-     */
-    public static final int FAIL = 500;
-
-    private int code;
-
-    private String msg;
-
-    private T data;
-
-    public static <T> R<T> ok() {
-        return restResult(null, SUCCESS, "操作成功");
-    }
-
-    public static <T> R<T> ok(T data) {
-        return restResult(data, SUCCESS, "操作成功");
-    }
-
-    public static <T> R<T> ok(String msg) {
-        return restResult(null, SUCCESS, msg);
-    }
-
-    public static <T> R<T> ok(String msg, T data) {
-        return restResult(data, SUCCESS, msg);
-    }
-
-    public static <T> R<T> fail() {
-        return restResult(null, FAIL, "操作失败");
-    }
-
-    public static <T> R<T> fail(String msg) {
-        return restResult(null, FAIL, msg);
-    }
-
-    public static <T> R<T> fail(T data) {
-        return restResult(data, FAIL, "操作失败");
-    }
-
-    public static <T> R<T> fail(String msg, T data) {
-        return restResult(data, FAIL, msg);
-    }
-
-    public static <T> R<T> fail(int code, String msg) {
-        return restResult(null, code, msg);
-    }
-
-    /**
-     * 返回警告消息
-     *
-     * @param msg 返回内容
-     * @return 警告消息
-     */
-    public static <T> R<T> warn(String msg) {
-        return restResult(null, HttpStatus.WARN, msg);
-    }
-
-    /**
-     * 返回警告消息
-     *
-     * @param msg 返回内容
-     * @param data 数据对象
-     * @return 警告消息
-     */
-    public static <T> R<T> warn(String msg, T data) {
-        return restResult(data, HttpStatus.WARN, msg);
-    }
-
-    private static <T> R<T> restResult(T data, int code, String msg) {
-        R<T> r = new R<>();
-        r.setCode(code);
-        r.setData(data);
-        r.setMsg(msg);
-        return r;
-    }
-
-    public static <T> Boolean isError(R<T> ret) {
-        return !isSuccess(ret);
-    }
-
-    public static <T> Boolean isSuccess(R<T> ret) {
-        return R.SUCCESS == ret.getCode();
-    }
-}

+ 0 - 38
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java

@@ -1,38 +0,0 @@
-package com.ruoyi.common.core.domain.dto;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * 角色
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-public class RoleDTO implements Serializable {
-
-    /**
-     * 角色ID
-     */
-    private Long roleId;
-
-    /**
-     * 角色名称
-     */
-    private String roleName;
-
-    /**
-     * 角色权限
-     */
-    private String roleKey;
-
-    /**
-     * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
-     */
-    private String dataScope;
-
-}

+ 0 - 62
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java

@@ -1,62 +0,0 @@
-package com.ruoyi.common.core.domain.dto;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-
-/**
- * 当前在线会话
- *
- * @author ruoyi
- */
-
-@Data
-@NoArgsConstructor
-public class UserOnlineDTO implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 会话编号
-     */
-    private String tokenId;
-
-    /**
-     * 部门名称
-     */
-    private String deptName;
-
-    /**
-     * 用户名称
-     */
-    private String userName;
-
-    /**
-     * 登录IP地址
-     */
-    private String ipaddr;
-
-    /**
-     * 登录地址
-     */
-    private String loginLocation;
-
-    /**
-     * 浏览器类型
-     */
-    private String browser;
-
-    /**
-     * 操作系统
-     */
-    private String os;
-
-    /**
-     * 登录时间
-     */
-    private Long loginTime;
-
-}

+ 0 - 35
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/EmailLoginBody.java

@@ -1,35 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import lombok.Data;
-
-/**
- * 短信登录对象
- *
- * @author Lion Li
- */
-
-@Data
-public class EmailLoginBody {
-
-    /**
-     * 租户ID
-     */
-    @NotBlank(message = "{tenant.number.not.blank}")
-    private String tenantId;
-
-    /**
-     * 邮箱
-     */
-    @NotBlank(message = "{user.email.not.blank}")
-    @Email(message = "{user.email.not.valid}")
-    private String email;
-
-    /**
-     * 邮箱code
-     */
-    @NotBlank(message = "{email.code.not.blank}")
-    private String emailCode;
-
-}

+ 0 - 48
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java

@@ -1,48 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import com.ruoyi.common.core.constant.UserConstants;
-import lombok.Data;
-import org.hibernate.validator.constraints.Length;
-
-import jakarta.validation.constraints.NotBlank;
-
-/**
- * 用户登录对象
- *
- * @author Lion Li
- */
-
-@Data
-public class LoginBody {
-
-    /**
-     * 租户ID
-     */
-    @NotBlank(message = "{tenant.number.not.blank}")
-    private String tenantId;
-
-    /**
-     * 用户名
-     */
-    @NotBlank(message = "{user.username.not.blank}")
-    @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
-    private String username;
-
-    /**
-     * 用户密码
-     */
-    @NotBlank(message = "{user.password.not.blank}")
-    @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
-    private String password;
-
-    /**
-     * 验证码
-     */
-    private String code;
-
-    /**
-     * 唯一标识
-     */
-    private String uuid;
-
-}

+ 0 - 123
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java

@@ -1,123 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import com.ruoyi.common.core.domain.dto.RoleDTO;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.List;
-import java.util.Set;
-
-/**
- * 登录用户身份权限
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-public class LoginUser implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 租户ID
-     */
-    private String tenantId;
-
-    /**
-     * 用户ID
-     */
-    private Long userId;
-
-    /**
-     * 部门ID
-     */
-    private Long deptId;
-
-    /**
-     * 部门名
-     */
-    private String deptName;
-
-    /**
-     * 用户唯一标识
-     */
-    private String token;
-
-    /**
-     * 用户类型
-     */
-    private String userType;
-
-    /**
-     * 登录时间
-     */
-    private Long loginTime;
-
-    /**
-     * 过期时间
-     */
-    private Long expireTime;
-
-    /**
-     * 登录IP地址
-     */
-    private String ipaddr;
-
-    /**
-     * 登录地点
-     */
-    private String loginLocation;
-
-    /**
-     * 浏览器类型
-     */
-    private String browser;
-
-    /**
-     * 操作系统
-     */
-    private String os;
-
-    /**
-     * 菜单权限
-     */
-    private Set<String> menuPermission;
-
-    /**
-     * 角色权限
-     */
-    private Set<String> rolePermission;
-
-    /**
-     * 用户名
-     */
-    private String username;
-
-    /**
-     * 角色对象
-     */
-    private List<RoleDTO> roles;
-
-    /**
-     * 数据权限 当前角色ID
-     */
-    private Long roleId;
-
-    /**
-     * 获取登录id
-     */
-    public String getLoginId() {
-        if (userType == null) {
-            throw new IllegalArgumentException("用户类型不能为空");
-        }
-        if (userId == null) {
-            throw new IllegalArgumentException("用户ID不能为空");
-        }
-        return userType + ":" + userId;
-    }
-
-}

+ 0 - 17
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java

@@ -1,17 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 用户注册对象
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class RegisterBody extends LoginBody {
-
-    private String userType;
-
-}

+ 0 - 34
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java

@@ -1,34 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import lombok.Data;
-
-import jakarta.validation.constraints.NotBlank;
-
-/**
- * 短信登录对象
- *
- * @author Lion Li
- */
-
-@Data
-public class SmsLoginBody {
-
-    /**
-     * 租户ID
-     */
-    @NotBlank(message = "{tenant.number.not.blank}")
-    private String tenantId;
-
-    /**
-     * 手机号
-     */
-    @NotBlank(message = "{user.phonenumber.not.blank}")
-    private String phonenumber;
-
-    /**
-     * 短信code
-     */
-    @NotBlank(message = "{sms.code.not.blank}")
-    private String smsCode;
-
-}

+ 0 - 27
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java

@@ -1,27 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-
-/**
- * 小程序登录用户身份权限
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@NoArgsConstructor
-public class XcxLoginUser extends LoginUser {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * openid
-     */
-    private String openid;
-
-}

+ 0 - 32
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java

@@ -1,32 +0,0 @@
-package com.ruoyi.common.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 设备类型
- * 针对一套 用户体系
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum DeviceType {
-
-    /**
-     * pc端
-     */
-    PC("pc"),
-
-    /**
-     * app端
-     */
-    APP("app"),
-
-    /**
-     * 小程序端
-     */
-    XCX("xcx");
-
-    private final String device;
-}

+ 0 - 44
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java

@@ -1,44 +0,0 @@
-package com.ruoyi.common.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 登录类型
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum LoginType {
-
-    /**
-     * 密码登录
-     */
-    PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"),
-
-    /**
-     * 短信登录
-     */
-    SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"),
-
-    /**
-     * 邮箱登录
-     */
-    EMAIL("email.code.retry.limit.exceed", "email.code.retry.limit.count"),
-
-    /**
-     * 小程序登录
-     */
-    XCX("", "");
-
-    /**
-     * 登录重试超出限制提示
-     */
-    final String retryLimitExceed;
-
-    /**
-     * 登录重试限制计数提示
-     */
-    final String retryLimitCount;
-}

+ 0 - 30
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/TenantStatus.java

@@ -1,30 +0,0 @@
-package com.ruoyi.common.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 用户状态
- *
- * @author LionLi
- */
-@Getter
-@AllArgsConstructor
-public enum TenantStatus {
-    /**
-     * 正常
-     */
-    OK("0", "正常"),
-    /**
-     * 停用
-     */
-    DISABLE("1", "停用"),
-    /**
-     * 删除
-     */
-    DELETED("2", "删除");
-
-    private final String code;
-    private final String info;
-
-}

+ 0 - 30
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java

@@ -1,30 +0,0 @@
-package com.ruoyi.common.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 用户状态
- *
- * @author ruoyi
- */
-@Getter
-@AllArgsConstructor
-public enum UserStatus {
-    /**
-     * 正常
-     */
-    OK("0", "正常"),
-    /**
-     * 停用
-     */
-    DISABLE("1", "停用"),
-    /**
-     * 删除
-     */
-    DELETED("2", "删除");
-
-    private final String code;
-    private final String info;
-
-}

+ 0 - 37
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java

@@ -1,37 +0,0 @@
-package com.ruoyi.common.core.enums;
-
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 设备类型
- * 针对多套 用户体系
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum UserType {
-
-    /**
-     * pc端
-     */
-    SYS_USER("sys_user"),
-
-    /**
-     * app端
-     */
-    APP_USER("app_user");
-
-    private final String userType;
-
-    public static UserType getUserType(String str) {
-        for (UserType value : values()) {
-            if (StringUtils.contains(str, value.getUserType())) {
-                return value;
-            }
-        }
-        throw new RuntimeException("'UserType' not found By " + str);
-    }
-}

+ 0 - 17
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java

@@ -1,17 +0,0 @@
-package com.ruoyi.common.core.exception;
-
-import java.io.Serial;
-
-/**
- * 演示模式异常
- *
- * @author ruoyi
- */
-public class DemoModeException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public DemoModeException() {
-    }
-}

+ 0 - 53
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java

@@ -1,53 +0,0 @@
-package com.ruoyi.common.core.exception;
-
-import java.io.Serial;
-
-/**
- * 全局异常
- *
- * @author ruoyi
- */
-public class GlobalException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 错误提示
-     */
-    private String message;
-
-    /**
-     * 错误明细,内部调试错误
-     */
-    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;
-    }
-}

+ 0 - 67
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java

@@ -1,67 +0,0 @@
-package com.ruoyi.common.core.exception;
-
-import java.io.Serial;
-
-/**
- * 业务异常
- *
- * @author ruoyi
- */
-public final class ServiceException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 错误码
-     */
-    private Integer code;
-
-    /**
-     * 错误提示
-     */
-    private String message;
-
-    /**
-     * 错误明细,内部调试错误
-     */
-    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;
-    }
-}

+ 0 - 26
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java

@@ -1,26 +0,0 @@
-package com.ruoyi.common.core.exception;
-
-import java.io.Serial;
-
-/**
- * 工具类异常
- *
- * @author ruoyi
- */
-public class UtilException extends RuntimeException {
-
-    @Serial
-    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);
-    }
-}

+ 0 - 79
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java

@@ -1,79 +0,0 @@
-package com.ruoyi.common.core.exception.base;
-
-import com.ruoyi.common.core.utils.MessageUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-
-/**
- * 基础异常
- *
- * @author ruoyi
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@NoArgsConstructor
-public class BaseException extends RuntimeException {
-
-    @Serial
-    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 (!StringUtils.isEmpty(code)) {
-            message = MessageUtils.message(code, args);
-        }
-        if (message == null) {
-            message = defaultMessage;
-        }
-        return message;
-    }
-
-}

+ 0 - 21
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java

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

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java

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

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java

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

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java

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

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java

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

+ 0 - 20
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java

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

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java

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

+ 0 - 19
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java

@@ -1,19 +0,0 @@
-package com.ruoyi.common.core.exception.user;
-
-import java.io.Serial;
-
-/**
- * 用户错误最大次数异常类
- *
- * @author ruoyi
- */
-public class UserPasswordRetryLimitExceedException extends UserException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) {
-        super("user.password.retry.limit.exceed", retryLimitCount, lockTime);
-    }
-
-}

+ 0 - 41
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java

@@ -1,41 +0,0 @@
-package com.ruoyi.common.core.manager;
-
-import com.ruoyi.common.core.utils.Threads;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Component;
-
-import jakarta.annotation.PreDestroy;
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * 确保应用退出时能关闭后台线程
- *
- * @author Lion Li
- */
-@Slf4j
-@Component
-public class ShutdownManager {
-
-    @Autowired
-    @Qualifier("scheduledExecutorService")
-    private ScheduledExecutorService scheduledExecutorService;
-
-    @PreDestroy
-    public void destroy() {
-        shutdownAsyncManager();
-    }
-
-    /**
-     * 停止异步执行任务
-     */
-    private void shutdownAsyncManager() {
-        try {
-            log.info("====关闭后台任务任务线程池====");
-            Threads.shutdownAndAwaitTermination(scheduledExecutorService);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-}

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/ConfigService.java

@@ -1,18 +0,0 @@
-package com.ruoyi.common.core.service;
-
-/**
- * 通用 参数配置服务
- *
- * @author Lion Li
- */
-public interface ConfigService {
-
-    /**
-     * 根据参数 key 获取参数值
-     *
-     * @param configKey 参数 key
-     * @return 参数值
-     */
-    String getConfigValue(String configKey);
-
-}

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DeptService.java

@@ -1,18 +0,0 @@
-package com.ruoyi.common.core.service;
-
-/**
- * 通用 部门服务
- *
- * @author Lion Li
- */
-public interface DeptService {
-
-    /**
-     * 通过部门ID查询部门名称
-     *
-     * @param deptIds 部门ID串逗号分隔
-     * @return 部门名称串逗号分隔
-     */
-    String selectDeptNameByIds(String deptIds);
-
-}

+ 0 - 57
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DictService.java

@@ -1,57 +0,0 @@
-package com.ruoyi.common.core.service;
-
-/**
- * 通用 字典服务
- *
- * @author Lion Li
- */
-public interface DictService {
-
-    /**
-     * 分隔符
-     */
-    String SEPARATOR = ",";
-
-    /**
-     * 根据字典类型和字典值获取字典标签
-     *
-     * @param dictType  字典类型
-     * @param dictValue 字典值
-     * @return 字典标签
-     */
-    default String getDictLabel(String dictType, String dictValue) {
-        return getDictLabel(dictType, dictValue, SEPARATOR);
-    }
-
-    /**
-     * 根据字典类型和字典标签获取字典值
-     *
-     * @param dictType  字典类型
-     * @param dictLabel 字典标签
-     * @return 字典值
-     */
-    default String getDictValue(String dictType, String dictLabel) {
-        return getDictValue(dictType, dictLabel, SEPARATOR);
-    }
-
-    /**
-     * 根据字典类型和字典值获取字典标签
-     *
-     * @param dictType  字典类型
-     * @param dictValue 字典值
-     * @param separator 分隔符
-     * @return 字典标签
-     */
-    String getDictLabel(String dictType, String dictValue, String separator);
-
-    /**
-     * 根据字典类型和字典标签获取字典值
-     *
-     * @param dictType  字典类型
-     * @param dictLabel 字典标签
-     * @param separator 分隔符
-     * @return 字典值
-     */
-    String getDictValue(String dictType, String dictLabel, String separator);
-
-}

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/OssService.java

@@ -1,18 +0,0 @@
-package com.ruoyi.common.core.service;
-
-/**
- * 通用 OSS服务
- *
- * @author Lion Li
- */
-public interface OssService {
-
-    /**
-     * 通过ossId查询对应的url
-     *
-     * @param ossIds ossId串逗号分隔
-     * @return url串逗号分隔
-     */
-    String selectUrlByIds(String ossIds);
-
-}

+ 0 - 18
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/UserService.java

@@ -1,18 +0,0 @@
-package com.ruoyi.common.core.service;
-
-/**
- * 通用 用户服务
- *
- * @author Lion Li
- */
-public interface UserService {
-
-    /**
-     * 通过用户ID查询用户账户
-     *
-     * @param userId 用户ID
-     * @return 用户账户
-     */
-    String selectUserNameById(Long userId);
-
-}

+ 0 - 168
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java

@@ -1,168 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.commons.lang3.time.DateFormatUtils;
-
-import java.lang.management.ManagementFactory;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Date;
-
-/**
- * 时间工具类
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
-
-    public static final String YYYY = "yyyy";
-
-    public static final String YYYY_MM = "yyyy-MM";
-
-    public static final String YYYY_MM_DD = "yyyy-MM-dd";
-
-    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
-
-    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
-
-    private static final String[] PARSE_PATTERNS = {
-        "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
-        "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
-        "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
-
-    /**
-     * 获取当前Date型日期
-     *
-     * @return Date() 当前日期
-     */
-    public static Date getNowDate() {
-        return new Date();
-    }
-
-    /**
-     * 获取当前日期, 默认格式为yyyy-MM-dd
-     *
-     * @return String
-     */
-    public static String getDate() {
-        return dateTimeNow(YYYY_MM_DD);
-    }
-
-    public static String getTime() {
-        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
-    }
-
-    public static String dateTimeNow() {
-        return dateTimeNow(YYYYMMDDHHMMSS);
-    }
-
-    public static String dateTimeNow(final String format) {
-        return parseDateToStr(format, new Date());
-    }
-
-    public static String dateTime(final Date date) {
-        return parseDateToStr(YYYY_MM_DD, date);
-    }
-
-    public static String parseDateToStr(final String format, final Date date) {
-        return new SimpleDateFormat(format).format(date);
-    }
-
-    public static Date dateTime(final String format, final String ts) {
-        try {
-            return new SimpleDateFormat(format).parse(ts);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 日期路径 即年/月/日 如2018/08/08
-     */
-    public static String datePath() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyy/MM/dd");
-    }
-
-    /**
-     * 日期路径 即年/月/日 如20180808
-     */
-    public static String dateTime() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyyMMdd");
-    }
-
-    /**
-     * 日期型字符串转化为日期 格式
-     */
-    public static Date parseDate(Object str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            return parseDate(str.toString(), PARSE_PATTERNS);
-        } catch (ParseException e) {
-            return null;
-        }
-    }
-
-    /**
-     * 获取服务器启动时间
-     */
-    public static Date getServerStartDate() {
-        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
-        return new Date(time);
-    }
-
-    /**
-     * 计算相差天数
-     */
-    public static int differentDaysByMillisecond(Date date1, Date date2) {
-        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
-    }
-
-    /**
-     * 计算两个时间差
-     */
-    public static String getDatePoor(Date endDate, Date nowDate) {
-        long nd = 1000 * 24 * 60 * 60;
-        long nh = 1000 * 60 * 60;
-        long nm = 1000 * 60;
-        // long ns = 1000;
-        // 获得两个时间的毫秒时间差异
-        long diff = endDate.getTime() - nowDate.getTime();
-        // 计算差多少天
-        long day = diff / nd;
-        // 计算差多少小时
-        long hour = diff % nd / nh;
-        // 计算差多少分钟
-        long min = diff % nd % nh / nm;
-        // 计算差多少秒//输出结果
-        // long sec = diff % nd % nh % nm / ns;
-        return day + "天" + hour + "小时" + min + "分钟";
-    }
-
-    /**
-     * 增加 LocalDateTime ==> Date
-     */
-    public static Date toDate(LocalDateTime temporalAccessor) {
-        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
-        return Date.from(zdt.toInstant());
-    }
-
-    /**
-     * 增加 LocalDate ==> Date
-     */
-    public static Date toDate(LocalDate temporalAccessor) {
-        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
-        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
-        return Date.from(zdt.toInstant());
-    }
-}

+ 0 - 92
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MapstructUtils.java

@@ -1,92 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjectUtil;
-import io.github.linpeilie.Converter;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mapstruct 工具类
- * <p>参考文档:<a href="https://mapstruct.plus/guide/quick-start">mapstruct-plus</a></p>
- *
- * @author Michelle.Chung
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class MapstructUtils {
-
-    private final static Converter CONVERTER = SpringUtils.getBean(Converter.class);
-
-    /**
-     * 将 T 类型对象,转换为 desc 类型的对象并返回
-     *
-     * @param source 数据来源实体
-     * @param desc   描述对象 转换后的对象
-     * @return desc
-     */
-    public static <T, V> V convert(T source, Class<V> desc) {
-        if (ObjectUtil.isNull(source)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(desc)) {
-            return null;
-        }
-        return CONVERTER.convert(source, desc);
-    }
-
-    /**
-     * 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象
-     *
-     * @param source 数据来源实体
-     * @param desc   转换后的对象
-     * @return desc
-     */
-    public static <T, V> V convert(T source, V desc) {
-        if (ObjectUtil.isNull(source)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(desc)) {
-            return null;
-        }
-        return CONVERTER.convert(source, desc);
-    }
-
-    /**
-     * 将 T 类型的集合,转换为 desc 类型的集合并返回
-     *
-     * @param sourceList 数据来源实体列表
-     * @param desc       描述对象 转换后的对象
-     * @return desc
-     */
-    public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) {
-        if (ObjectUtil.isNull(sourceList)) {
-            return null;
-        }
-        if (CollUtil.isEmpty(sourceList)) {
-            return CollUtil.newArrayList();
-        }
-        return CONVERTER.convert(sourceList, desc);
-    }
-
-    /**
-     * 将 Map 转换为 beanClass 类型的集合并返回
-     *
-     * @param map       数据来源
-     * @param beanClass bean类
-     * @return bean对象
-     */
-    public static <T> T convert(Map<String, Object> map, Class<T> beanClass) {
-        if (MapUtil.isEmpty(map)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(beanClass)) {
-            return null;
-        }
-        return CONVERTER.convert(map, beanClass);
-    }
-
-}

+ 0 - 28
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java

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

+ 0 - 193
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java

@@ -1,193 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import cn.hutool.core.convert.Convert;
-import cn.hutool.extra.servlet.JakartaServletUtil;
-import cn.hutool.http.HttpStatus;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.springframework.http.MediaType;
-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 java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 客户端工具类
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ServletUtils extends JakartaServletUtil {
-
-    /**
-     * 获取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);
-    }
-
-    /**
-     * 获得所有请求参数
-     *
-     * @param request 请求对象{@link ServletRequest}
-     * @return Map
-     */
-    public static Map<String, String[]> getParams(ServletRequest request) {
-        final Map<String, String[]> map = request.getParameterMap();
-        return Collections.unmodifiableMap(map);
-    }
-
-    /**
-     * 获得所有请求参数
-     *
-     * @param request 请求对象{@link ServletRequest}
-     * @return Map
-     */
-    public static Map<String, String> getParamMap(ServletRequest request) {
-        Map<String, String> params = new HashMap<>();
-        for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) {
-            params.put(entry.getKey(), StringUtils.join(entry.getValue(), StringUtils.SEPARATOR));
-        }
-        return params;
-    }
-
-    /**
-     * 获取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(HttpStatus.HTTP_OK);
-            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
-            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
-            response.getWriter().print(string);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * 是否是Ajax异步请求
-     *
-     * @param request
-     */
-    public static boolean isAjaxRequest(HttpServletRequest request) {
-
-        String accept = request.getHeader("accept");
-        if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) {
-            return true;
-        }
-
-        String xRequestedWith = request.getHeader("X-Requested-With");
-        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
-            return true;
-        }
-
-        String uri = request.getRequestURI();
-        if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) {
-            return true;
-        }
-
-        String ajax = request.getParameter("__ajax");
-        return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml");
-    }
-
-    public static String getClientIP() {
-        return getClientIP(getRequest());
-    }
-
-    /**
-     * 内容编码
-     *
-     * @param str 内容
-     * @return 编码后的内容
-     */
-    public static String urlEncode(String str) {
-        return URLEncoder.encode(str, StandardCharsets.UTF_8);
-    }
-
-    /**
-     * 内容解码
-     *
-     * @param str 内容
-     * @return 解码后的内容
-     */
-    public static String urlDecode(String str) {
-        return URLDecoder.decode(str, StandardCharsets.UTF_8);
-    }
-
-}

+ 0 - 62
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java

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

+ 0 - 254
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java

@@ -1,254 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.*;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * stream 流工具类
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class StreamUtils {
-
-    /**
-     * 将collection过滤
-     *
-     * @param collection 需要转化的集合
-     * @param function   过滤方法
-     * @return 过滤后的list
-     */
-    public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题
-        return collection.stream().filter(function).collect(Collectors.toList());
-    }
-
-    /**
-     * 将collection拼接
-     *
-     * @param collection 需要转化的集合
-     * @param function   拼接方法
-     * @return 拼接后的list
-     */
-    public static <E> String join(Collection<E> collection, Function<E, String> function) {
-        return join(collection, function, StringUtils.SEPARATOR);
-    }
-
-    /**
-     * 将collection拼接
-     *
-     * @param collection 需要转化的集合
-     * @param function   拼接方法
-     * @param delimiter  拼接符
-     * @return 拼接后的list
-     */
-    public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
-        if (CollUtil.isEmpty(collection)) {
-            return StringUtils.EMPTY;
-        }
-        return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
-    }
-
-    /**
-     * 将collection排序
-     *
-     * @param collection 需要转化的集合
-     * @param comparing  排序方法
-     * @return 排序后的list
-     */
-    public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题
-        return collection.stream().sorted(comparing).collect(Collectors.toList());
-    }
-
-    /**
-     * 将collection转化为类型不变的map<br>
-     * <B>{@code Collection<V>  ---->  Map<K,V>}</B>
-     *
-     * @param collection 需要转化的集合
-     * @param key        V类型转化为K类型的lambda方法
-     * @param <V>        collection中的泛型
-     * @param <K>        map中的key类型
-     * @return 转化后的map
-     */
-    public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
-    }
-
-    /**
-     * 将Collection转化为map(value类型与collection的泛型不同)<br>
-     * <B>{@code Collection<E> -----> Map<K,V>  }</B>
-     *
-     * @param collection 需要转化的集合
-     * @param key        E类型转化为K类型的lambda方法
-     * @param value      E类型转化为V类型的lambda方法
-     * @param <E>        collection中的泛型
-     * @param <K>        map中的key类型
-     * @param <V>        map中的value类型
-     * @return 转化后的map
-     */
-    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
-    }
-
-    /**
-     * 将collection按照规则(比如有相同的班级id)分类成map<br>
-     * <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
-     *
-     * @param collection 需要分类的集合
-     * @param key        分类的规则
-     * @param <E>        collection中的泛型
-     * @param <K>        map中的key类型
-     * @return 分类后的map
-     */
-    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
-    }
-
-    /**
-     * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
-     * <B>{@code Collection<E>  --->  Map<T,Map<U,List<E>>> } </B>
-     *
-     * @param collection 需要分类的集合
-     * @param key1       第一个分类的规则
-     * @param key2       第二个分类的规则
-     * @param <E>        集合元素类型
-     * @param <K>        第一个map中的key类型
-     * @param <U>        第二个map中的key类型
-     * @return 分类后的map
-     */
-    public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
-    }
-
-    /**
-     * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
-     * <B>{@code Collection<E>  --->  Map<T,Map<U,E>> } </B>
-     *
-     * @param collection 需要分类的集合
-     * @param key1       第一个分类的规则
-     * @param key2       第二个分类的规则
-     * @param <T>        第一个map中的key类型
-     * @param <U>        第二个map中的key类型
-     * @param <E>        collection中的泛型
-     * @return 分类后的map
-     */
-    public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
-        if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
-    }
-
-    /**
-     * 将collection转化为List集合,但是两者的泛型不同<br>
-     * <B>{@code Collection<E>  ------>  List<T> } </B>
-     *
-     * @param collection 需要转化的集合
-     * @param function   collection中的泛型转化为list泛型的lambda表达式
-     * @param <E>        collection中的泛型
-     * @param <T>        List中的泛型
-     * @return 转化后的list
-     */
-    public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        return collection
-            .stream()
-            .map(function)
-            .filter(Objects::nonNull)
-            // 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题
-            .collect(Collectors.toList());
-    }
-
-    /**
-     * 将collection转化为Set集合,但是两者的泛型不同<br>
-     * <B>{@code Collection<E>  ------>  Set<T> } </B>
-     *
-     * @param collection 需要转化的集合
-     * @param function   collection中的泛型转化为set泛型的lambda表达式
-     * @param <E>        collection中的泛型
-     * @param <T>        Set中的泛型
-     * @return 转化后的Set
-     */
-    public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
-        if (CollUtil.isEmpty(collection) || function == null) {
-            return CollUtil.newHashSet();
-        }
-        return collection
-            .stream()
-            .map(function)
-            .filter(Objects::nonNull)
-            .collect(Collectors.toSet());
-    }
-
-
-    /**
-     * 合并两个相同key类型的map
-     *
-     * @param map1  第一个需要合并的 map
-     * @param map2  第二个需要合并的 map
-     * @param merge 合并的lambda,将key  value1 value2合并成最终的类型,注意value可能为空的情况
-     * @param <K>   map中的key类型
-     * @param <X>   第一个 map的value类型
-     * @param <Y>   第二个 map的value类型
-     * @param <V>   最终map的value类型
-     * @return 合并后的map
-     */
-    public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
-        if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
-            return MapUtil.newHashMap();
-        } else if (MapUtil.isEmpty(map1)) {
-            map1 = MapUtil.newHashMap();
-        } else if (MapUtil.isEmpty(map2)) {
-            map2 = MapUtil.newHashMap();
-        }
-        Set<K> key = new HashSet<>();
-        key.addAll(map1.keySet());
-        key.addAll(map2.keySet());
-        Map<K, V> map = new HashMap<>();
-        for (K t : key) {
-            X x = map1.get(t);
-            Y y = map2.get(t);
-            V z = merge.apply(x, y);
-            if (z != null) {
-                map.put(t, z);
-            }
-        }
-        return map;
-    }
-
-}

+ 0 - 321
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java

@@ -1,321 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.lang.Validator;
-import cn.hutool.core.util.StrUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.springframework.util.AntPathMatcher;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 字符串工具类
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class StringUtils extends org.apache.commons.lang3.StringUtils {
-
-    public static final String SEPARATOR = ",";
-
-    /**
-     * 获取参数不为空值
-     *
-     * @param str defaultValue 要判断的value
-     * @return value 返回值
-     */
-    public static String blankToDefault(String str, String defaultValue) {
-        return StrUtil.blankToDefault(str, defaultValue);
-    }
-
-    /**
-     * * 判断一个字符串是否为空串
-     *
-     * @param str String
-     * @return true:为空 false:非空
-     */
-    public static boolean isEmpty(String str) {
-        return StrUtil.isEmpty(str);
-    }
-
-    /**
-     * * 判断一个字符串是否为非空串
-     *
-     * @param str String
-     * @return true:非空串 false:空串
-     */
-    public static boolean isNotEmpty(String str) {
-        return !isEmpty(str);
-    }
-
-    /**
-     * 去空格
-     */
-    public static String trim(String str) {
-        return StrUtil.trim(str);
-    }
-
-    /**
-     * 截取字符串
-     *
-     * @param str   字符串
-     * @param start 开始
-     * @return 结果
-     */
-    public static String substring(final String str, int start) {
-        return substring(str, start, str.length());
-    }
-
-    /**
-     * 截取字符串
-     *
-     * @param str   字符串
-     * @param start 开始
-     * @param end   结束
-     * @return 结果
-     */
-    public static String substring(final String str, int start, int end) {
-        return StrUtil.sub(str, start, end);
-    }
-
-    /**
-     * 格式化文本, {} 表示占位符<br>
-     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
-     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
-     * 例:<br>
-     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
-     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is {} for a<br>
-     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
-     *
-     * @param template 文本模板,被替换的部分用 {} 表示
-     * @param params   参数值
-     * @return 格式化后的文本
-     */
-    public static String format(String template, Object... params) {
-        return StrUtil.format(template, params);
-    }
-
-    /**
-     * 是否为http(s)://开头
-     *
-     * @param link 链接
-     * @return 结果
-     */
-    public static boolean ishttp(String link) {
-        return Validator.isUrl(link);
-    }
-
-    /**
-     * 字符串转set
-     *
-     * @param str 字符串
-     * @param sep 分隔符
-     * @return set集合
-     */
-    public static Set<String> str2Set(String str, String sep) {
-        return new HashSet<>(str2List(str, sep, true, false));
-    }
-
-    /**
-     * 字符串转list
-     *
-     * @param str         字符串
-     * @param sep         分隔符
-     * @param filterBlank 过滤纯空白
-     * @param trim        去掉首尾空白
-     * @return list集合
-     */
-    public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
-        List<String> list = new ArrayList<>();
-        if (isEmpty(str)) {
-            return list;
-        }
-
-        // 过滤空白字符串
-        if (filterBlank && isBlank(str)) {
-            return list;
-        }
-        String[] split = str.split(sep);
-        for (String string : split) {
-            if (filterBlank && isBlank(string)) {
-                continue;
-            }
-            if (trim) {
-                string = trim(string);
-            }
-            list.add(string);
-        }
-
-        return list;
-    }
-
-    /**
-     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
-     *
-     * @param cs                  指定字符串
-     * @param searchCharSequences 需要检查的字符串数组
-     * @return 是否包含任意一个字符串
-     */
-    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
-        return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);
-    }
-
-    /**
-     * 驼峰转下划线命名
-     */
-    public static String toUnderScoreCase(String str) {
-        return StrUtil.toUnderlineCase(str);
-    }
-
-    /**
-     * 是否包含字符串
-     *
-     * @param str  验证字符串
-     * @param strs 字符串组
-     * @return 包含返回true
-     */
-    public static boolean inStringIgnoreCase(String str, String... strs) {
-        return StrUtil.equalsAnyIgnoreCase(str, strs);
-    }
-
-    /**
-     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
-     *
-     * @param name 转换前的下划线大写方式命名的字符串
-     * @return 转换后的驼峰式命名的字符串
-     */
-    public static String convertToCamelCase(String name) {
-        return StrUtil.upperFirst(StrUtil.toCamelCase(name));
-    }
-
-    /**
-     * 驼峰式命名法 例如:user_name->userName
-     */
-    public static String toCamelCase(String s) {
-        return StrUtil.toCamelCase(s);
-    }
-
-    /**
-     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
-     *
-     * @param str  指定字符串
-     * @param strs 需要检查的字符串数组
-     * @return 是否匹配
-     */
-    public static boolean matches(String str, List<String> strs) {
-        if (isEmpty(str) || CollUtil.isEmpty(strs)) {
-            return false;
-        }
-        for (String pattern : strs) {
-            if (isMatch(pattern, str)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 判断url是否与规则配置:
-     * ? 表示单个字符;
-     * * 表示一层路径内的任意字符串,不可跨层级;
-     * ** 表示任意层路径;
-     *
-     * @param pattern 匹配规则
-     * @param url     需要匹配的url
-     */
-    public static boolean isMatch(String pattern, String url) {
-        AntPathMatcher matcher = new AntPathMatcher();
-        return matcher.match(pattern, url);
-    }
-
-    /**
-     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
-     *
-     * @param num  数字对象
-     * @param size 字符串指定长度
-     * @return 返回数字的字符串格式,该字符串为指定长度。
-     */
-    public static String padl(final Number num, final int size) {
-        return padl(num.toString(), size, '0');
-    }
-
-    /**
-     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
-     *
-     * @param s    原始字符串
-     * @param size 字符串指定长度
-     * @param c    用于补齐的字符
-     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
-     */
-    public static String padl(final String s, final int size, final char c) {
-        final StringBuilder sb = new StringBuilder(size);
-        if (s != null) {
-            final int len = s.length();
-            if (s.length() <= size) {
-                sb.append(String.valueOf(c).repeat(size - len));
-                sb.append(s);
-            } else {
-                return s.substring(len - size, len);
-            }
-        } else {
-            sb.append(String.valueOf(c).repeat(Math.max(0, size)));
-        }
-        return sb.toString();
-    }
-
-    /**
-     * 切分字符串(分隔符默认逗号)
-     *
-     * @param str 被切分的字符串
-     * @return 分割后的数据列表
-     */
-    public static List<String> splitList(String str) {
-        return splitTo(str, Convert::toStr);
-    }
-
-    /**
-     * 切分字符串
-     *
-     * @param str       被切分的字符串
-     * @param separator 分隔符
-     * @return 分割后的数据列表
-     */
-    public static List<String> splitList(String str, String separator) {
-        return splitTo(str, separator, Convert::toStr);
-    }
-
-    /**
-     * 切分字符串自定义转换(分隔符默认逗号)
-     *
-     * @param str    被切分的字符串
-     * @param mapper 自定义转换
-     * @return 分割后的数据列表
-     */
-    public static <T> List<T> splitTo(String str, Function<? super Object, T> mapper) {
-        return splitTo(str, SEPARATOR, mapper);
-    }
-
-    /**
-     * 切分字符串自定义转换
-     *
-     * @param str       被切分的字符串
-     * @param separator 分隔符
-     * @param mapper    自定义转换
-     * @return 分割后的数据列表
-     */
-    public static <T> List<T> splitTo(String str, String separator, Function<? super Object, T> mapper) {
-        if (isBlank(str)) {
-            return new ArrayList<>(0);
-        }
-        return StrUtil.split(str, separator)
-            .stream()
-            .filter(Objects::nonNull)
-            .map(mapper)
-            .collect(Collectors.toList());
-    }
-
-}

+ 0 - 75
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java

@@ -1,75 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.concurrent.*;
-
-/**
- * 线程相关工具类.
- *
- * @author ruoyi
- */
-@Slf4j
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class Threads {
-
-    /**
-     * 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)) {
-                        log.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) {
-            log.error(t.getMessage(), t);
-        }
-    }
-}

+ 0 - 35
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java

@@ -1,35 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.tree.Tree;
-import cn.hutool.core.lang.tree.TreeNodeConfig;
-import cn.hutool.core.lang.tree.TreeUtil;
-import cn.hutool.core.lang.tree.parser.NodeParser;
-import com.ruoyi.common.core.utils.reflect.ReflectUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * 扩展 hutool TreeUtil 封装系统树构建
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class TreeBuildUtils extends TreeUtil {
-
-    /**
-     * 根据前端定制差异化字段
-     */
-    public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
-
-    public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> nodeParser) {
-        if (CollUtil.isEmpty(list)) {
-            return null;
-        }
-        K k = ReflectUtils.invokeGetter(list.get(0), "parentId");
-        return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
-    }
-
-}

+ 0 - 28
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java

@@ -1,28 +0,0 @@
-package com.ruoyi.common.core.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
-import jakarta.validation.Validator;
-import java.util.Set;
-
-/**
- * Validator 校验框架工具
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ValidatorUtils {
-
-    private static final Validator VALID = SpringUtils.getBean(Validator.class);
-
-    public static <T> void validate(T object, Class<?>... groups) {
-        Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
-        if (!validate.isEmpty()) {
-            throw new ConstraintViolationException("参数校验异常", validate);
-        }
-    }
-
-}

+ 0 - 43
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java

@@ -1,43 +0,0 @@
-package com.ruoyi.common.core.utils.file;
-
-import cn.hutool.core.io.FileUtil;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-
-/**
- * 文件处理工具类
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class FileUtils extends FileUtil {
-
-    /**
-     * 下载文件名重新编码
-     *
-     * @param response     响应对象
-     * @param realFileName 真实文件名
-     */
-    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) {
-        String percentEncodedFileName = percentEncode(realFileName);
-        String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName);
-        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
-        response.setHeader("Content-disposition", contentDispositionValue);
-        response.setHeader("download-filename", percentEncodedFileName);
-    }
-
-    /**
-     * 百分号编码工具方法
-     *
-     * @param s 需要百分号编码的字符串
-     * @return 百分号编码后的字符串
-     */
-    public static String percentEncode(String s) {
-        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
-        return encode.replaceAll("\\+", "%20");
-    }
-}

+ 0 - 40
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java

@@ -1,40 +0,0 @@
-package com.ruoyi.common.core.utils.file;
-
-/**
- * 媒体类型工具类
- *
- * @author ruoyi
- */
-public class MimeTypeUtils {
-    public static final String IMAGE_PNG = "image/png";
-
-    public static final String IMAGE_JPG = "image/jpg";
-
-    public static final String IMAGE_JPEG = "image/jpeg";
-
-    public static final String IMAGE_BMP = "image/bmp";
-
-    public static final String IMAGE_GIF = "image/gif";
-
-    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
-
-    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
-
-    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
-        "asf", "rm", "rmvb"};
-
-    public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
-
-    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
-        // 图片
-        "bmp", "gif", "jpg", "jpeg", "png",
-        // word excel powerpoint
-        "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
-        // 压缩文件
-        "rar", "zip", "gz", "bz2",
-        // 视频格式
-        "mp4", "avi", "rmvb",
-        // pdf
-        "pdf"};
-
-}

+ 0 - 33
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java

@@ -1,33 +0,0 @@
-package com.ruoyi.common.core.utils.ip;
-
-import cn.hutool.core.net.NetUtil;
-import cn.hutool.http.HtmlUtil;
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 获取地址类
- *
- * @author Lion Li
- */
-@Slf4j
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class AddressUtils {
-
-    // 未知地址
-    public static final String UNKNOWN = "XX XX";
-
-    public static String getRealAddressByIP(String ip) {
-        if (StringUtils.isBlank(ip)) {
-            return UNKNOWN;
-        }
-        // 内网不查询
-        ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
-        if (NetUtil.isInnerIP(ip)) {
-            return "内网IP";
-        }
-        return RegionUtils.getCityInfo(ip);
-    }
-}

+ 0 - 67
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/RegionUtils.java

@@ -1,67 +0,0 @@
-package com.ruoyi.common.core.utils.ip;
-
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.resource.ClassPathResource;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.core.exception.ServiceException;
-import com.ruoyi.common.core.utils.file.FileUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.lionsoul.ip2region.xdb.Searcher;
-
-import java.io.File;
-
-/**
- * 根据ip地址定位工具类,离线方式
- * 参考地址:<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">集成 ip2region 实现离线IP地址定位库</a>
- *
- * @author lishuyan
- */
-@Slf4j
-public class RegionUtils {
-
-    private static final Searcher SEARCHER;
-
-    static {
-        String fileName = "/ip2region.xdb";
-        File existFile = FileUtils.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
-        if (!FileUtils.exist(existFile)) {
-            ClassPathResource fileStream = new ClassPathResource(fileName);
-            if (ObjectUtil.isEmpty(fileStream.getStream())) {
-                throw new ServiceException("RegionUtils初始化失败,原因:IP地址库数据不存在!");
-            }
-            FileUtils.writeFromStream(fileStream.getStream(), existFile);
-        }
-
-        String dbPath = existFile.getPath();
-
-        // 1、从 dbPath 加载整个 xdb 到内存。
-        byte[] cBuff;
-        try {
-            cBuff = Searcher.loadContentFromFile(dbPath);
-        } catch (Exception e) {
-            throw new ServiceException("RegionUtils初始化失败,原因:从ip2region.xdb文件加载内容失败!" + e.getMessage());
-        }
-        // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
-        try {
-            SEARCHER = Searcher.newWithBuffer(cBuff);
-        } catch (Exception e) {
-            throw new ServiceException("RegionUtils初始化失败,原因:" + e.getMessage());
-        }
-    }
-
-    /**
-     * 根据IP地址离线获取城市
-     */
-    public static String getCityInfo(String ip) {
-        try {
-            ip = ip.trim();
-            // 3、执行查询
-            String region = SEARCHER.search(ip);
-            return region.replace("0|", "").replace("|0", "");
-        } catch (Exception e) {
-            log.error("IP地址离线获取城市异常 {}", ip);
-            return "未知";
-        }
-    }
-
-}

+ 0 - 56
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java

@@ -1,56 +0,0 @@
-package com.ruoyi.common.core.utils.reflect;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.lang.reflect.Method;
-
-/**
- * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
- *
- * @author Lion Li
- */
-@SuppressWarnings("rawtypes")
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ReflectUtils extends ReflectUtil {
-
-    private static final String SETTER_PREFIX = "set";
-
-    private static final String GETTER_PREFIX = "get";
-
-    /**
-     * 调用Getter方法.
-     * 支持多级,如:对象名.对象名.方法
-     */
-    @SuppressWarnings("unchecked")
-    public static <E> E invokeGetter(Object obj, String propertyName) {
-        Object object = obj;
-        for (String name : StringUtils.split(propertyName, ".")) {
-            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
-            object = invoke(object, getterMethodName);
-        }
-        return (E) object;
-    }
-
-    /**
-     * 调用Setter方法, 仅匹配方法名。
-     * 支持多级,如:对象名.对象名.方法
-     */
-    public static <E> void invokeSetter(Object obj, String propertyName, E value) {
-        Object object = obj;
-        String[] names = StringUtils.split(propertyName, ".");
-        for (int i = 0; i < names.length; i++) {
-            if (i < names.length - 1) {
-                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
-                object = invoke(object, getterMethodName);
-            } else {
-                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
-                Method method = getMethodByName(object.getClass(), setterMethodName);
-                invoke(object, method, value);
-            }
-        }
-    }
-
-}

+ 0 - 57
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java

@@ -1,57 +0,0 @@
-package com.ruoyi.common.core.utils.sql;
-
-import com.ruoyi.common.core.exception.UtilException;
-import com.ruoyi.common.core.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-/**
- * sql操作工具类
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class SqlUtil {
-
-    /**
-     * 定义常用的 sql关键字
-     */
-    public static final String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
-
-    /**
-     * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
-     */
-    public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
-
-    /**
-     * 检查字符,防止注入绕过
-     */
-    public static String escapeOrderBySql(String value) {
-        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
-            throw new UtilException("参数不符合规范,不能进行查询");
-        }
-        return value;
-    }
-
-    /**
-     * 验证 order by 语法是否符合规范
-     */
-    public static boolean isValidOrderBySql(String value) {
-        return value.matches(SQL_PATTERN);
-    }
-
-    /**
-     * SQL关键字检查
-     */
-    public static void filterKeyword(String value) {
-        if (StringUtils.isEmpty(value)) {
-            return;
-        }
-        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
-        for (String sqlKeyword : sqlKeywords) {
-            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
-                throw new UtilException("参数存在SQL注入风险");
-            }
-        }
-    }
-}

+ 0 - 9
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/AddGroup.java

@@ -1,9 +0,0 @@
-package com.ruoyi.common.core.validate;
-
-/**
- * 校验分组 add
- *
- * @author Lion Li
- */
-public interface AddGroup {
-}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików