mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-24 07:19:46 +08:00
Compare commits
132 Commits
Author | SHA1 | Date | |
---|---|---|---|
1a70cf658c | |||
242e26abee | |||
52d33195ec | |||
d8b486c793 | |||
00b6ca5dfe | |||
9ebaf936c1 | |||
dac463efa6 | |||
da1b18792b | |||
85b4adf400 | |||
70f39cb1ee | |||
d87dfd6397 | |||
1496220a74 | |||
996835d124 | |||
f6f3db1701 | |||
6ee3085260 | |||
a6f6562693 | |||
d8585d0ee7 | |||
4761237849 | |||
f1a09711c1 | |||
346a3cf7f1 | |||
c42229bc54 | |||
317ab351ce | |||
e1579622de | |||
f2ff839106 | |||
c494ab9963 | |||
15f7d4dc47 | |||
dd9ef8431b | |||
e729a924d4 | |||
aeacfea536 | |||
43b31edb75 | |||
8448bcdc6d | |||
e1efdb8602 | |||
409849db1a | |||
9d6b0b35a3 | |||
7f00861e68 | |||
d2b1177580 | |||
ef91551449 | |||
4063b0c2dd | |||
5117fe2958 | |||
9ed60f22de | |||
8498ead56c | |||
53ae4ea6bc | |||
4c8137daf2 | |||
6e017c35f7 | |||
06cda3fb18 | |||
b38151a0bb | |||
2790b5ddc4 | |||
f70951d374 | |||
9ebe1ae918 | |||
06e6f7af0c | |||
d6894c89ed | |||
ebf780617a | |||
e130475259 | |||
115af9c402 | |||
8b914c1091 | |||
9c368e8e68 | |||
700db1fc15 | |||
35f9c0fb72 | |||
3091241279 | |||
56050aa650 | |||
b5cbb58c2d | |||
adaa93acfb | |||
5d043078b2 | |||
fe8db721d7 | |||
4d02466fed | |||
ca69c00cf4 | |||
6733e48ea1 | |||
dca5d69dd2 | |||
842af57d74 | |||
8dc92383d9 | |||
1ae35032a5 | |||
223ae7ae72 | |||
87a212f093 | |||
5952b1c90e | |||
83ba9be342 | |||
a1431c5cb1 | |||
e41a58b10d | |||
da94e89825 | |||
0381df6b17 | |||
31acd6b301 | |||
3c5dfdcf57 | |||
e0b65b857d | |||
83395d4e2f | |||
a6bed384d7 | |||
afac00de33 | |||
ee80e97578 | |||
35fac6cc0c | |||
e5515751fd | |||
c9c1e5ca7f | |||
b47e67ff30 | |||
f5de8b9ddf | |||
a63abbf268 | |||
1f42bd3d22 | |||
93c4cc2cd1 | |||
ab4b21ff58 | |||
83a09c475d | |||
9d99afd159 | |||
1858ac6b25 | |||
78290128e7 | |||
68193fd37f | |||
cd9c3c3f4f | |||
8bd023b49f | |||
57daef9ced | |||
fb134da091 | |||
c1a3eaaffb | |||
b6dbe7b5a5 | |||
8138063bfe | |||
4c8dc500c7 | |||
85247991b6 | |||
a127eaa0e9 | |||
ebb9f15a75 | |||
cd137bd9fc | |||
07bde5f88a | |||
6fffa02acf | |||
5830c3c96d | |||
9f2dc5c233 | |||
ec076c1e0d | |||
6e8ef308ed | |||
dc48f9858b | |||
a6b2ac5dcd | |||
c0685b7f7f | |||
fb2d616c57 | |||
6ff6853082 | |||
f8014ae969 | |||
88ed6e25ca | |||
1de2b7a57e | |||
95f7ba0080 | |||
bb73b31e6b | |||
9ecc4475dd | |||
f01aa37394 | |||
4517dea98d | |||
a64a029323 |
@ -1,13 +1,49 @@
|
|||||||
### 使用版本(未按照模板填写直接删除)
|
### 使用版本(未按照模板填写直接删除)
|
||||||
|
|
||||||
|
- jdk版本(带上尾号): 例如 1.8.0_202
|
||||||
|
- 框架版本(项目启动时输出的版本号): 例如 4.4.0
|
||||||
|
- 其他依赖版本(你觉得有必要的):
|
||||||
|
|
||||||
|
### 问题前提
|
||||||
|
|
||||||
|
> 功能不好用 不会用 是否已经看过项目文档
|
||||||
|
> 项目运行报错 是否已经拿着报错信息去百度 常见报错百度百度足以
|
||||||
|
> 是否搜索过其他issue 一些已经解决的问题 会在issue内留下解决方法
|
||||||
|
> 无法线上解决或者与框架无关的问题的欢迎加VIP群跟作者一对一谈
|
||||||
|
|
||||||
|
### 异常模块
|
||||||
|
|
||||||
|
> 此报错都涉及到那些系统模块
|
||||||
|
|
||||||
|
例如 ruoyi-system ruoyi-auth 等等
|
||||||
|
|
||||||
### 问题描述
|
### 问题描述
|
||||||
|
|
||||||
|
> 越详细越容易直击问题所在
|
||||||
|
|
||||||
|
已知: XXX功能不好用 或 XXX数据不正常 等等
|
||||||
|
|
||||||
### 希望结果
|
### 希望结果
|
||||||
|
|
||||||
|
> 想知道你觉得怎么样是正常或者合理的
|
||||||
|
|
||||||
|
希望功能可以有XXX结果 或者 XXX现象
|
||||||
|
|
||||||
### 重现步骤
|
### 重现步骤
|
||||||
|
|
||||||
|
> 作者并不知道这个问题是如何出现的
|
||||||
|
|
||||||
### 报错信息(截图为主 请勿发混乱格式)
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
|
||||||
|
### 相关代码与报错信息(请勿发混乱格式)
|
||||||
|
|
||||||
|
> 代码可按照如下形式提供或者截图均可 越详细越好
|
||||||
|
> 大多数问题都是 代码编写错误问题 逻辑问题 或者用法错误等问题
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class XXX {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
@ -1,7 +1,7 @@
|
|||||||
### 更改目的 解决了什么问题(请提交到dev分支)
|
### 更改目的 解决了什么问题(请提交到dev分支)
|
||||||
|
|
||||||
|
|
||||||
### 描述 做了哪些改动
|
### 改动逻辑 这么写的思路(让作者更好的理解你的意图)
|
||||||
|
|
||||||
|
|
||||||
### 测试 都做了哪些测试(未经过测试不采纳)
|
### 测试 都做了哪些测试(未经过测试不采纳)
|
@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
<deployment type="dockerfile">
|
<deployment type="dockerfile">
|
||||||
<settings>
|
<settings>
|
||||||
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:4.3.1" />
|
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:4.5.0" />
|
||||||
<option name="buildOnly" value="true" />
|
<option name="buildOnly" value="true" />
|
||||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
|
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
|
||||||
</settings>
|
</settings>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
<deployment type="dockerfile">
|
<deployment type="dockerfile">
|
||||||
<settings>
|
<settings>
|
||||||
<option name="imageTag" value="ruoyi/ruoyi-server:4.3.1" />
|
<option name="imageTag" value="ruoyi/ruoyi-server:4.5.0" />
|
||||||
<option name="buildOnly" value="true" />
|
<option name="buildOnly" value="true" />
|
||||||
<option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
|
<option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
|
||||||
</settings>
|
</settings>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<configuration default="false" name="ruoyi-xxl-job-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
<configuration default="false" name="ruoyi-xxl-job-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||||
<deployment type="dockerfile">
|
<deployment type="dockerfile">
|
||||||
<settings>
|
<settings>
|
||||||
<option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.3.1" />
|
<option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.5.0" />
|
||||||
<option name="buildOnly" value="true" />
|
<option name="buildOnly" value="true" />
|
||||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile" />
|
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile" />
|
||||||
</settings>
|
</settings>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
|
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
|
||||||
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
||||||
<br>
|
<br>
|
||||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
|
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
@ -14,7 +14,7 @@
|
|||||||
> 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
|
> 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
|
||||||
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
|
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
|
||||||
|
|
||||||
> 系统演示: [传送门](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/系统演示?sort_id=4836388)
|
> 系统演示: [传送门](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4836388&doc_id=1469725)
|
||||||
|
|
||||||
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
||||||
|----------|---------------------|---------------------------------------------------------------------------------------------------|----------------------------|
|
|----------|---------------------|---------------------------------------------------------------------------------------------------|----------------------------|
|
||||||
@ -41,7 +41,7 @@
|
|||||||
| 分布式队列 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 普通队列、延迟队列、优先队列 等 |
|
| 分布式队列 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 普通队列、延迟队列、优先队列 等 |
|
||||||
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
|
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
|
||||||
| 分布式幂等 | Redisson | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 拦截重复提交 |
|
| 分布式幂等 | Redisson | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 拦截重复提交 |
|
||||||
| 分布式日志 | TLog | [TLog文档](https://yomahub.com/tlog/docs) | 支持跟踪链路日志记录、性能分析、链路排查 |
|
| 分布式链路追踪 | Apache SkyWalking | [Apache SkyWalking文档](https://skywalking.apache.org/docs/) | 链路追踪、网格分析、度量聚合、可视化 |
|
||||||
| 分布式任务调度 | Xxl-Job | [Xxl-Job官网](https://www.xuxueli.com/xxl-job/) | 高性能 高可靠 易扩展 |
|
| 分布式任务调度 | Xxl-Job | [Xxl-Job官网](https://www.xuxueli.com/xxl-job/) | 高性能 高可靠 易扩展 |
|
||||||
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
|
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
|
||||||
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
|
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
|
||||||
@ -51,7 +51,7 @@
|
|||||||
| Excel框架 | Alibaba EasyExcel | [EasyExcel文档](https://www.yuque.com/easyexcel/doc/easyexcel) | 性能优异 扩展性强 |
|
| Excel框架 | Alibaba EasyExcel | [EasyExcel文档](https://www.yuque.com/easyexcel/doc/easyexcel) | 性能优异 扩展性强 |
|
||||||
| 文档框架 | SpringDoc、javadoc | [接口文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5805266&doc_id=1469725) | 无注解零入侵基于java注释 |
|
| 文档框架 | SpringDoc、javadoc | [接口文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5805266&doc_id=1469725) | 无注解零入侵基于java注释 |
|
||||||
| 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 |
|
| 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 |
|
||||||
| 代码生成器 | 适配MP、Knife4j规范化代码 | [Hutool文档](https://www.hutool.cn/docs/) | 一键生成前后端代码 |
|
| 代码生成器 | 适配MP、SpringDoc规范化代码 | [代码生成文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5522329&doc_id=1469725) | 一键生成前后端代码 |
|
||||||
| 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 |
|
| 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 |
|
||||||
| 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
|
| 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
|
||||||
|
|
||||||
|
156
pom.xml
156
pom.xml
@ -6,50 +6,77 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
|
|
||||||
<name>RuoYi-Vue-Plus</name>
|
<name>RuoYi-Vue-Plus</name>
|
||||||
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
|
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
|
||||||
<description>RuoYi-Vue-Plus后台管理系统</description>
|
<description>RuoYi-Vue-Plus后台管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi-vue-plus.version>4.3.1</ruoyi-vue-plus.version>
|
<ruoyi-vue-plus.version>4.5.0</ruoyi-vue-plus.version>
|
||||||
<spring-boot.version>2.7.5</spring-boot.version>
|
<spring-boot.version>2.7.7</spring-boot.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
|
||||||
<spring-boot.mybatis>2.2.2</spring-boot.mybatis>
|
<spring-boot.mybatis>2.2.2</spring-boot.mybatis>
|
||||||
<druid.version>1.2.12</druid.version>
|
<springdoc.version>1.6.14</springdoc.version>
|
||||||
<springdoc.version>1.6.12</springdoc.version>
|
|
||||||
<poi.version>5.2.3</poi.version>
|
<poi.version>5.2.3</poi.version>
|
||||||
<easyexcel.version>3.1.1</easyexcel.version>
|
<easyexcel.version>3.1.5</easyexcel.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<satoken.version>1.31.0</satoken.version>
|
<satoken.version>1.34.0</satoken.version>
|
||||||
<mybatis-plus.version>3.5.2</mybatis-plus.version>
|
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
|
||||||
<p6spy.version>3.9.1</p6spy.version>
|
<p6spy.version>3.9.1</p6spy.version>
|
||||||
<hutool.version>5.8.8</hutool.version>
|
<hutool.version>5.8.11</hutool.version>
|
||||||
<okhttp.version>4.10.0</okhttp.version>
|
<okhttp.version>4.10.0</okhttp.version>
|
||||||
<spring-boot-admin.version>2.7.6</spring-boot-admin.version>
|
<spring-boot-admin.version>2.7.10</spring-boot-admin.version>
|
||||||
<redisson.version>3.17.7</redisson.version>
|
<redisson.version>3.19.1</redisson.version>
|
||||||
<lock4j.version>2.2.2</lock4j.version>
|
<lock4j.version>2.2.3</lock4j.version>
|
||||||
<dynamic-ds.version>3.5.2</dynamic-ds.version>
|
<dynamic-ds.version>3.5.2</dynamic-ds.version>
|
||||||
<tlog.version>1.5.0</tlog.version>
|
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
||||||
<xxl-job.version>2.3.1</xxl-job.version>
|
<xxl-job.version>2.3.1</xxl-job.version>
|
||||||
<lombok.version>1.18.24</lombok.version>
|
<lombok.version>1.18.24</lombok.version>
|
||||||
|
|
||||||
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
|
||||||
<guava.version>31.1-jre</guava.version>
|
|
||||||
<!-- 临时修复 snakeyaml 漏洞 -->
|
<!-- 临时修复 snakeyaml 漏洞 -->
|
||||||
<snakeyaml.version>1.32</snakeyaml.version>
|
<snakeyaml.version>1.33</snakeyaml.version>
|
||||||
|
|
||||||
<!-- OSS 配置 -->
|
<!-- OSS 配置 -->
|
||||||
<aws-java-sdk-s3.version>1.12.324</aws-java-sdk-s3.version>
|
<aws-java-sdk-s3.version>1.12.373</aws-java-sdk-s3.version>
|
||||||
<!-- SMS 配置 -->
|
<!-- SMS 配置 -->
|
||||||
<aliyun.sms.version>2.0.22</aliyun.sms.version>
|
<aliyun.sms.version>2.0.23</aliyun.sms.version>
|
||||||
<tencent.sms.version>3.1.611</tencent.sms.version>
|
<tencent.sms.version>3.1.660</tencent.sms.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>local</id>
|
||||||
|
<properties>
|
||||||
|
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||||
|
<profiles.active>local</profiles.active>
|
||||||
|
<logging.level>debug</logging.level>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||||
|
<profiles.active>dev</profiles.active>
|
||||||
|
<logging.level>debug</logging.level>
|
||||||
|
</properties>
|
||||||
|
<activation>
|
||||||
|
<!-- 默认环境 -->
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>prod</id>
|
||||||
|
<properties>
|
||||||
|
<profiles.active>prod</profiles.active>
|
||||||
|
<logging.level>warn</logging.level>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -72,13 +99,6 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里数据库连接池 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba</groupId>
|
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
|
||||||
<version>${druid.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springdoc-openapi-webmvc-core</artifactId>
|
<artifactId>springdoc-openapi-webmvc-core</artifactId>
|
||||||
@ -157,11 +177,7 @@
|
|||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
<version>${mybatis-plus.version}</version>
|
<version>${mybatis-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>mybatis-plus-extension</artifactId>
|
|
||||||
<version>${mybatis-plus.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- sql性能分析插件 -->
|
<!-- sql性能分析插件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>p6spy</groupId>
|
<groupId>p6spy</groupId>
|
||||||
@ -189,7 +205,7 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.tencentcloudapi</groupId>
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||||
<version>${tencent.sms.version}</version>
|
<version>${tencent.sms.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@ -224,36 +240,9 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.yomahub</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>tlog-web-spring-boot-starter</artifactId>
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
<version>${tlog.version}</version>
|
<version>${alibaba-ttl.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>dom4j</artifactId>
|
|
||||||
<groupId>dom4j</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-beanutils</artifactId>
|
|
||||||
<groupId>commons-beanutils</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.yomahub</groupId>
|
|
||||||
<artifactId>tlog-xxljob-spring-boot-starter</artifactId>
|
|
||||||
<version>${tlog.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>${guava.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 临时修复 snakeyaml 漏洞 -->
|
<!-- 临时修复 snakeyaml 漏洞 -->
|
||||||
@ -365,6 +354,19 @@
|
|||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- 单元测试使用 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>-Dfile.encoding=UTF-8</argLine>
|
||||||
|
<!-- 根据打包环境执行对应的@Tag测试方法 -->
|
||||||
|
<groups>${profiles.active}</groups>
|
||||||
|
<!-- 排除标签 -->
|
||||||
|
<excludedGroups>exclude</excludedGroups>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
@ -411,36 +413,6 @@
|
|||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>local</id>
|
|
||||||
<properties>
|
|
||||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
|
||||||
<profiles.active>local</profiles.active>
|
|
||||||
<logging.level>debug</logging.level>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>dev</id>
|
|
||||||
<properties>
|
|
||||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
|
||||||
<profiles.active>dev</profiles.active>
|
|
||||||
<logging.level>debug</logging.level>
|
|
||||||
</properties>
|
|
||||||
<activation>
|
|
||||||
<!-- 默认环境 -->
|
|
||||||
<activeByDefault>true</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>prod</id>
|
|
||||||
<properties>
|
|
||||||
<profiles.active>prod</profiles.active>
|
|
||||||
<logging.level>warn</logging.level>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
|
|||||||
|
|
||||||
MAINTAINER Lion Li
|
MAINTAINER Lion Li
|
||||||
|
|
||||||
RUN mkdir -p /ruoyi/server
|
RUN mkdir -p /ruoyi/server/logs \
|
||||||
RUN mkdir -p /ruoyi/server/logs
|
/ruoyi/server/temp \
|
||||||
RUN mkdir -p /ruoyi/server/temp
|
/ruoyi/skywalking/agent
|
||||||
|
|
||||||
WORKDIR /ruoyi/server
|
WORKDIR /ruoyi/server
|
||||||
|
|
||||||
@ -14,4 +14,10 @@ EXPOSE ${SERVER_PORT}
|
|||||||
|
|
||||||
ADD ./target/ruoyi-admin.jar ./app.jar
|
ADD ./target/ruoyi-admin.jar ./app.jar
|
||||||
|
|
||||||
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dserver.port=${SERVER_PORT}","-jar", "app.jar"]
|
ENTRYPOINT ["java", \
|
||||||
|
"-Djava.security.egd=file:/dev/./urandom", \
|
||||||
|
"-Dserver.port=${SERVER_PORT}", \
|
||||||
|
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
|
||||||
|
# "-Dskywalking.agent.service_name=ruoyi-server", \
|
||||||
|
# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \
|
||||||
|
"-jar", "app.jar"]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
<!-- Mysql驱动包 -->
|
<!-- Mysql驱动包 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Oracle -->
|
<!-- Oracle -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -78,6 +78,24 @@
|
|||||||
<artifactId>ruoyi-demo</artifactId>
|
<artifactId>ruoyi-demo</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- skywalking 整合 logback -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.apache.skywalking</groupId>-->
|
||||||
|
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
|
||||||
|
<!-- <version>${与你的agent探针版本保持一致}</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.apache.skywalking</groupId>-->
|
||||||
|
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
|
||||||
|
<!-- <version>${与你的agent探针版本保持一致}</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -3,7 +3,6 @@ package com.ruoyi.web.controller.common;
|
|||||||
import cn.dev33.satoken.annotation.SaIgnore;
|
import cn.dev33.satoken.annotation.SaIgnore;
|
||||||
import cn.hutool.captcha.AbstractCaptcha;
|
import cn.hutool.captcha.AbstractCaptcha;
|
||||||
import cn.hutool.captcha.generator.CodeGenerator;
|
import cn.hutool.captcha.generator.CodeGenerator;
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
@ -21,6 +20,9 @@ import com.ruoyi.sms.entity.SmsResult;
|
|||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
@ -95,28 +97,16 @@ public class CaptchaController {
|
|||||||
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||||
captcha.setGenerator(codeGenerator);
|
captcha.setGenerator(codeGenerator);
|
||||||
captcha.createCode();
|
captcha.createCode();
|
||||||
String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode();
|
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));
|
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||||
ajax.put("uuid", uuid);
|
ajax.put("uuid", uuid);
|
||||||
ajax.put("img", captcha.getImageBase64());
|
ajax.put("img", captcha.getImageBase64());
|
||||||
return R.ok(ajax);
|
return R.ok(ajax);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCodeResult(String capStr) {
|
|
||||||
int numberLength = captchaProperties.getNumberLength();
|
|
||||||
int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim());
|
|
||||||
char operator = capStr.charAt(numberLength);
|
|
||||||
int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
|
|
||||||
switch (operator) {
|
|
||||||
case '*':
|
|
||||||
return Convert.toStr(a * b);
|
|
||||||
case '+':
|
|
||||||
return Convert.toStr(a + b);
|
|
||||||
case '-':
|
|
||||||
return Convert.toStr(a - b);
|
|
||||||
default:
|
|
||||||
return StringUtils.EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public class SysUserOnlineController extends BaseController {
|
|||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo<SysUserOnline> list(String ipaddr, String userName) {
|
public TableDataInfo<SysUserOnline> list(String ipaddr, String userName) {
|
||||||
// 获取所有未过期的 token
|
// 获取所有未过期的 token
|
||||||
List<String> keys = StpUtil.searchTokenValue("", -1, 0, false);
|
List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
|
||||||
List<UserOnlineDTO> userOnlineDTOList = new ArrayList<>();
|
List<UserOnlineDTO> userOnlineDTOList = new ArrayList<>();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, "");
|
String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, "");
|
||||||
@ -83,7 +83,7 @@ public class SysUserOnlineController extends BaseController {
|
|||||||
public R<Void> forceLogout(@PathVariable String tokenId) {
|
public R<Void> forceLogout(@PathVariable String tokenId) {
|
||||||
try {
|
try {
|
||||||
StpUtil.kickoutByTokenValue(tokenId);
|
StpUtil.kickoutByTokenValue(tokenId);
|
||||||
} catch (NotLoginException e) {
|
} catch (NotLoginException ignored) {
|
||||||
}
|
}
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
@ -108,10 +108,10 @@ public class SysDeptController extends BaseController {
|
|||||||
@DeleteMapping("/{deptId}")
|
@DeleteMapping("/{deptId}")
|
||||||
public R<Void> remove(@PathVariable Long deptId) {
|
public R<Void> remove(@PathVariable Long deptId) {
|
||||||
if (deptService.hasChildByDeptId(deptId)) {
|
if (deptService.hasChildByDeptId(deptId)) {
|
||||||
return R.fail("存在下级部门,不允许删除");
|
return R.warn("存在下级部门,不允许删除");
|
||||||
}
|
}
|
||||||
if (deptService.checkDeptExistUser(deptId)) {
|
if (deptService.checkDeptExistUser(deptId)) {
|
||||||
return R.fail("部门存在用户,不允许删除");
|
return R.warn("部门存在用户,不允许删除");
|
||||||
}
|
}
|
||||||
deptService.checkDeptDataScope(deptId);
|
deptService.checkDeptDataScope(deptId);
|
||||||
return toAjax(deptService.deleteDeptById(deptId));
|
return toAjax(deptService.deleteDeptById(deptId));
|
||||||
|
@ -13,7 +13,6 @@ import com.ruoyi.system.domain.vo.RouterVo;
|
|||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
import com.ruoyi.system.service.SysLoginService;
|
import com.ruoyi.system.service.SysLoginService;
|
||||||
import com.ruoyi.system.service.SysPermissionService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -39,7 +38,6 @@ public class SysLoginController {
|
|||||||
private final SysLoginService loginService;
|
private final SysLoginService loginService;
|
||||||
private final ISysMenuService menuService;
|
private final ISysMenuService menuService;
|
||||||
private final ISysUserService userService;
|
private final ISysUserService userService;
|
||||||
private final SysPermissionService permissionService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
|
@ -117,10 +117,10 @@ public class SysMenuController extends BaseController {
|
|||||||
@DeleteMapping("/{menuId}")
|
@DeleteMapping("/{menuId}")
|
||||||
public R<Void> remove(@PathVariable("menuId") Long menuId) {
|
public R<Void> remove(@PathVariable("menuId") Long menuId) {
|
||||||
if (menuService.hasChildByMenuId(menuId)) {
|
if (menuService.hasChildByMenuId(menuId)) {
|
||||||
return R.fail("存在子菜单,不允许删除");
|
return R.warn("存在子菜单,不允许删除");
|
||||||
}
|
}
|
||||||
if (menuService.checkMenuExistRole(menuId)) {
|
if (menuService.checkMenuExistRole(menuId)) {
|
||||||
return R.fail("菜单已分配,不允许删除");
|
return R.warn("菜单已分配,不允许删除");
|
||||||
}
|
}
|
||||||
return toAjax(menuService.deleteMenuById(menuId));
|
return toAjax(menuService.deleteMenuById(menuId));
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class SysOssConfigController extends BaseController {
|
|||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||||
return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0);
|
return toAjax(iSysOssConfigService.insertByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +77,7 @@ public class SysOssConfigController extends BaseController {
|
|||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||||
return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0);
|
return toAjax(iSysOssConfigService.updateByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,7 +90,7 @@ public class SysOssConfigController extends BaseController {
|
|||||||
@DeleteMapping("/{ossConfigIds}")
|
@DeleteMapping("/{ossConfigIds}")
|
||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ossConfigIds) {
|
@PathVariable Long[] ossConfigIds) {
|
||||||
return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0);
|
return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup;
|
|||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.file.FileUtils;
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
|
import com.ruoyi.oss.core.OssClient;
|
||||||
|
import com.ruoyi.oss.factory.OssFactory;
|
||||||
import com.ruoyi.system.domain.SysOss;
|
import com.ruoyi.system.domain.SysOss;
|
||||||
import com.ruoyi.system.domain.bo.SysOssBo;
|
import com.ruoyi.system.domain.bo.SysOssBo;
|
||||||
import com.ruoyi.system.domain.vo.SysOssVo;
|
import com.ruoyi.system.domain.vo.SysOssVo;
|
||||||
@ -80,7 +82,7 @@ public class SysOssController extends BaseController {
|
|||||||
if (ObjectUtil.isNull(file)) {
|
if (ObjectUtil.isNull(file)) {
|
||||||
throw new ServiceException("上传文件不能为空");
|
throw new ServiceException("上传文件不能为空");
|
||||||
}
|
}
|
||||||
SysOss oss = iSysOssService.upload(file);
|
SysOssVo oss = iSysOssService.upload(file);
|
||||||
Map<String, String> map = new HashMap<>(2);
|
Map<String, String> map = new HashMap<>(2);
|
||||||
map.put("url", oss.getUrl());
|
map.put("url", oss.getUrl());
|
||||||
map.put("fileName", oss.getOriginalName());
|
map.put("fileName", oss.getOriginalName());
|
||||||
@ -96,23 +98,7 @@ public class SysOssController extends BaseController {
|
|||||||
@SaCheckPermission("system:oss:download")
|
@SaCheckPermission("system:oss:download")
|
||||||
@GetMapping("/download/{ossId}")
|
@GetMapping("/download/{ossId}")
|
||||||
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
||||||
SysOssVo sysOss = iSysOssService.getById(ossId);
|
iSysOssService.download(ossId,response);
|
||||||
if (ObjectUtil.isNull(sysOss)) {
|
|
||||||
throw new ServiceException("文件数据不存在!");
|
|
||||||
}
|
|
||||||
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
|
||||||
long data;
|
|
||||||
try {
|
|
||||||
data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
|
||||||
} catch (HttpException e) {
|
|
||||||
if (e.getMessage().contains("403")) {
|
|
||||||
throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
|
|
||||||
} else {
|
|
||||||
throw new ServiceException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.setContentLength(Convert.toInt(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,7 +111,7 @@ public class SysOssController extends BaseController {
|
|||||||
@DeleteMapping("/{ossIds}")
|
@DeleteMapping("/{ossIds}")
|
||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ossIds) {
|
@PathVariable Long[] ossIds) {
|
||||||
return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0);
|
return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import com.ruoyi.common.helper.LoginHelper;
|
|||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
||||||
import com.ruoyi.system.domain.SysOss;
|
import com.ruoyi.system.domain.SysOss;
|
||||||
|
import com.ruoyi.system.domain.vo.SysOssVo;
|
||||||
import com.ruoyi.system.service.ISysOssService;
|
import com.ruoyi.system.service.ISysOssService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -115,7 +116,7 @@ public class SysProfileController extends BaseController {
|
|||||||
if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
|
if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
|
||||||
return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
|
return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
|
||||||
}
|
}
|
||||||
SysOss oss = iSysOssService.upload(avatarfile);
|
SysOssVo oss = iSysOssService.upload(avatarfile);
|
||||||
String avatar = oss.getUrl();
|
String avatar = oss.getUrl();
|
||||||
if (userService.updateUserAvatar(getUsername(), avatar)) {
|
if (userService.updateUserAvatar(getUsername(), avatar)) {
|
||||||
ajax.put("imgUrl", avatar);
|
ajax.put("imgUrl", avatar);
|
||||||
|
@ -33,7 +33,7 @@ xxl.job:
|
|||||||
--- # 数据源配置
|
--- # 数据源配置
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
||||||
dynamic:
|
dynamic:
|
||||||
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||||
@ -45,6 +45,7 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
|
type: ${spring.datasource.type}
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||||
@ -54,72 +55,46 @@ spring:
|
|||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
lazy: true
|
lazy: true
|
||||||
|
type: ${spring.datasource.type}
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
url:
|
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
# oracle:
|
# oracle:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: oracle.jdbc.OracleDriver
|
# driverClassName: oracle.jdbc.OracleDriver
|
||||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||||
# username: ROOT
|
# username: ROOT
|
||||||
# password: root
|
# password: root
|
||||||
# druid:
|
# hikari:
|
||||||
# validationQuery: SELECT 1 FROM DUAL
|
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||||
# postgres:
|
# postgres:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: org.postgresql.Driver
|
# driverClassName: org.postgresql.Driver
|
||||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||||
# username: root
|
# username: root
|
||||||
# password: root
|
# password: root
|
||||||
# sqlserver:
|
# sqlserver:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true
|
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||||
# username: SA
|
# username: SA
|
||||||
# password: root
|
# password: root
|
||||||
druid:
|
hikari:
|
||||||
# 初始连接数
|
|
||||||
initialSize: 5
|
|
||||||
# 最小连接池数量
|
|
||||||
minIdle: 10
|
|
||||||
# 最大连接池数量
|
# 最大连接池数量
|
||||||
maxActive: 20
|
maxPoolSize: 20
|
||||||
|
# 最小空闲线程数量
|
||||||
|
minIdle: 10
|
||||||
# 配置获取连接等待超时的时间
|
# 配置获取连接等待超时的时间
|
||||||
maxWait: 60000
|
connectionTimeout: 10000
|
||||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
# 校验超时时间
|
||||||
timeBetweenEvictionRunsMillis: 60000
|
validationTimeout: 5000
|
||||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
# 空闲连接存活最大时间,默认10分钟
|
||||||
minEvictableIdleTimeMillis: 300000
|
idleTimeout: 60000
|
||||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||||
maxEvictableIdleTimeMillis: 900000
|
maxLifetime: 900000
|
||||||
# 配置检测连接是否有效
|
# 连接测试query(配置检测连接是否有效)
|
||||||
validationQuery: SELECT 1
|
connectionTestQuery: SELECT 1
|
||||||
testWhileIdle: true
|
|
||||||
testOnBorrow: false
|
|
||||||
testOnReturn: false
|
|
||||||
# 注意这个值和druid原生不一致,默认启动了stat
|
|
||||||
filters: stat
|
|
||||||
|
|
||||||
--- # druid 配置
|
|
||||||
spring.datasource.druid:
|
|
||||||
webStatFilter:
|
|
||||||
enabled: true
|
|
||||||
statViewServlet:
|
|
||||||
enabled: true
|
|
||||||
# 设置白名单,不填则允许所有访问
|
|
||||||
allow:
|
|
||||||
url-pattern: /druid/*
|
|
||||||
# 控制台管理用户名和密码
|
|
||||||
login-username: ruoyi
|
|
||||||
login-password: 123456
|
|
||||||
filter:
|
|
||||||
stat:
|
|
||||||
enabled: true
|
|
||||||
# 慢SQL记录
|
|
||||||
log-slow-sql: true
|
|
||||||
slow-sql-millis: 1000
|
|
||||||
merge-sql: true
|
|
||||||
wall:
|
|
||||||
config:
|
|
||||||
multi-statement-allow: true
|
|
||||||
|
|
||||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
spring:
|
spring:
|
||||||
|
@ -36,7 +36,7 @@ xxl.job:
|
|||||||
--- # 数据源配置
|
--- # 数据源配置
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
||||||
dynamic:
|
dynamic:
|
||||||
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||||
@ -48,6 +48,7 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
|
type: ${spring.datasource.type}
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||||
@ -57,72 +58,46 @@ spring:
|
|||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
lazy: true
|
lazy: true
|
||||||
|
type: ${spring.datasource.type}
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
url:
|
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
# oracle:
|
# oracle:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: oracle.jdbc.OracleDriver
|
# driverClassName: oracle.jdbc.OracleDriver
|
||||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||||
# username: ROOT
|
# username: ROOT
|
||||||
# password: root
|
# password: root
|
||||||
# druid:
|
# hikari:
|
||||||
# validationQuery: SELECT 1 FROM DUAL
|
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||||
# postgres:
|
# postgres:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: org.postgresql.Driver
|
# driverClassName: org.postgresql.Driver
|
||||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||||
# username: root
|
# username: root
|
||||||
# password: root
|
# password: root
|
||||||
# sqlserver:
|
# sqlserver:
|
||||||
|
# type: ${spring.datasource.type}
|
||||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true
|
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||||
# username: SA
|
# username: SA
|
||||||
# password: root
|
# password: root
|
||||||
druid:
|
hikari:
|
||||||
# 初始连接数
|
|
||||||
initialSize: 5
|
|
||||||
# 最小连接池数量
|
|
||||||
minIdle: 10
|
|
||||||
# 最大连接池数量
|
# 最大连接池数量
|
||||||
maxActive: 20
|
maxPoolSize: 20
|
||||||
|
# 最小空闲线程数量
|
||||||
|
minIdle: 10
|
||||||
# 配置获取连接等待超时的时间
|
# 配置获取连接等待超时的时间
|
||||||
maxWait: 60000
|
connectionTimeout: 10000
|
||||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
# 校验超时时间
|
||||||
timeBetweenEvictionRunsMillis: 60000
|
validationTimeout: 5000
|
||||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
# 空闲连接存活最大时间,默认10分钟
|
||||||
minEvictableIdleTimeMillis: 300000
|
idleTimeout: 60000
|
||||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||||
maxEvictableIdleTimeMillis: 900000
|
maxLifetime: 900000
|
||||||
# 配置检测连接是否有效
|
# 连接测试query(配置检测连接是否有效)
|
||||||
validationQuery: SELECT 1
|
connectionTestQuery: SELECT 1
|
||||||
testWhileIdle: true
|
|
||||||
testOnBorrow: false
|
|
||||||
testOnReturn: false
|
|
||||||
# 注意这个值和druid原生不一致,默认启动了stat
|
|
||||||
filters: stat
|
|
||||||
|
|
||||||
--- # druid 配置
|
|
||||||
spring.datasource.druid:
|
|
||||||
webStatFilter:
|
|
||||||
enabled: true
|
|
||||||
statViewServlet:
|
|
||||||
enabled: true
|
|
||||||
# 设置白名单,不填则允许所有访问
|
|
||||||
allow:
|
|
||||||
url-pattern: /druid/*
|
|
||||||
# 控制台管理用户名和密码
|
|
||||||
login-username: ruoyi
|
|
||||||
login-password: 123456
|
|
||||||
filter:
|
|
||||||
stat:
|
|
||||||
enabled: true
|
|
||||||
# 慢SQL记录
|
|
||||||
log-slow-sql: true
|
|
||||||
slow-sql-millis: 1000
|
|
||||||
merge-sql: true
|
|
||||||
wall:
|
|
||||||
config:
|
|
||||||
multi-statement-allow: true
|
|
||||||
|
|
||||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
spring:
|
spring:
|
||||||
|
@ -83,6 +83,9 @@ spring:
|
|||||||
restart:
|
restart:
|
||||||
# 热部署开关
|
# 热部署开关
|
||||||
enabled: true
|
enabled: true
|
||||||
|
mvc:
|
||||||
|
format:
|
||||||
|
date-time: yyyy-MM-dd HH:mm:ss
|
||||||
jackson:
|
jackson:
|
||||||
# 日期格式化
|
# 日期格式化
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
@ -115,8 +118,6 @@ sa-token:
|
|||||||
token-prefix: "Bearer"
|
token-prefix: "Bearer"
|
||||||
# jwt秘钥
|
# jwt秘钥
|
||||||
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
|
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
|
||||||
# 是否输出操作日志
|
|
||||||
is-log: true
|
|
||||||
|
|
||||||
# security配置
|
# security配置
|
||||||
security:
|
security:
|
||||||
@ -131,8 +132,6 @@ security:
|
|||||||
- /favicon.ico
|
- /favicon.ico
|
||||||
- /*/api-docs
|
- /*/api-docs
|
||||||
- /*/api-docs/**
|
- /*/api-docs/**
|
||||||
# druid 监控配置
|
|
||||||
- /druid/**
|
|
||||||
# actuator 监控配置
|
# actuator 监控配置
|
||||||
- /actuator
|
- /actuator
|
||||||
- /actuator/**
|
- /actuator/**
|
||||||
@ -206,6 +205,9 @@ swagger:
|
|||||||
name: ${sa-token.token-name}
|
name: ${sa-token.token-name}
|
||||||
|
|
||||||
springdoc:
|
springdoc:
|
||||||
|
swagger-ui:
|
||||||
|
# 持久化认证数据
|
||||||
|
persistAuthorization: true
|
||||||
#这里定义了两个分组,可定义多个,也可以不定义
|
#这里定义了两个分组,可定义多个,也可以不定义
|
||||||
group-configs:
|
group-configs:
|
||||||
- group: 1.演示模块
|
- group: 1.演示模块
|
||||||
|
@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试
|
|||||||
rate.limiter.message=访问过于频繁,请稍候再试
|
rate.limiter.message=访问过于频繁,请稍候再试
|
||||||
sms.code.not.blank=短信验证码不能为空
|
sms.code.not.blank=短信验证码不能为空
|
||||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟
|
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
||||||
xcx.code.not.blank=小程序code不能为空
|
xcx.code.not.blank=小程序code不能为空
|
||||||
|
@ -41,5 +41,5 @@ repeat.submit.message=Repeat submit is not allowed, please try again later
|
|||||||
rate.limiter.message=Visit too frequently, please try again later
|
rate.limiter.message=Visit too frequently, please try again later
|
||||||
sms.code.not.blank=Sms code cannot be blank
|
sms.code.not.blank=Sms code cannot be blank
|
||||||
sms.code.retry.limit.count=Sms code input error {0} times
|
sms.code.retry.limit.count=Sms code input error {0} times
|
||||||
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {0} minutes
|
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
|
||||||
xcx.code.not.blank=Mini program code cannot be blank
|
xcx.code.not.blank=Mini program code cannot be blank
|
||||||
|
@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试
|
|||||||
rate.limiter.message=访问过于频繁,请稍候再试
|
rate.limiter.message=访问过于频繁,请稍候再试
|
||||||
sms.code.not.blank=短信验证码不能为空
|
sms.code.not.blank=短信验证码不能为空
|
||||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟
|
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
|
||||||
xcx.code.not.blank=小程序code不能为空
|
xcx.code.not.blank=小程序code不能为空
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<!-- 控制台输出 -->
|
<!-- 控制台输出 -->
|
||||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
|
<encoder>
|
||||||
<pattern>${console.log.pattern}</pattern>
|
<pattern>${console.log.pattern}</pattern>
|
||||||
<charset>utf-8</charset>
|
<charset>utf-8</charset>
|
||||||
</encoder>
|
</encoder>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<!-- 日志最大 1天 -->
|
<!-- 日志最大 1天 -->
|
||||||
<maxHistory>1</maxHistory>
|
<maxHistory>1</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
|
<encoder>
|
||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
<charset>utf-8</charset>
|
<charset>utf-8</charset>
|
||||||
</encoder>
|
</encoder>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
<!-- 日志最大的历史 60天 -->
|
<!-- 日志最大的历史 60天 -->
|
||||||
<maxHistory>60</maxHistory>
|
<maxHistory>60</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
|
<encoder>
|
||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
@ -64,7 +64,7 @@
|
|||||||
<!-- 日志最大的历史 60天 -->
|
<!-- 日志最大的历史 60天 -->
|
||||||
<maxHistory>60</maxHistory>
|
<maxHistory>60</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
|
<encoder>
|
||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
@ -78,7 +78,7 @@
|
|||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- info异步输出 -->
|
<!-- info异步输出 -->
|
||||||
<appender name="async_info" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
|
<appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||||
<discardingThreshold>0</discardingThreshold>
|
<discardingThreshold>0</discardingThreshold>
|
||||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||||
@ -88,7 +88,7 @@
|
|||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- error异步输出 -->
|
<!-- error异步输出 -->
|
||||||
<appender name="async_error" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
|
<appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||||
<discardingThreshold>0</discardingThreshold>
|
<discardingThreshold>0</discardingThreshold>
|
||||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||||
@ -97,12 +97,33 @@
|
|||||||
<appender-ref ref="file_error"/>
|
<appender-ref ref="file_error"/>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
<!-- 整合 skywalking 控制台输出 tid -->
|
||||||
|
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
|
||||||
|
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||||
|
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||||
|
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||||
|
<!-- </layout>-->
|
||||||
|
<!-- <charset>utf-8</charset>-->
|
||||||
|
<!-- </encoder>-->
|
||||||
|
<!-- </appender>-->
|
||||||
|
|
||||||
|
<!-- 整合 skywalking 推送采集日志 -->
|
||||||
|
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
|
||||||
|
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||||
|
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||||
|
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||||
|
<!-- </layout>-->
|
||||||
|
<!-- <charset>utf-8</charset>-->
|
||||||
|
<!-- </encoder>-->
|
||||||
|
<!-- </appender>-->
|
||||||
|
|
||||||
<!--系统操作日志-->
|
<!--系统操作日志-->
|
||||||
<root level="info">
|
<root level="info">
|
||||||
<appender-ref ref="console" />
|
<appender-ref ref="console" />
|
||||||
<appender-ref ref="async_info" />
|
<appender-ref ref="async_info" />
|
||||||
<appender-ref ref="async_error" />
|
<appender-ref ref="async_error" />
|
||||||
<appender-ref ref="file_console" />
|
<appender-ref ref="file_console" />
|
||||||
|
<!-- <appender-ref ref="sky_log"/>-->
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -24,3 +24,5 @@ outagedetection=true
|
|||||||
outagedetectioninterval=2
|
outagedetectioninterval=2
|
||||||
# 是否过滤 Log
|
# 是否过滤 Log
|
||||||
filter=true
|
filter=true
|
||||||
|
# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
|
||||||
|
exclude=SELECT 1
|
||||||
|
45
ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
Normal file
45
ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
70
ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
Normal file
70
ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package com.ruoyi.test;
|
||||||
|
|
||||||
|
import com.ruoyi.common.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
ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
Normal file
72
ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package com.ruoyi.test;
|
||||||
|
|
||||||
|
import com.ruoyi.common.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
ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
Normal file
54
ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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 ==================");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -79,10 +79,6 @@
|
|||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>mybatis-plus-extension</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- dynamic-datasource 多数据源-->
|
<!-- dynamic-datasource 多数据源-->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package com.ruoyi.common.annotation;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaIgnore;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 匿名访问不鉴权注解
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Documented
|
|
||||||
public @interface Anonymous {
|
|
||||||
}
|
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.ruoyi.common.annotation;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.ruoyi.common.jackson.DictDataJsonSerializer;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典数据映射注解
|
||||||
|
*
|
||||||
|
* @author itino
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
@JacksonAnnotationsInside
|
||||||
|
@JsonSerialize(using = DictDataJsonSerializer.class)
|
||||||
|
public @interface DictDataMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置字典的type值 (如: sys_user_sex)
|
||||||
|
*/
|
||||||
|
String dictType() default "";
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.ruoyi.common.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;
|
||||||
|
}
|
@ -2,6 +2,8 @@ package com.ruoyi.common.core.domain;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -23,6 +25,7 @@ public class BaseEntity implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 搜索值
|
* 搜索值
|
||||||
*/
|
*/
|
||||||
|
@JsonIgnore
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String searchValue;
|
private String searchValue;
|
||||||
|
|
||||||
@ -53,6 +56,7 @@ public class BaseEntity implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 请求参数
|
* 请求参数
|
||||||
*/
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private Map<String, Object> params = new HashMap<>();
|
private Map<String, Object> params = new HashMap<>();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.common.core.domain;
|
package com.ruoyi.common.core.domain;
|
||||||
|
|
||||||
|
import com.ruoyi.common.constant.HttpStatus;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@ -67,6 +68,27 @@ public class R<T> implements Serializable {
|
|||||||
return restResult(null, code, 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) {
|
private static <T> R<T> restResult(T data, int code, String msg) {
|
||||||
R<T> r = new R<>();
|
R<T> r = new R<>();
|
||||||
r.setCode(code);
|
r.setCode(code);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.ruoyi.common.core.domain.dto;
|
package com.ruoyi.common.core.domain.dto;
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.ruoyi.common.core.domain.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录事件
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LogininforEvent implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录状态 0成功 1失败
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示消息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求体
|
||||||
|
*/
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他参数
|
||||||
|
*/
|
||||||
|
private Object[] args;
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.ruoyi.common.core.domain.dto;
|
package com.ruoyi.common.core.domain.event;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -6,13 +6,13 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用操作日志实体
|
* 操作日志事件
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class OperLogDTO implements Serializable {
|
public class OperLogEvent implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
@ -4,16 +4,12 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.enums.SqlMethod;
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||||
import com.ruoyi.common.utils.BeanCopyUtils;
|
import com.ruoyi.common.utils.BeanCopyUtils;
|
||||||
import org.apache.ibatis.binding.MapperMethod;
|
|
||||||
import org.apache.ibatis.logging.Log;
|
import org.apache.ibatis.logging.Log;
|
||||||
import org.apache.ibatis.logging.LogFactory;
|
import org.apache.ibatis.logging.LogFactory;
|
||||||
|
|
||||||
@ -21,7 +17,6 @@ import java.io.Serializable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义 Mapper 接口, 实现 自定义扩展
|
* 自定义 Mapper 接口, 实现 自定义扩展
|
||||||
@ -37,8 +32,6 @@ public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
|
|||||||
|
|
||||||
Log log = LogFactory.getLog(BaseMapperPlus.class);
|
Log log = LogFactory.getLog(BaseMapperPlus.class);
|
||||||
|
|
||||||
int DEFAULT_BATCH_SIZE = 1000;
|
|
||||||
|
|
||||||
default Class<V> currentVoClass() {
|
default Class<V> currentVoClass() {
|
||||||
return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);
|
return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);
|
||||||
}
|
}
|
||||||
@ -59,79 +52,49 @@ public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
|
|||||||
* 批量插入
|
* 批量插入
|
||||||
*/
|
*/
|
||||||
default boolean insertBatch(Collection<T> entityList) {
|
default boolean insertBatch(Collection<T> entityList) {
|
||||||
return insertBatch(entityList, DEFAULT_BATCH_SIZE);
|
return Db.saveBatch(entityList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新
|
* 批量更新
|
||||||
*/
|
*/
|
||||||
default boolean updateBatchById(Collection<T> entityList) {
|
default boolean updateBatchById(Collection<T> entityList) {
|
||||||
return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
|
return Db.updateBatchById(entityList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入或更新
|
* 批量插入或更新
|
||||||
*/
|
*/
|
||||||
default boolean insertOrUpdateBatch(Collection<T> entityList) {
|
default boolean insertOrUpdateBatch(Collection<T> entityList) {
|
||||||
return insertOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
|
return Db.saveOrUpdateBatch(entityList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入(包含限制条数)
|
* 批量插入(包含限制条数)
|
||||||
*/
|
*/
|
||||||
default boolean insertBatch(Collection<T> entityList, int batchSize) {
|
default boolean insertBatch(Collection<T> entityList, int batchSize) {
|
||||||
String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.INSERT_ONE);
|
return Db.saveBatch(entityList, batchSize);
|
||||||
return SqlHelper.executeBatch(this.currentModelClass(), log, entityList, batchSize,
|
|
||||||
(sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量更新(包含限制条数)
|
* 批量更新(包含限制条数)
|
||||||
*/
|
*/
|
||||||
default boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
default boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||||
String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.UPDATE_BY_ID);
|
return Db.updateBatchById(entityList, batchSize);
|
||||||
return SqlHelper.executeBatch(this.currentModelClass(), log, entityList, batchSize,
|
|
||||||
(sqlSession, entity) -> {
|
|
||||||
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
|
||||||
param.put(Constants.ENTITY, entity);
|
|
||||||
sqlSession.update(sqlStatement, param);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入或更新(包含限制条数)
|
* 批量插入或更新(包含限制条数)
|
||||||
*/
|
*/
|
||||||
default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
||||||
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.currentModelClass());
|
return Db.saveOrUpdateBatch(entityList, batchSize);
|
||||||
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
|
|
||||||
String keyProperty = tableInfo.getKeyProperty();
|
|
||||||
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
|
|
||||||
return SqlHelper.saveOrUpdateBatch(this.currentModelClass(), this.currentMapperClass(), log, entityList, batchSize, (sqlSession, entity) -> {
|
|
||||||
Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
|
|
||||||
String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.SELECT_BY_ID);
|
|
||||||
return StringUtils.checkValNull(idVal)
|
|
||||||
|| CollectionUtils.isEmpty(sqlSession.selectList(sqlStatement, entity));
|
|
||||||
}, (sqlSession, entity) -> {
|
|
||||||
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
|
||||||
param.put(Constants.ENTITY, entity);
|
|
||||||
String sqlStatement = SqlHelper.getSqlStatement(this.currentMapperClass(), SqlMethod.UPDATE_BY_ID);
|
|
||||||
sqlSession.update(sqlStatement, param);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插入或更新(包含限制条数)
|
* 插入或更新(包含限制条数)
|
||||||
*/
|
*/
|
||||||
default boolean insertOrUpdate(T entity) {
|
default boolean insertOrUpdate(T entity) {
|
||||||
if (null != entity) {
|
return Db.saveOrUpdate(entity);
|
||||||
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.currentModelClass());
|
|
||||||
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
|
|
||||||
String keyProperty = tableInfo.getKeyProperty();
|
|
||||||
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
|
|
||||||
Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
|
|
||||||
return StringUtils.checkValNull(idVal) || Objects.isNull(selectById((Serializable) idVal)) ? insert(entity) > 0 : updateById(entity) > 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default V selectVoById(Serializable id) {
|
default V selectVoById(Serializable id) {
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package com.ruoyi.common.core.service;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用 系统访问日志
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
public interface LogininforService {
|
|
||||||
|
|
||||||
void recordLogininfor(String username, String status, String message,
|
|
||||||
HttpServletRequest request, Object... args);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package com.ruoyi.common.core.service;
|
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.dto.OperLogDTO;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用 操作日志
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
public interface OperLogService {
|
|
||||||
|
|
||||||
@Async
|
|
||||||
void recordOper(OperLogDTO operLogDTO);
|
|
||||||
}
|
|
@ -86,7 +86,7 @@ public class CellMergeStrategy extends AbstractMergeStrategy {
|
|||||||
// 空值跳过不合并
|
// 空值跳过不合并
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cellValue != val) {
|
if (!cellValue.equals(val)) {
|
||||||
if (i - repeatCell.getCurrent() > 1) {
|
if (i - repeatCell.getCurrent() > 1) {
|
||||||
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
|
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import java.io.BufferedReader;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建可重复读取inputStream的request
|
* 构建可重复读取inputStream的request
|
||||||
@ -27,7 +26,7 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
request.setCharacterEncoding(Constants.UTF8);
|
request.setCharacterEncoding(Constants.UTF8);
|
||||||
response.setCharacterEncoding(Constants.UTF8);
|
response.setCharacterEncoding(Constants.UTF8);
|
||||||
|
|
||||||
body = IoUtil.readUtf8(request.getInputStream()).getBytes(StandardCharsets.UTF_8);
|
body = IoUtil.readBytes(request.getInputStream(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.common.filter;
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HtmlUtil;
|
import cn.hutool.http.HtmlUtil;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
@ -32,12 +33,12 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
String[] values = super.getParameterValues(name);
|
String[] values = super.getParameterValues(name);
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
int length = values.length;
|
int length = values.length;
|
||||||
String[] escapseValues = new String[length];
|
String[] escapesValues = new String[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
// 防xss攻击和过滤前后空格
|
// 防xss攻击和过滤前后空格
|
||||||
escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim();
|
escapesValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim();
|
||||||
}
|
}
|
||||||
return escapseValues;
|
return escapesValues;
|
||||||
}
|
}
|
||||||
return super.getParameterValues(name);
|
return super.getParameterValues(name);
|
||||||
}
|
}
|
||||||
@ -50,7 +51,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 为空,直接返回
|
// 为空,直接返回
|
||||||
String json = IoUtil.read(super.getInputStream(), StandardCharsets.UTF_8);
|
String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8);
|
||||||
if (StringUtils.isEmpty(json)) {
|
if (StringUtils.isEmpty(json)) {
|
||||||
return super.getInputStream();
|
return super.getInputStream();
|
||||||
}
|
}
|
||||||
@ -88,7 +89,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是Json请求
|
* 是否是Json请求
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public boolean isJsonRequest() {
|
public boolean isJsonRequest() {
|
||||||
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
|
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
|
||||||
|
@ -2,6 +2,7 @@ package com.ruoyi.common.helper;
|
|||||||
|
|
||||||
import cn.dev33.satoken.context.SaHolder;
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.ruoyi.common.jackson;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.BeanProperty;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||||
|
import com.ruoyi.common.annotation.DictDataMapper;
|
||||||
|
import com.ruoyi.common.core.service.DictService;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典数据json序列化工具
|
||||||
|
*
|
||||||
|
* @author itino
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class DictDataJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
|
||||||
|
|
||||||
|
private String dictType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||||
|
try {
|
||||||
|
DictService dictService = SpringUtils.getBean(DictService.class);
|
||||||
|
if (ObjectUtil.isNotNull(dictService)) {
|
||||||
|
String label = dictService.getDictLabel(dictType, value);
|
||||||
|
gen.writeString(StringUtils.isNotBlank(label) ? label : value);
|
||||||
|
} else {
|
||||||
|
gen.writeString(value);
|
||||||
|
}
|
||||||
|
} catch (BeansException e) {
|
||||||
|
log.error("字典数据未查到, 采用默认处理 => {}", e.getMessage());
|
||||||
|
gen.writeString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
|
||||||
|
DictDataMapper anno = property.getAnnotation(DictDataMapper.class);
|
||||||
|
if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) {
|
||||||
|
this.dictType = anno.dictType();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return prov.findValueSerializer(property.getType(), property);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import org.springframework.web.context.request.RequestAttributes;
|
|||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
@ -19,6 +20,9 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端工具类
|
* 客户端工具类
|
||||||
@ -70,6 +74,31 @@ public class ServletUtils extends ServletUtil {
|
|||||||
return Convert.toBool(getRequest().getParameter(name), 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(), ","));
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取request
|
* 获取request
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,7 @@ import javax.servlet.ServletOutputStream;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -84,7 +85,13 @@ public class ExcelUtil {
|
|||||||
* @param response 响应体
|
* @param response 响应体
|
||||||
*/
|
*/
|
||||||
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
|
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
|
||||||
exportExcel(list, sheetName, clazz, false, response);
|
try {
|
||||||
|
resetResponse(sheetName, response);
|
||||||
|
ServletOutputStream os = response.getOutputStream();
|
||||||
|
exportExcel(list, sheetName, clazz, false, os);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("导出Excel异常");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,23 +107,48 @@ public class ExcelUtil {
|
|||||||
try {
|
try {
|
||||||
resetResponse(sheetName, response);
|
resetResponse(sheetName, response);
|
||||||
ServletOutputStream os = response.getOutputStream();
|
ServletOutputStream os = response.getOutputStream();
|
||||||
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
|
exportExcel(list, sheetName, clazz, merge, os);
|
||||||
.autoCloseStream(false)
|
|
||||||
// 自动适配
|
|
||||||
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
|
|
||||||
// 大数值自动转换 防止失真
|
|
||||||
.registerConverter(new ExcelBigNumberConvert())
|
|
||||||
.sheet(sheetName);
|
|
||||||
if (merge) {
|
|
||||||
// 合并处理器
|
|
||||||
builder.registerWriteHandler(new CellMergeStrategy(list, true));
|
|
||||||
}
|
|
||||||
builder.doWrite(list);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("导出Excel异常");
|
throw new RuntimeException("导出Excel异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出excel
|
||||||
|
*
|
||||||
|
* @param list 导出数据集合
|
||||||
|
* @param sheetName 工作表的名称
|
||||||
|
* @param clazz 实体类
|
||||||
|
* @param os 输出流
|
||||||
|
*/
|
||||||
|
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
|
||||||
|
exportExcel(list, sheetName, clazz, false, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出excel
|
||||||
|
*
|
||||||
|
* @param list 导出数据集合
|
||||||
|
* @param sheetName 工作表的名称
|
||||||
|
* @param clazz 实体类
|
||||||
|
* @param merge 是否合并单元格
|
||||||
|
* @param os 输出流
|
||||||
|
*/
|
||||||
|
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) {
|
||||||
|
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
|
||||||
|
.autoCloseStream(false)
|
||||||
|
// 自动适配
|
||||||
|
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
|
||||||
|
// 大数值自动转换 防止失真
|
||||||
|
.registerConverter(new ExcelBigNumberConvert())
|
||||||
|
.sheet(sheetName);
|
||||||
|
if (merge) {
|
||||||
|
// 合并处理器
|
||||||
|
builder.registerWriteHandler(new CellMergeStrategy(list, true));
|
||||||
|
}
|
||||||
|
builder.doWrite(list);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单表多数据模板导出 模板格式为 {.属性}
|
* 单表多数据模板导出 模板格式为 {.属性}
|
||||||
*
|
*
|
||||||
@ -125,31 +157,46 @@ public class ExcelUtil {
|
|||||||
* 例如: excel/temp.xlsx
|
* 例如: excel/temp.xlsx
|
||||||
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
||||||
* @param data 模板需要的数据
|
* @param data 模板需要的数据
|
||||||
|
* @param response 响应体
|
||||||
*/
|
*/
|
||||||
public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
|
public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
resetResponse(filename, response);
|
resetResponse(filename, response);
|
||||||
ClassPathResource templateResource = new ClassPathResource(templatePath);
|
ServletOutputStream os = response.getOutputStream();
|
||||||
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
|
exportTemplate(data, templatePath, os);
|
||||||
.withTemplate(templateResource.getStream())
|
|
||||||
.autoCloseStream(false)
|
|
||||||
// 大数值自动转换 防止失真
|
|
||||||
.registerConverter(new ExcelBigNumberConvert())
|
|
||||||
.build();
|
|
||||||
WriteSheet writeSheet = EasyExcel.writerSheet().build();
|
|
||||||
if (CollUtil.isEmpty(data)) {
|
|
||||||
throw new IllegalArgumentException("数据为空");
|
|
||||||
}
|
|
||||||
// 单表多数据导出 模板格式为 {.属性}
|
|
||||||
for (Object d : data) {
|
|
||||||
excelWriter.fill(d, writeSheet);
|
|
||||||
}
|
|
||||||
excelWriter.finish();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("导出Excel异常");
|
throw new RuntimeException("导出Excel异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单表多数据模板导出 模板格式为 {.属性}
|
||||||
|
*
|
||||||
|
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
|
||||||
|
* 例如: excel/temp.xlsx
|
||||||
|
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
||||||
|
* @param data 模板需要的数据
|
||||||
|
* @param os 输出流
|
||||||
|
*/
|
||||||
|
public static void exportTemplate(List<Object> data, String templatePath, OutputStream os) {
|
||||||
|
ClassPathResource templateResource = new ClassPathResource(templatePath);
|
||||||
|
ExcelWriter excelWriter = EasyExcel.write(os)
|
||||||
|
.withTemplate(templateResource.getStream())
|
||||||
|
.autoCloseStream(false)
|
||||||
|
// 大数值自动转换 防止失真
|
||||||
|
.registerConverter(new ExcelBigNumberConvert())
|
||||||
|
.build();
|
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build();
|
||||||
|
if (CollUtil.isEmpty(data)) {
|
||||||
|
throw new IllegalArgumentException("数据为空");
|
||||||
|
}
|
||||||
|
// 单表多数据导出 模板格式为 {.属性}
|
||||||
|
for (Object d : data) {
|
||||||
|
excelWriter.fill(d, writeSheet);
|
||||||
|
}
|
||||||
|
excelWriter.finish();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多表多数据模板导出 模板格式为 {key.属性}
|
* 多表多数据模板导出 模板格式为 {key.属性}
|
||||||
*
|
*
|
||||||
@ -158,37 +205,52 @@ public class ExcelUtil {
|
|||||||
* 例如: excel/temp.xlsx
|
* 例如: excel/temp.xlsx
|
||||||
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
||||||
* @param data 模板需要的数据
|
* @param data 模板需要的数据
|
||||||
|
* @param response 响应体
|
||||||
*/
|
*/
|
||||||
public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
|
public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
resetResponse(filename, response);
|
resetResponse(filename, response);
|
||||||
ClassPathResource templateResource = new ClassPathResource(templatePath);
|
ServletOutputStream os = response.getOutputStream();
|
||||||
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
|
exportTemplateMultiList(data, templatePath, os);
|
||||||
.withTemplate(templateResource.getStream())
|
|
||||||
.autoCloseStream(false)
|
|
||||||
// 大数值自动转换 防止失真
|
|
||||||
.registerConverter(new ExcelBigNumberConvert())
|
|
||||||
.build();
|
|
||||||
WriteSheet writeSheet = EasyExcel.writerSheet().build();
|
|
||||||
if (CollUtil.isEmpty(data)) {
|
|
||||||
throw new IllegalArgumentException("数据为空");
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, Object> map : data.entrySet()) {
|
|
||||||
// 设置列表后续还有数据
|
|
||||||
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
|
|
||||||
if (map.getValue() instanceof Collection) {
|
|
||||||
// 多表导出必须使用 FillWrapper
|
|
||||||
excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
|
|
||||||
} else {
|
|
||||||
excelWriter.fill(map.getValue(), writeSheet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
excelWriter.finish();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("导出Excel异常");
|
throw new RuntimeException("导出Excel异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多表多数据模板导出 模板格式为 {key.属性}
|
||||||
|
*
|
||||||
|
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
|
||||||
|
* 例如: excel/temp.xlsx
|
||||||
|
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
|
||||||
|
* @param data 模板需要的数据
|
||||||
|
* @param os 输出流
|
||||||
|
*/
|
||||||
|
public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) {
|
||||||
|
ClassPathResource templateResource = new ClassPathResource(templatePath);
|
||||||
|
ExcelWriter excelWriter = EasyExcel.write(os)
|
||||||
|
.withTemplate(templateResource.getStream())
|
||||||
|
.autoCloseStream(false)
|
||||||
|
// 大数值自动转换 防止失真
|
||||||
|
.registerConverter(new ExcelBigNumberConvert())
|
||||||
|
.build();
|
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build();
|
||||||
|
if (CollUtil.isEmpty(data)) {
|
||||||
|
throw new IllegalArgumentException("数据为空");
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> map : data.entrySet()) {
|
||||||
|
// 设置列表后续还有数据
|
||||||
|
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
|
||||||
|
if (map.getValue() instanceof Collection) {
|
||||||
|
// 多表导出必须使用 FillWrapper
|
||||||
|
excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
|
||||||
|
} else {
|
||||||
|
excelWriter.fill(map.getValue(), writeSheet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
excelWriter.finish();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置响应体
|
* 重置响应体
|
||||||
*/
|
*/
|
||||||
|
@ -4,7 +4,6 @@ import com.ruoyi.common.utils.spring.SpringUtils;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.redisson.api.*;
|
import org.redisson.api.*;
|
||||||
import org.redisson.config.Config;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -27,14 +26,6 @@ public class RedisUtils {
|
|||||||
|
|
||||||
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
|
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
|
||||||
|
|
||||||
public static NameMapper getNameMapper() {
|
|
||||||
Config config = CLIENT.getConfig();
|
|
||||||
if (config.isClusterConfig()) {
|
|
||||||
return config.useClusterServers().getNameMapper();
|
|
||||||
}
|
|
||||||
return config.useSingleServer().getNameMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 限流
|
* 限流
|
||||||
*
|
*
|
||||||
@ -218,6 +209,15 @@ public class RedisUtils {
|
|||||||
batch.execute();
|
batch.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查缓存对象是否存在
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
*/
|
||||||
|
public static boolean isExistsObject(final String key) {
|
||||||
|
return CLIENT.getBucket(key).isExists();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存List数据
|
* 缓存List数据
|
||||||
*
|
*
|
||||||
@ -327,6 +327,17 @@ public class RedisUtils {
|
|||||||
return rMap.getAll(rMap.keySet());
|
return rMap.getAll(rMap.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存Map的key列表
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @return key列表
|
||||||
|
*/
|
||||||
|
public static <T> Set<String> getCacheMapKeySet(final String key) {
|
||||||
|
RMap<String, T> rMap = CLIENT.getMap(key);
|
||||||
|
return rMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 往Hash中存入数据
|
* 往Hash中存入数据
|
||||||
*
|
*
|
||||||
@ -426,8 +437,8 @@ public class RedisUtils {
|
|||||||
* @return 对象列表
|
* @return 对象列表
|
||||||
*/
|
*/
|
||||||
public static Collection<String> keys(final String pattern) {
|
public static Collection<String> keys(final String pattern) {
|
||||||
Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(getNameMapper().map(pattern));
|
Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(pattern);
|
||||||
return stream.map(key -> getNameMapper().unmap(key)).collect(Collectors.toList());
|
return stream.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,7 +447,7 @@ public class RedisUtils {
|
|||||||
* @param pattern 字符串前缀
|
* @param pattern 字符串前缀
|
||||||
*/
|
*/
|
||||||
public static void deleteKeys(final String pattern) {
|
public static void deleteKeys(final String pattern) {
|
||||||
CLIENT.getKeys().deleteByPattern(getNameMapper().map(pattern));
|
CLIENT.getKeys().deleteByPattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -446,6 +457,6 @@ public class RedisUtils {
|
|||||||
*/
|
*/
|
||||||
public static Boolean hasKey(String key) {
|
public static Boolean hasKey(String key) {
|
||||||
RKeys rKeys = CLIENT.getKeys();
|
RKeys rKeys = CLIENT.getKeys();
|
||||||
return rKeys.countExists(getNameMapper().map(key)) > 0;
|
return rKeys.countExists(key) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.ruoyi.common.utils.spring;
|
|||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import org.springframework.aop.framework.AopContext;
|
import org.springframework.aop.framework.AopContext;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,4 +63,12 @@ public final class SpringUtils extends SpringUtil {
|
|||||||
return (T) AopContext.currentProxy();
|
return (T) AopContext.currentProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取spring上下文
|
||||||
|
*/
|
||||||
|
public static ApplicationContext context() {
|
||||||
|
return getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>com.tencentcloudapi</groupId>-->
|
<!-- <groupId>com.tencentcloudapi</groupId>-->
|
||||||
<!-- <artifactId>tencentcloud-sdk-java</artifactId>-->
|
<!-- <artifactId>tencentcloud-sdk-java-sms</artifactId>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -46,7 +46,7 @@ public class TestBatchController extends BaseController {
|
|||||||
testDemo.setValue("测试新增");
|
testDemo.setValue("测试新增");
|
||||||
list.add(testDemo);
|
list.add(testDemo);
|
||||||
}
|
}
|
||||||
return toAjax(testDemoMapper.insertBatch(list) ? 1 : 0);
|
return toAjax(testDemoMapper.insertBatch(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,7 +74,7 @@ public class TestBatchController extends BaseController {
|
|||||||
testDemo.setId(null);
|
testDemo.setId(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toAjax(testDemoMapper.insertOrUpdateBatch(list) ? 1 : 0);
|
return toAjax(testDemoMapper.insertOrUpdateBatch(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,7 +119,7 @@ public class TestDemoController extends BaseController {
|
|||||||
// 使用校验工具对标 @Validated(AddGroup.class) 注解
|
// 使用校验工具对标 @Validated(AddGroup.class) 注解
|
||||||
// 用于在非 Controller 的地方校验对象
|
// 用于在非 Controller 的地方校验对象
|
||||||
ValidatorUtils.validate(bo, AddGroup.class);
|
ValidatorUtils.validate(bo, AddGroup.class);
|
||||||
return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);
|
return toAjax(iTestDemoService.insertByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +130,7 @@ public class TestDemoController extends BaseController {
|
|||||||
@RepeatSubmit
|
@RepeatSubmit
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
|
||||||
return toAjax(iTestDemoService.updateByBo(bo) ? 1 : 0);
|
return toAjax(iTestDemoService.updateByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,6 +143,6 @@ public class TestDemoController extends BaseController {
|
|||||||
@DeleteMapping("/{ids}")
|
@DeleteMapping("/{ids}")
|
||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ids) {
|
@PathVariable Long[] ids) {
|
||||||
return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
|
return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ public class TestTreeController extends BaseController {
|
|||||||
@RepeatSubmit
|
@RepeatSubmit
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
|
||||||
return toAjax(iTestTreeService.insertByBo(bo) ? 1 : 0);
|
return toAjax(iTestTreeService.insertByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +89,7 @@ public class TestTreeController extends BaseController {
|
|||||||
@RepeatSubmit
|
@RepeatSubmit
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
|
||||||
return toAjax(iTestTreeService.updateByBo(bo) ? 1 : 0);
|
return toAjax(iTestTreeService.updateByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,6 +102,6 @@ public class TestTreeController extends BaseController {
|
|||||||
@DeleteMapping("/{ids}")
|
@DeleteMapping("/{ids}")
|
||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ids) {
|
@PathVariable Long[] ids) {
|
||||||
return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
|
return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.ruoyi.demo.controller.queue;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体类 注意不允许使用内部类 否则会找不到类
|
* 实体类 注意不允许使用内部类 否则会找不到类
|
||||||
@ -17,7 +16,7 @@ public class PriorityDemo implements Comparable<PriorityDemo> {
|
|||||||
private Integer orderNum;
|
private Integer orderNum;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull PriorityDemo other) {
|
public int compareTo(PriorityDemo other) {
|
||||||
return Integer.compare(getOrderNum(), other.getOrderNum());
|
return Integer.compare(getOrderNum(), other.getOrderNum());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
|
@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
|
|||||||
|
|
||||||
MAINTAINER Lion Li
|
MAINTAINER Lion Li
|
||||||
|
|
||||||
RUN mkdir -p /ruoyi/monitor
|
|
||||||
RUN mkdir -p /ruoyi/monitor/logs
|
RUN mkdir -p /ruoyi/monitor/logs
|
||||||
|
|
||||||
WORKDIR /ruoyi/monitor
|
WORKDIR /ruoyi/monitor
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
|
|||||||
|
|
||||||
MAINTAINER Lion Li
|
MAINTAINER Lion Li
|
||||||
|
|
||||||
RUN mkdir -p /ruoyi/xxljob
|
|
||||||
RUN mkdir -p /ruoyi/xxljob/logs
|
RUN mkdir -p /ruoyi/xxljob/logs
|
||||||
|
|
||||||
WORKDIR /ruoyi/xxljob
|
WORKDIR /ruoyi/xxljob
|
||||||
@ -14,4 +13,4 @@ EXPOSE 9100
|
|||||||
|
|
||||||
ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar
|
ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar
|
||||||
|
|
||||||
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
|
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>ruoyi-xxl-job-admin</artifactId>
|
<artifactId>ruoyi-xxl-job-admin</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@ -64,8 +64,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<!-- mysql -->
|
<!-- mysql -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -40,12 +40,6 @@
|
|||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里数据库连接池 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba</groupId>
|
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- sql性能分析插件 -->
|
<!-- sql性能分析插件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>p6spy</groupId>
|
<groupId>p6spy</groupId>
|
||||||
@ -62,17 +56,17 @@
|
|||||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 系统模块-->
|
<!-- 系统模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.yomahub</groupId>
|
|
||||||
<artifactId>tlog-web-spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -4,8 +4,7 @@ import cn.hutool.core.lang.Dict;
|
|||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.domain.dto.OperLogDTO;
|
import com.ruoyi.common.core.domain.event.OperLogEvent;
|
||||||
import com.ruoyi.common.core.service.OperLogService;
|
|
||||||
import com.ruoyi.common.enums.BusinessStatus;
|
import com.ruoyi.common.enums.BusinessStatus;
|
||||||
import com.ruoyi.common.enums.HttpMethod;
|
import com.ruoyi.common.enums.HttpMethod;
|
||||||
import com.ruoyi.common.helper.LoginHelper;
|
import com.ruoyi.common.helper.LoginHelper;
|
||||||
@ -21,7 +20,6 @@ import org.aspectj.lang.annotation.Aspect;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.HandlerMapping;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@ -68,7 +66,7 @@ public class LogAspect {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
// *========数据库日志=========*//
|
// *========数据库日志=========*//
|
||||||
OperLogDTO operLog = new OperLogDTO();
|
OperLogEvent operLog = new OperLogEvent();
|
||||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||||
// 请求的地址
|
// 请求的地址
|
||||||
String ip = ServletUtils.getClientIP();
|
String ip = ServletUtils.getClientIP();
|
||||||
@ -88,11 +86,10 @@ public class LogAspect {
|
|||||||
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||||
// 处理设置注解上的参数
|
// 处理设置注解上的参数
|
||||||
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
||||||
// 保存数据库
|
// 发布事件保存数据库
|
||||||
SpringUtils.getBean(OperLogService.class).recordOper(operLog);
|
SpringUtils.context().publishEvent(operLog);
|
||||||
} catch (Exception exp) {
|
} catch (Exception exp) {
|
||||||
// 记录本地异常日志
|
// 记录本地异常日志
|
||||||
log.error("==前置通知异常==");
|
|
||||||
log.error("异常信息:{}", exp.getMessage());
|
log.error("异常信息:{}", exp.getMessage());
|
||||||
exp.printStackTrace();
|
exp.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -105,7 +102,7 @@ public class LogAspect {
|
|||||||
* @param operLog 操作日志
|
* @param operLog 操作日志
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogDTO operLog, Object jsonResult) throws Exception {
|
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception {
|
||||||
// 设置action动作
|
// 设置action动作
|
||||||
operLog.setBusinessType(log.businessType().ordinal());
|
operLog.setBusinessType(log.businessType().ordinal());
|
||||||
// 设置标题
|
// 设置标题
|
||||||
@ -129,14 +126,15 @@ public class LogAspect {
|
|||||||
* @param operLog 操作日志
|
* @param operLog 操作日志
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
private void setRequestValue(JoinPoint joinPoint, OperLogDTO operLog) throws Exception {
|
private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception {
|
||||||
String requestMethod = operLog.getRequestMethod();
|
String requestMethod = operLog.getRequestMethod();
|
||||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||||
String params = argsArrayToString(joinPoint.getArgs());
|
String params = argsArrayToString(joinPoint.getArgs());
|
||||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||||
} else {
|
} else {
|
||||||
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||||
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
|
MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES);
|
||||||
|
operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@EnableAsync
|
@EnableAsync(proxyTargetClass = true)
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AsyncConfig extends AsyncConfigurerSupport {
|
public class AsyncConfig extends AsyncConfigurerSupport {
|
||||||
|
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
package com.ruoyi.framework.config;
|
|
||||||
|
|
||||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
|
||||||
import com.alibaba.druid.util.Utils;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import javax.servlet.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* druid 配置多数据源
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class DruidConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 去除监控页面底部的广告
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
|
|
||||||
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
|
|
||||||
// 获取web监控页面的参数
|
|
||||||
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
|
|
||||||
// 提取common.js的配置路径
|
|
||||||
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
|
|
||||||
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
|
|
||||||
final String filePath = "support/http/resources/js/common.js";
|
|
||||||
// 创建filter进行过滤
|
|
||||||
Filter filter = new Filter() {
|
|
||||||
@Override
|
|
||||||
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
// 重置缓冲区,响应头不会被重置
|
|
||||||
// response.resetBuffer();
|
|
||||||
// 获取common.js
|
|
||||||
String text = Utils.readFromResource(filePath);
|
|
||||||
// 正则替换banner, 除去底部的广告信息
|
|
||||||
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
|
|
||||||
text = text.replaceAll("powered.*?shrek.wang</a>", "");
|
|
||||||
response.getWriter().write(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
|
||||||
registrationBean.setFilter(filter);
|
|
||||||
registrationBean.addUrlPatterns(commonJsPattern);
|
|
||||||
return registrationBean;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,6 @@ import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -25,7 +24,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
@EnableConfigurationProperties(RedissonProperties.class)
|
@EnableConfigurationProperties(RedissonProperties.class)
|
||||||
public class RedisConfig extends CachingConfigurerSupport {
|
public class RedisConfig {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedissonProperties redissonProperties;
|
private RedissonProperties redissonProperties;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
|
import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
|
||||||
import com.yomahub.tlog.web.interceptor.TLogWebInterceptor;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.CacheControl;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
@ -22,8 +20,6 @@ public class ResourcesConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
// 全局链路跟踪拦截器
|
|
||||||
registry.addInterceptor(new TLogWebInterceptor());
|
|
||||||
// 全局访问性能拦截
|
// 全局访问性能拦截
|
||||||
registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
|
registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
|
|||||||
import cn.dev33.satoken.router.SaRouter;
|
import cn.dev33.satoken.router.SaRouter;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
|
||||||
import com.ruoyi.framework.config.properties.ExcludeUrlProperties;
|
|
||||||
import com.ruoyi.framework.config.properties.SecurityProperties;
|
import com.ruoyi.framework.config.properties.SecurityProperties;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -34,14 +32,10 @@ public class SaTokenConfig implements WebMvcConfigurer {
|
|||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
// 注册路由拦截器,自定义验证规则
|
// 注册路由拦截器,自定义验证规则
|
||||||
registry.addInterceptor(new SaInterceptor(handler -> {
|
registry.addInterceptor(new SaInterceptor(handler -> {
|
||||||
// 自定义注解 @Anonymous 匿名访问配置,后续版本将删除
|
|
||||||
ExcludeUrlProperties excludeUrlProperties = SpringUtils.getBean(ExcludeUrlProperties.class);
|
|
||||||
// 登录验证 -- 排除多个路径
|
// 登录验证 -- 排除多个路径
|
||||||
SaRouter
|
SaRouter
|
||||||
// 获取所有的
|
// 获取所有的
|
||||||
.match("/**")
|
.match("/**")
|
||||||
// 排除下不需要拦截的(每次匹配)
|
|
||||||
.notMatch(excludeUrlProperties.getExcludes())
|
|
||||||
// 对未排除的路径进行检查
|
// 对未排除的路径进行检查
|
||||||
.check(() -> {
|
.check(() -> {
|
||||||
// 检查是否登录 是否有token
|
// 检查是否登录 是否有token
|
||||||
|
@ -23,6 +23,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger 文档配置
|
* Swagger 文档配置
|
||||||
@ -51,8 +52,11 @@ public class SwaggerConfig {
|
|||||||
openApi.tags(swaggerProperties.getTags());
|
openApi.tags(swaggerProperties.getTags());
|
||||||
openApi.paths(swaggerProperties.getPaths());
|
openApi.paths(swaggerProperties.getPaths());
|
||||||
openApi.components(swaggerProperties.getComponents());
|
openApi.components(swaggerProperties.getComponents());
|
||||||
|
Set<String> keySet = swaggerProperties.getComponents().getSecuritySchemes().keySet();
|
||||||
List<SecurityRequirement> list = new ArrayList<>();
|
List<SecurityRequirement> list = new ArrayList<>();
|
||||||
list.add(new SecurityRequirement().addList("apikey"));
|
SecurityRequirement securityRequirement = new SecurityRequirement();
|
||||||
|
keySet.forEach(securityRequirement::addList);
|
||||||
|
list.add(securityRequirement);
|
||||||
openApi.security(list);
|
openApi.security(list);
|
||||||
|
|
||||||
return openApi;
|
return openApi;
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package com.ruoyi.framework.config;
|
|
||||||
|
|
||||||
import com.yomahub.tlog.springboot.TLogWebAutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 整合 TLog 框架配置
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
* @since 3.3.0
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
// 排除 web 自动配置 自定义实现
|
|
||||||
@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class)
|
|
||||||
public class TLogConfig {
|
|
||||||
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package com.ruoyi.framework.config.properties;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaIgnore;
|
|
||||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
|
||||||
import cn.hutool.core.util.ReUtil;
|
|
||||||
import com.ruoyi.common.annotation.Anonymous;
|
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
|
||||||
import org.springframework.web.util.pattern.PathPattern;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置注解允许匿名访问的url
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
* @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替,
|
|
||||||
* 底层过滤方法详见 {@link SaInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Lazy
|
|
||||||
@Component
|
|
||||||
public class ExcludeUrlProperties implements InitializingBean {
|
|
||||||
|
|
||||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final List<String> excludes = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
String asterisk = "*";
|
|
||||||
RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
|
|
||||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
|
||||||
|
|
||||||
map.keySet().forEach(info -> {
|
|
||||||
HandlerMethod handlerMethod = map.get(info);
|
|
||||||
|
|
||||||
// 获取方法上边的注解 替代path variable 为 *
|
|
||||||
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
|
|
||||||
Optional.ofNullable(method).ifPresent(anonymous -> {
|
|
||||||
Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns();
|
|
||||||
patterns.forEach(url -> {
|
|
||||||
excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取类上边的注解, 替代path variable 为 *
|
|
||||||
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
|
|
||||||
Optional.ofNullable(controller).ifPresent(anonymous -> {
|
|
||||||
Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns();
|
|
||||||
patterns.forEach(url -> {
|
|
||||||
excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -54,7 +54,7 @@ public class PlusDataPermissionHandler {
|
|||||||
/**
|
/**
|
||||||
* 无效注解方法缓存用于快速返回
|
* 无效注解方法缓存用于快速返回
|
||||||
*/
|
*/
|
||||||
private final Set<String> inavlidCacheSet = new ConcurrentHashSet<>();
|
private final Set<String> invalidCacheSet = new ConcurrentHashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spel 解析器
|
* spel 解析器
|
||||||
@ -70,7 +70,7 @@ public class PlusDataPermissionHandler {
|
|||||||
public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
|
public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
|
||||||
DataColumn[] dataColumns = findAnnotation(mappedStatementId);
|
DataColumn[] dataColumns = findAnnotation(mappedStatementId);
|
||||||
if (ArrayUtil.isEmpty(dataColumns)) {
|
if (ArrayUtil.isEmpty(dataColumns)) {
|
||||||
inavlidCacheSet.add(mappedStatementId);
|
invalidCacheSet.add(mappedStatementId);
|
||||||
return where;
|
return where;
|
||||||
}
|
}
|
||||||
LoginUser currentUser = DataPermissionHelper.getVariable("user");
|
LoginUser currentUser = DataPermissionHelper.getVariable("user");
|
||||||
@ -194,6 +194,6 @@ public class PlusDataPermissionHandler {
|
|||||||
* 是否为无效方法 无数据权限
|
* 是否为无效方法 无数据权限
|
||||||
*/
|
*/
|
||||||
public boolean isInvalid(String mappedStatementId) {
|
public boolean isInvalid(String mappedStatementId) {
|
||||||
return inavlidCacheSet.contains(mappedStatementId);
|
return invalidCacheSet.contains(mappedStatementId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,20 @@ public class UserActionListener implements SaTokenListener {
|
|||||||
public void doUntieDisable(String loginType, Object loginId, String service) {
|
public void doUntieDisable(String loginType, Object loginId, String service) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次打开二级认证时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每次创建Session时触发
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doCloseSafe(String loginType, String tokenValue, String service) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每次创建Session时触发
|
* 每次创建Session时触发
|
||||||
*/
|
*/
|
||||||
|
@ -105,7 +105,7 @@ public class GlobalExceptionHandler {
|
|||||||
public R<Void> handleServiceException(ServiceException e, HttpServletRequest request) {
|
public R<Void> handleServiceException(ServiceException e, HttpServletRequest request) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
Integer code = e.getCode();
|
Integer code = e.getCode();
|
||||||
return ObjectUtil.isNotNull(code) ? R.fail(code.intValue(), e.getMessage()) : R.fail(e.getMessage());
|
return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "gen")
|
@ConfigurationProperties(prefix = "gen")
|
||||||
@PropertySource(value = {"classpath:generator.yml"})
|
@PropertySource(value = {"classpath:generator.yml"}, encoding = "UTF-8")
|
||||||
public class GenConfig {
|
public class GenConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,12 +3,11 @@ package com.ruoyi.generator.service;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.lang.Dict;
|
import cn.hutool.core.lang.Dict;
|
||||||
import cn.hutool.core.lang.Snowflake;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
@ -58,6 +57,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
|
|
||||||
private final GenTableMapper baseMapper;
|
private final GenTableMapper baseMapper;
|
||||||
private final GenTableColumnMapper genTableColumnMapper;
|
private final GenTableColumnMapper genTableColumnMapper;
|
||||||
|
private final IdentifierGenerator identifierGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询业务字段列表
|
* 查询业务字段列表
|
||||||
@ -205,10 +205,9 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
Map<String, String> dataMap = new LinkedHashMap<>();
|
Map<String, String> dataMap = new LinkedHashMap<>();
|
||||||
// 查询表信息
|
// 查询表信息
|
||||||
GenTable table = baseMapper.selectGenTableById(tableId);
|
GenTable table = baseMapper.selectGenTableById(tableId);
|
||||||
Snowflake snowflake = IdUtil.getSnowflake();
|
|
||||||
List<Long> menuIds = new ArrayList<>();
|
List<Long> menuIds = new ArrayList<>();
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
menuIds.add(snowflake.nextId());
|
menuIds.add(identifierGenerator.nextId(null).longValue());
|
||||||
}
|
}
|
||||||
table.setMenuIds(menuIds);
|
table.setMenuIds(menuIds);
|
||||||
// 设置主子表信息
|
// 设置主子表信息
|
||||||
@ -356,10 +355,9 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
private void generatorCode(String tableName, ZipOutputStream zip) {
|
private void generatorCode(String tableName, ZipOutputStream zip) {
|
||||||
// 查询表信息
|
// 查询表信息
|
||||||
GenTable table = baseMapper.selectGenTableByName(tableName);
|
GenTable table = baseMapper.selectGenTableByName(tableName);
|
||||||
Snowflake snowflake = IdUtil.getSnowflake();
|
|
||||||
List<Long> menuIds = new ArrayList<>();
|
List<Long> menuIds = new ArrayList<>();
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
menuIds.add(snowflake.nextId());
|
menuIds.add(identifierGenerator.nextId(null).longValue());
|
||||||
}
|
}
|
||||||
table.setMenuIds(menuIds);
|
table.setMenuIds(menuIds);
|
||||||
// 设置主子表信息
|
// 设置主子表信息
|
||||||
|
@ -89,7 +89,7 @@ public class ${ClassName}Controller extends BaseController {
|
|||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
|
||||||
return toAjax(i${ClassName}Service.insertByBo(bo) ? 1 : 0);
|
return toAjax(i${ClassName}Service.insertByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,7 +100,7 @@ public class ${ClassName}Controller extends BaseController {
|
|||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
|
||||||
return toAjax(i${ClassName}Service.updateByBo(bo) ? 1 : 0);
|
return toAjax(i${ClassName}Service.updateByBo(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,6 +113,6 @@ public class ${ClassName}Controller extends BaseController {
|
|||||||
@DeleteMapping("/{${pkColumn.javaField}s}")
|
@DeleteMapping("/{${pkColumn.javaField}s}")
|
||||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
|
@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
|
||||||
return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true) ? 1 : 0);
|
return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,11 +186,11 @@
|
|||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
@ -204,8 +204,11 @@
|
|||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -216,7 +219,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
@ -227,24 +230,27 @@
|
|||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@ -335,7 +341,7 @@ export default {
|
|||||||
#set($comment=$column.columnComment)
|
#set($comment=$column.columnComment)
|
||||||
#end
|
#end
|
||||||
$column.javaField: [
|
$column.javaField: [
|
||||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
]#if($foreach.count != $columns.size()),#end
|
]#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@ -398,10 +404,7 @@ export default {
|
|||||||
reset() {
|
reset() {
|
||||||
this.form = {
|
this.form = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "radio")
|
#if($column.htmlType == "checkbox")
|
||||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
|
|
||||||
|
|
||||||
#elseif($column.htmlType == "checkbox")
|
|
||||||
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
#else
|
#else
|
||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
|
@ -133,9 +133,9 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
#elseif($column.list && $column.htmlType == "imageUpload")
|
#elseif($column.list && $column.htmlType == "imageUpload")
|
||||||
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
|
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
|
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
||||||
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||||
@ -197,11 +197,11 @@
|
|||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
@ -215,8 +215,11 @@
|
|||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -227,7 +230,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
@ -238,24 +241,27 @@
|
|||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in dict.type.${dictType}"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@ -412,7 +418,7 @@ export default {
|
|||||||
#set($comment=$column.columnComment)
|
#set($comment=$column.columnComment)
|
||||||
#end
|
#end
|
||||||
$column.javaField: [
|
$column.javaField: [
|
||||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
]#if($foreach.count != $columns.size()),#end
|
]#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@ -456,9 +462,7 @@ export default {
|
|||||||
reset() {
|
reset() {
|
||||||
this.form = {
|
this.form = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "radio")
|
#if($column.htmlType == "checkbox")
|
||||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
|
|
||||||
#elseif($column.htmlType == "checkbox")
|
|
||||||
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
#else
|
#else
|
||||||
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
||||||
|
@ -135,26 +135,11 @@
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
|
||||||
type="text"
|
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
|
||||||
icon="Edit"
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
|
||||||
@click="handleUpdate(scope.row)"
|
</template>
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
|
||||||
>修改</el-button>
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
icon="Plus"
|
|
||||||
@click="handleAdd(scope.row)"
|
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
|
||||||
>新增</el-button>
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
icon="Delete"
|
|
||||||
@click="handleDelete(scope.row)"
|
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
|
||||||
>删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
@ -187,11 +172,11 @@
|
|||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
@ -205,8 +190,11 @@
|
|||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -217,7 +205,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
@ -228,24 +216,27 @@
|
|||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@ -321,7 +312,7 @@ const data = reactive({
|
|||||||
#set($comment=$column.columnComment)
|
#set($comment=$column.columnComment)
|
||||||
#end
|
#end
|
||||||
$column.javaField: [
|
$column.javaField: [
|
||||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
]#if($foreach.count != $columns.size()),#end
|
]#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@ -374,10 +365,7 @@ function cancel() {
|
|||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "radio")
|
#if($column.htmlType == "checkbox")
|
||||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
|
|
||||||
|
|
||||||
#elseif($column.htmlType == "checkbox")
|
|
||||||
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
#else
|
#else
|
||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
|
@ -147,20 +147,10 @@
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
|
||||||
type="text"
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
|
||||||
icon="Edit"
|
</template>
|
||||||
@click="handleUpdate(scope.row)"
|
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
|
||||||
>修改</el-button>
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
icon="Delete"
|
|
||||||
@click="handleDelete(scope.row)"
|
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
|
||||||
>删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
@ -190,11 +180,11 @@
|
|||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
@ -208,8 +198,11 @@
|
|||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -220,7 +213,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
@ -231,24 +224,27 @@
|
|||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in ${dictType}"
|
v-for="dict in ${dictType}"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@ -397,7 +393,7 @@ const data = reactive({
|
|||||||
#set($comment=$column.columnComment)
|
#set($comment=$column.columnComment)
|
||||||
#end
|
#end
|
||||||
$column.javaField: [
|
$column.javaField: [
|
||||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
]#if($foreach.count != $columns.size()),#end
|
]#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@ -441,9 +437,7 @@ function cancel() {
|
|||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "radio")
|
#if($column.htmlType == "checkbox")
|
||||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
|
|
||||||
#elseif($column.htmlType == "checkbox")
|
|
||||||
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
#else
|
#else
|
||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@ -29,11 +29,6 @@
|
|||||||
<artifactId>xxl-job-core</artifactId>
|
<artifactId>xxl-job-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.yomahub</groupId>
|
|
||||||
<artifactId>tlog-xxljob-spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -12,7 +12,6 @@ import java.io.InputStreamReader;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XxlJob开发示例(Bean模式)
|
* XxlJob开发示例(Bean模式)
|
||||||
@ -39,7 +38,6 @@ public class SampleService {
|
|||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
XxlJobHelper.log("beat at:" + i);
|
XxlJobHelper.log("beat at:" + i);
|
||||||
TimeUnit.SECONDS.sleep(2);
|
|
||||||
}
|
}
|
||||||
// default success
|
// default success
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public interface OssConstant {
|
|||||||
/**
|
/**
|
||||||
* 云服务商
|
* 云服务商
|
||||||
*/
|
*/
|
||||||
String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu"};
|
String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https 状态
|
* https 状态
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.ruoyi.oss.core;
|
package com.ruoyi.oss.core;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import com.amazonaws.ClientConfiguration;
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.HttpMethod;
|
||||||
import com.amazonaws.Protocol;
|
import com.amazonaws.Protocol;
|
||||||
import com.amazonaws.auth.AWSCredentials;
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||||
@ -16,12 +18,15 @@ import com.ruoyi.common.utils.DateUtils;
|
|||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.oss.constant.OssConstant;
|
import com.ruoyi.oss.constant.OssConstant;
|
||||||
import com.ruoyi.oss.entity.UploadResult;
|
import com.ruoyi.oss.entity.UploadResult;
|
||||||
|
import com.ruoyi.oss.enumd.AccessPolicyType;
|
||||||
import com.ruoyi.oss.enumd.PolicyType;
|
import com.ruoyi.oss.enumd.PolicyType;
|
||||||
import com.ruoyi.oss.exception.OssException;
|
import com.ruoyi.oss.exception.OssException;
|
||||||
import com.ruoyi.oss.properties.OssProperties;
|
import com.ruoyi.oss.properties.OssProperties;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* S3 存储协议 所有兼容S3协议的云厂商均支持
|
* S3 存储协议 所有兼容S3协议的云厂商均支持
|
||||||
@ -57,7 +62,7 @@ public class OssClient {
|
|||||||
.withClientConfiguration(clientConfig)
|
.withClientConfiguration(clientConfig)
|
||||||
.withCredentials(credentialsProvider)
|
.withCredentials(credentialsProvider)
|
||||||
.disableChunkedEncoding();
|
.disableChunkedEncoding();
|
||||||
if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)){
|
if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) {
|
||||||
// minio 使用https限制使用域名访问 需要此配置 站点填域名
|
// minio 使用https限制使用域名访问 需要此配置 站点填域名
|
||||||
build.enablePathStyleAccess();
|
build.enablePathStyleAccess();
|
||||||
}
|
}
|
||||||
@ -79,9 +84,10 @@ public class OssClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
|
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
|
||||||
createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
|
AccessPolicyType accessPolicy = getAccessPolicy();
|
||||||
|
createBucketRequest.setCannedAcl(accessPolicy.getAcl());
|
||||||
client.createBucket(createBucketRequest);
|
client.createBucket(createBucketRequest);
|
||||||
client.setBucketPolicy(bucketName, getPolicy(bucketName, PolicyType.READ));
|
client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType()));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]");
|
throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]");
|
||||||
}
|
}
|
||||||
@ -92,13 +98,16 @@ public class OssClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
||||||
|
if (!(inputStream instanceof ByteArrayInputStream)) {
|
||||||
|
inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
ObjectMetadata metadata = new ObjectMetadata();
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
metadata.setContentType(contentType);
|
metadata.setContentType(contentType);
|
||||||
metadata.setContentLength(inputStream.available());
|
metadata.setContentLength(inputStream.available());
|
||||||
PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata);
|
PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata);
|
||||||
// 设置上传对象的 Acl 为公共读
|
// 设置上传对象的 Acl 为公共读
|
||||||
putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
|
putObjectRequest.setCannedAcl(getAccessPolicy().getAcl());
|
||||||
client.putObject(putObjectRequest);
|
client.putObject(putObjectRequest);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
|
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
|
||||||
@ -111,7 +120,7 @@ public class OssClient {
|
|||||||
try {
|
try {
|
||||||
client.deleteObject(properties.getBucketName(), path);
|
client.deleteObject(properties.getBucketName(), path);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
|
throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,16 +138,23 @@ public class OssClient {
|
|||||||
* @param path 完整文件路径
|
* @param path 完整文件路径
|
||||||
*/
|
*/
|
||||||
public ObjectMetadata getObjectMetadata(String path) {
|
public ObjectMetadata getObjectMetadata(String path) {
|
||||||
|
path = path.replace(getUrl() + "/", "");
|
||||||
S3Object object = client.getObject(properties.getBucketName(), path);
|
S3Object object = client.getObject(properties.getBucketName(), path);
|
||||||
return object.getObjectMetadata();
|
return object.getObjectMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InputStream getObjectContent(String path) {
|
||||||
|
path = path.replace(getUrl() + "/", "");
|
||||||
|
S3Object object = client.getObject(properties.getBucketName(), path);
|
||||||
|
return object.getObjectContent();
|
||||||
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
String domain = properties.getDomain();
|
String domain = properties.getDomain();
|
||||||
String endpoint = properties.getEndpoint();
|
String endpoint = properties.getEndpoint();
|
||||||
String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://";
|
String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://";
|
||||||
// 云服务商直接返回
|
// 云服务商直接返回
|
||||||
if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)){
|
if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) {
|
||||||
if (StringUtils.isNotBlank(domain)) {
|
if (StringUtils.isNotBlank(domain)) {
|
||||||
return header + domain;
|
return header + domain;
|
||||||
}
|
}
|
||||||
@ -167,6 +183,24 @@ public class OssClient {
|
|||||||
return configKey;
|
return configKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPrivateUrl(String objectKey, Integer second) {
|
||||||
|
GeneratePresignedUrlRequest generatePresignedUrlRequest =
|
||||||
|
new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
|
||||||
|
.withMethod(HttpMethod.GET)
|
||||||
|
.withExpiration(new Date(System.currentTimeMillis() + 1000L * second));
|
||||||
|
URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前桶权限类型
|
||||||
|
*
|
||||||
|
* @return 当前桶权限类型code
|
||||||
|
*/
|
||||||
|
public AccessPolicyType getAccessPolicy() {
|
||||||
|
return AccessPolicyType.getByType(properties.getAccessPolicy());
|
||||||
|
}
|
||||||
|
|
||||||
private static String getPolicy(String bucketName, PolicyType policyType) {
|
private static String getPolicy(String bucketName, PolicyType policyType) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n");
|
builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n");
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.ruoyi.oss.enumd;
|
||||||
|
|
||||||
|
import com.amazonaws.services.s3.model.CannedAccessControlList;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶访问策略配置
|
||||||
|
*
|
||||||
|
* @author 陈賝
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum AccessPolicyType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* private
|
||||||
|
*/
|
||||||
|
PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public
|
||||||
|
*/
|
||||||
|
PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* custom
|
||||||
|
*/
|
||||||
|
CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶 权限类型
|
||||||
|
*/
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件对象 权限类型
|
||||||
|
*/
|
||||||
|
private final CannedAccessControlList acl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶策略类型
|
||||||
|
*/
|
||||||
|
private final PolicyType policyType;
|
||||||
|
|
||||||
|
public static AccessPolicyType getByType(String type) {
|
||||||
|
for (AccessPolicyType value : values()) {
|
||||||
|
if (value.getType().equals(type)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("'type' not found By " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -50,4 +50,9 @@ public class OssProperties {
|
|||||||
*/
|
*/
|
||||||
private String isHttps;
|
private String isHttps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶权限类型(0private 1public 2custom)
|
||||||
|
*/
|
||||||
|
private String accessPolicy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.tencentcloudapi</groupId>
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>4.3.1</version>
|
<version>4.5.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -82,4 +82,8 @@ public class SysOssConfig extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶权限类型(0private 1public 2custom)
|
||||||
|
*/
|
||||||
|
private String accessPolicy;
|
||||||
}
|
}
|
||||||
|
@ -98,4 +98,10 @@ public class SysOssConfigBo extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶权限类型(0private 1public 2custom)
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||||
|
private String accessPolicy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -82,4 +82,9 @@ public class SysOssConfigVo {
|
|||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶权限类型(0private 1public 2custom)
|
||||||
|
*/
|
||||||
|
private String accessPolicy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import com.ruoyi.system.domain.bo.SysOssBo;
|
|||||||
import com.ruoyi.system.domain.vo.SysOssVo;
|
import com.ruoyi.system.domain.vo.SysOssVo;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -23,7 +25,9 @@ public interface ISysOssService {
|
|||||||
|
|
||||||
SysOssVo getById(Long ossId);
|
SysOssVo getById(Long ossId);
|
||||||
|
|
||||||
SysOss upload(MultipartFile file);
|
SysOssVo upload(MultipartFile file);
|
||||||
|
|
||||||
|
void download(Long ossId, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
@ -5,23 +5,28 @@ import cn.dev33.satoken.secure.BCrypt;
|
|||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.core.domain.event.LogininforEvent;
|
||||||
import com.ruoyi.common.core.domain.dto.RoleDTO;
|
import com.ruoyi.common.core.domain.dto.RoleDTO;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.core.domain.model.XcxLoginUser;
|
import com.ruoyi.common.core.domain.model.XcxLoginUser;
|
||||||
import com.ruoyi.common.core.service.LogininforService;
|
|
||||||
import com.ruoyi.common.enums.DeviceType;
|
import com.ruoyi.common.enums.DeviceType;
|
||||||
import com.ruoyi.common.enums.LoginType;
|
import com.ruoyi.common.enums.LoginType;
|
||||||
import com.ruoyi.common.enums.UserStatus;
|
import com.ruoyi.common.enums.UserStatus;
|
||||||
import com.ruoyi.common.exception.user.*;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
|
import com.ruoyi.common.exception.user.UserException;
|
||||||
import com.ruoyi.common.helper.LoginHelper;
|
import com.ruoyi.common.helper.LoginHelper;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.MessageUtils;
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.redis.RedisUtils;
|
import com.ruoyi.common.utils.redis.RedisUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.system.mapper.SysUserMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -42,9 +47,8 @@ import java.util.function.Supplier;
|
|||||||
@Service
|
@Service
|
||||||
public class SysLoginService {
|
public class SysLoginService {
|
||||||
|
|
||||||
private final ISysUserService userService;
|
private final SysUserMapper userMapper;
|
||||||
private final ISysConfigService configService;
|
private final ISysConfigService configService;
|
||||||
private final LogininforService asyncService;
|
|
||||||
private final SysPermissionService permissionService;
|
private final SysPermissionService permissionService;
|
||||||
|
|
||||||
@Value("${user.password.maxRetryCount}")
|
@Value("${user.password.maxRetryCount}")
|
||||||
@ -76,7 +80,7 @@ public class SysLoginService {
|
|||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.PC);
|
LoginHelper.loginByDevice(loginUser, DeviceType.PC);
|
||||||
|
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId(), username);
|
recordLoginInfo(user.getUserId(), username);
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
@ -85,21 +89,19 @@ public class SysLoginService {
|
|||||||
// 通过手机号查找用户
|
// 通过手机号查找用户
|
||||||
SysUser user = loadUserByPhonenumber(phonenumber);
|
SysUser user = loadUserByPhonenumber(phonenumber);
|
||||||
|
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
|
||||||
checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode, request));
|
|
||||||
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
// 此处可根据登录用户的数据不同 自行创建 loginUser
|
||||||
LoginUser loginUser = buildLoginUser(user);
|
LoginUser loginUser = buildLoginUser(user);
|
||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
|
LoginHelper.loginByDevice(loginUser, DeviceType.APP);
|
||||||
|
|
||||||
asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId(), user.getUserName());
|
recordLoginInfo(user.getUserId(), user.getUserName());
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String xcxLogin(String xcxCode) {
|
public String xcxLogin(String xcxCode) {
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
|
||||||
// xcxCode 为 小程序调用 wx.login 授权后获取
|
// xcxCode 为 小程序调用 wx.login 授权后获取
|
||||||
// todo 以下自行实现
|
// todo 以下自行实现
|
||||||
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
|
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
|
||||||
@ -115,7 +117,7 @@ public class SysLoginService {
|
|||||||
// 生成token
|
// 生成token
|
||||||
LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
|
LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
|
||||||
|
|
||||||
asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||||
recordLoginInfo(user.getUserId(), user.getUserName());
|
recordLoginInfo(user.getUserId(), user.getUserName());
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
}
|
}
|
||||||
@ -127,18 +129,35 @@ public class SysLoginService {
|
|||||||
try {
|
try {
|
||||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||||
StpUtil.logout();
|
StpUtil.logout();
|
||||||
asyncService.recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest());
|
recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||||
} catch (NotLoginException e) {
|
} catch (NotLoginException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void recordLogininfor(String username, String status, String message) {
|
||||||
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setUsername(username);
|
||||||
|
logininforEvent.setStatus(status);
|
||||||
|
logininforEvent.setMessage(message);
|
||||||
|
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||||
|
SpringUtils.context().publishEvent(logininforEvent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验短信验证码
|
* 校验短信验证码
|
||||||
*/
|
*/
|
||||||
private boolean validateSmsCode(String phonenumber, String smsCode, HttpServletRequest request) {
|
private boolean validateSmsCode(String phonenumber, String smsCode) {
|
||||||
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
|
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
|
||||||
if (StringUtils.isBlank(code)) {
|
if (StringUtils.isBlank(code)) {
|
||||||
asyncService.recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
|
recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
return code.equals(smsCode);
|
return code.equals(smsCode);
|
||||||
@ -156,43 +175,41 @@ public class SysLoginService {
|
|||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
|
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha)) {
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request);
|
recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysUser loadUserByUsername(String username) {
|
private SysUser loadUserByUsername(String username) {
|
||||||
SysUser user = userService.selectUserByUserName(username);
|
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||||
|
.select(SysUser::getUserName, SysUser::getStatus)
|
||||||
|
.eq(SysUser::getUserName, username));
|
||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
log.info("登录用户:{} 不存在.", username);
|
log.info("登录用户:{} 不存在.", username);
|
||||||
throw new UserException("user.not.exists", username);
|
throw new UserException("user.not.exists", username);
|
||||||
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
|
||||||
log.info("登录用户:{} 已被删除.", username);
|
|
||||||
throw new UserException("user.password.delete", username);
|
|
||||||
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||||
log.info("登录用户:{} 已被停用.", username);
|
log.info("登录用户:{} 已被停用.", username);
|
||||||
throw new UserException("user.blocked", username);
|
throw new UserException("user.blocked", username);
|
||||||
}
|
}
|
||||||
return user;
|
return userMapper.selectUserByUserName(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysUser loadUserByPhonenumber(String phonenumber) {
|
private SysUser loadUserByPhonenumber(String phonenumber) {
|
||||||
SysUser user = userService.selectUserByPhonenumber(phonenumber);
|
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||||
|
.select(SysUser::getPhonenumber, SysUser::getStatus)
|
||||||
|
.eq(SysUser::getPhonenumber, phonenumber));
|
||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
log.info("登录用户:{} 不存在.", phonenumber);
|
log.info("登录用户:{} 不存在.", phonenumber);
|
||||||
throw new UserException("user.not.exists", phonenumber);
|
throw new UserException("user.not.exists", phonenumber);
|
||||||
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
|
||||||
log.info("登录用户:{} 已被删除.", phonenumber);
|
|
||||||
throw new UserException("user.password.delete", phonenumber);
|
|
||||||
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||||
log.info("登录用户:{} 已被停用.", phonenumber);
|
log.info("登录用户:{} 已被停用.", phonenumber);
|
||||||
throw new UserException("user.blocked", phonenumber);
|
throw new UserException("user.blocked", phonenumber);
|
||||||
}
|
}
|
||||||
return user;
|
return userMapper.selectUserByPhonenumber(phonenumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SysUser loadUserByOpenid(String openid) {
|
private SysUser loadUserByOpenid(String openid) {
|
||||||
@ -202,9 +219,6 @@ public class SysLoginService {
|
|||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
log.info("登录用户:{} 不存在.", openid);
|
log.info("登录用户:{} 不存在.", openid);
|
||||||
// todo 用户不存在 业务逻辑自行实现
|
// todo 用户不存在 业务逻辑自行实现
|
||||||
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
|
||||||
log.info("登录用户:{} 已被删除.", openid);
|
|
||||||
// todo 用户已被删除 业务逻辑自行实现
|
|
||||||
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||||
log.info("登录用户:{} 已被停用.", openid);
|
log.info("登录用户:{} 已被停用.", openid);
|
||||||
// todo 用户已被停用 业务逻辑自行实现
|
// todo 用户已被停用 业务逻辑自行实现
|
||||||
@ -240,14 +254,13 @@ public class SysLoginService {
|
|||||||
sysUser.setLoginIp(ServletUtils.getClientIP());
|
sysUser.setLoginIp(ServletUtils.getClientIP());
|
||||||
sysUser.setLoginDate(DateUtils.getNowDate());
|
sysUser.setLoginDate(DateUtils.getNowDate());
|
||||||
sysUser.setUpdateBy(username);
|
sysUser.setUpdateBy(username);
|
||||||
userService.updateUserProfile(sysUser);
|
userMapper.updateById(sysUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录校验
|
* 登录校验
|
||||||
*/
|
*/
|
||||||
private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
|
private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
|
||||||
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
|
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
|
||||||
String loginFail = Constants.LOGIN_FAIL;
|
String loginFail = Constants.LOGIN_FAIL;
|
||||||
|
|
||||||
@ -255,7 +268,7 @@ public class SysLoginService {
|
|||||||
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
|
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
|
||||||
// 锁定时间内登录 则踢出
|
// 锁定时间内登录 则踢出
|
||||||
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
|
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
|
||||||
asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request);
|
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,12 +278,12 @@ public class SysLoginService {
|
|||||||
// 达到规定错误次数 则锁定登录
|
// 达到规定错误次数 则锁定登录
|
||||||
if (errorNumber.equals(maxRetryCount)) {
|
if (errorNumber.equals(maxRetryCount)) {
|
||||||
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
||||||
asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request);
|
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||||
} else {
|
} else {
|
||||||
// 未达到规定错误次数 则递增
|
// 未达到规定错误次数 则递增
|
||||||
RedisUtils.setCacheObject(errorKey, errorNumber);
|
RedisUtils.setCacheObject(errorKey, errorNumber);
|
||||||
asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber), request);
|
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
|
||||||
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import cn.dev33.satoken.secure.BCrypt;
|
|||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
|
import com.ruoyi.common.core.domain.event.LogininforEvent;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||||
import com.ruoyi.common.core.service.LogininforService;
|
|
||||||
import com.ruoyi.common.enums.UserType;
|
import com.ruoyi.common.enums.UserType;
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
@ -15,6 +15,7 @@ import com.ruoyi.common.utils.MessageUtils;
|
|||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.redis.RedisUtils;
|
import com.ruoyi.common.utils.redis.RedisUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -31,7 +32,6 @@ public class SysRegisterService {
|
|||||||
|
|
||||||
private final ISysUserService userService;
|
private final ISysUserService userService;
|
||||||
private final ISysConfigService configService;
|
private final ISysConfigService configService;
|
||||||
private final LogininforService asyncService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册
|
* 注册
|
||||||
@ -61,7 +61,7 @@ public class SysRegisterService {
|
|||||||
if (!regFlag) {
|
if (!regFlag) {
|
||||||
throw new UserException("user.register.error");
|
throw new UserException("user.register.error");
|
||||||
}
|
}
|
||||||
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"), request);
|
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,12 +77,30 @@ public class SysRegisterService {
|
|||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"), request);
|
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha)) {
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"), request);
|
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void recordLogininfor(String username, String status, String message) {
|
||||||
|
LogininforEvent logininforEvent = new LogininforEvent();
|
||||||
|
logininforEvent.setUsername(username);
|
||||||
|
logininforEvent.setStatus(status);
|
||||||
|
logininforEvent.setMessage(message);
|
||||||
|
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||||
|
SpringUtils.context().publishEvent(logininforEvent);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,10 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
|
|||||||
public String updateConfig(SysConfig config) {
|
public String updateConfig(SysConfig config) {
|
||||||
int row = 0;
|
int row = 0;
|
||||||
if (config.getConfigId() != null) {
|
if (config.getConfigId() != null) {
|
||||||
|
SysConfig temp = baseMapper.selectById(config.getConfigId());
|
||||||
|
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
|
||||||
|
CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey());
|
||||||
|
}
|
||||||
row = baseMapper.updateById(config);
|
row = baseMapper.updateById(config);
|
||||||
} else {
|
} else {
|
||||||
row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
|
row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.ruoyi.system.service.impl;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.CacheNames;
|
import com.ruoyi.common.constant.CacheNames;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.PageQuery;
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
@ -27,6 +29,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字典 业务层处理
|
* 字典 业务层处理
|
||||||
@ -231,28 +234,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
|
|||||||
* @param separator 分隔符
|
* @param separator 分隔符
|
||||||
* @return 字典标签
|
* @return 字典标签
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked cast")
|
||||||
@Override
|
@Override
|
||||||
public String getDictLabel(String dictType, String dictValue, String separator) {
|
public String getDictLabel(String dictType, String dictValue, String separator) {
|
||||||
StringBuilder propertyString = new StringBuilder();
|
// 优先从本地缓存获取
|
||||||
List<SysDictData> datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||||
|
if (ObjectUtil.isNull(datas)) {
|
||||||
if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) {
|
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||||
for (SysDictData dict : datas) {
|
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||||
for (String value : dictValue.split(separator)) {
|
}
|
||||||
if (value.equals(dict.getDictValue())) {
|
|
||||||
propertyString.append(dict.getDictLabel() + separator);
|
Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel);
|
||||||
break;
|
if (StringUtils.containsAny(dictValue, separator)) {
|
||||||
}
|
return Arrays.stream(dictValue.split(separator))
|
||||||
}
|
.map(v -> map.getOrDefault(v, StringUtils.EMPTY))
|
||||||
}
|
.collect(Collectors.joining(separator));
|
||||||
} else {
|
} else {
|
||||||
for (SysDictData dict : datas) {
|
return map.getOrDefault(dictValue, StringUtils.EMPTY);
|
||||||
if (dictValue.equals(dict.getDictValue())) {
|
|
||||||
return dict.getDictLabel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,28 +262,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
|
|||||||
* @param separator 分隔符
|
* @param separator 分隔符
|
||||||
* @return 字典值
|
* @return 字典值
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked cast")
|
||||||
@Override
|
@Override
|
||||||
public String getDictValue(String dictType, String dictLabel, String separator) {
|
public String getDictValue(String dictType, String dictLabel, String separator) {
|
||||||
StringBuilder propertyString = new StringBuilder();
|
// 优先从本地缓存获取
|
||||||
List<SysDictData> datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||||
|
if (ObjectUtil.isNull(datas)) {
|
||||||
if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) {
|
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||||
for (SysDictData dict : datas) {
|
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||||
for (String label : dictLabel.split(separator)) {
|
}
|
||||||
if (label.equals(dict.getDictLabel())) {
|
|
||||||
propertyString.append(dict.getDictValue() + separator);
|
Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue);
|
||||||
break;
|
if (StringUtils.containsAny(dictLabel, separator)) {
|
||||||
}
|
return Arrays.stream(dictLabel.split(separator))
|
||||||
}
|
.map(l -> map.getOrDefault(l, StringUtils.EMPTY))
|
||||||
}
|
.collect(Collectors.joining(separator));
|
||||||
} else {
|
} else {
|
||||||
for (SysDictData dict : datas) {
|
return map.getOrDefault(dictLabel, StringUtils.EMPTY);
|
||||||
if (dictLabel.equals(dict.getDictLabel())) {
|
|
||||||
return dict.getDictValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.PageQuery;
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
|
import com.ruoyi.common.core.domain.event.LogininforEvent;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.service.LogininforService;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
@ -16,6 +16,7 @@ import com.ruoyi.system.mapper.SysLogininforMapper;
|
|||||||
import com.ruoyi.system.service.ISysLogininforService;
|
import com.ruoyi.system.service.ISysLogininforService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -33,22 +34,19 @@ import java.util.Map;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class SysLogininforServiceImpl implements ISysLogininforService, LogininforService {
|
public class SysLogininforServiceImpl implements ISysLogininforService {
|
||||||
|
|
||||||
private final SysLogininforMapper baseMapper;
|
private final SysLogininforMapper baseMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param logininforEvent 登录事件
|
||||||
* @param status 状态
|
|
||||||
* @param message 消息
|
|
||||||
* @param args 列表
|
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
@Override
|
@EventListener
|
||||||
public void recordLogininfor(final String username, final String status, final String message,
|
public void recordLogininfor(LogininforEvent logininforEvent) {
|
||||||
HttpServletRequest request, final Object... args) {
|
HttpServletRequest request = logininforEvent.getRequest();
|
||||||
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||||
final String ip = ServletUtils.getClientIP(request);
|
final String ip = ServletUtils.getClientIP(request);
|
||||||
|
|
||||||
@ -56,27 +54,27 @@ public class SysLogininforServiceImpl implements ISysLogininforService, Logininf
|
|||||||
StringBuilder s = new StringBuilder();
|
StringBuilder s = new StringBuilder();
|
||||||
s.append(getBlock(ip));
|
s.append(getBlock(ip));
|
||||||
s.append(address);
|
s.append(address);
|
||||||
s.append(getBlock(username));
|
s.append(getBlock(logininforEvent.getUsername()));
|
||||||
s.append(getBlock(status));
|
s.append(getBlock(logininforEvent.getStatus()));
|
||||||
s.append(getBlock(message));
|
s.append(getBlock(logininforEvent.getMessage()));
|
||||||
// 打印信息到日志
|
// 打印信息到日志
|
||||||
log.info(s.toString(), args);
|
log.info(s.toString(), logininforEvent.getArgs());
|
||||||
// 获取客户端操作系统
|
// 获取客户端操作系统
|
||||||
String os = userAgent.getOs().getName();
|
String os = userAgent.getOs().getName();
|
||||||
// 获取客户端浏览器
|
// 获取客户端浏览器
|
||||||
String browser = userAgent.getBrowser().getName();
|
String browser = userAgent.getBrowser().getName();
|
||||||
// 封装对象
|
// 封装对象
|
||||||
SysLogininfor logininfor = new SysLogininfor();
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
logininfor.setUserName(username);
|
logininfor.setUserName(logininforEvent.getUsername());
|
||||||
logininfor.setIpaddr(ip);
|
logininfor.setIpaddr(ip);
|
||||||
logininfor.setLoginLocation(address);
|
logininfor.setLoginLocation(address);
|
||||||
logininfor.setBrowser(browser);
|
logininfor.setBrowser(browser);
|
||||||
logininfor.setOs(os);
|
logininfor.setOs(os);
|
||||||
logininfor.setMsg(message);
|
logininfor.setMsg(logininforEvent.getMessage());
|
||||||
// 日志状态
|
// 日志状态
|
||||||
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
|
if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
|
||||||
logininfor.setStatus(Constants.SUCCESS);
|
logininfor.setStatus(Constants.SUCCESS);
|
||||||
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
} else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) {
|
||||||
logininfor.setStatus(Constants.FAIL);
|
logininfor.setStatus(Constants.FAIL);
|
||||||
}
|
}
|
||||||
// 插入数据
|
// 插入数据
|
||||||
|
@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.helper.LoginHelper;
|
import com.ruoyi.common.helper.LoginHelper;
|
||||||
|
import com.ruoyi.common.utils.StreamUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.TreeBuildUtils;
|
import com.ruoyi.common.utils.TreeBuildUtils;
|
||||||
import com.ruoyi.system.domain.SysRoleMenu;
|
import com.ruoyi.system.domain.SysRoleMenu;
|
||||||
@ -425,13 +426,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
|||||||
* 得到子节点列表
|
* 得到子节点列表
|
||||||
*/
|
*/
|
||||||
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
|
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
|
||||||
List<SysMenu> tlist = new ArrayList<SysMenu>();
|
return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
|
||||||
for (SysMenu n : list) {
|
|
||||||
if (n.getParentId().longValue() == t.getMenuId().longValue()) {
|
|
||||||
tlist.add(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tlist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user