mirror of
https://gitee.com/y_project/RuoYi-Vue.git
synced 2025-12-08 06:52:29 +08:00
Compare commits
375 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 170cfb356c | |||
| 5879c2484a | |||
| c02dad2ca3 | |||
| 1bfa14e3c6 | |||
| 5dec58e7f5 | |||
| 8321f92d2c | |||
| da1095e298 | |||
| f56da498ab | |||
| e259093e01 | |||
| e963a86b15 | |||
| e447fb806b | |||
| 90c41d498c | |||
| ce6bea4ba0 | |||
| 9c7901f526 | |||
| 04f5a93aa8 | |||
| 751ca90690 | |||
| 1dfeae6a03 | |||
| 1ed60c79c0 | |||
| aee1e53140 | |||
| 253e2b2de1 | |||
| b1413f021e | |||
| 60c22b6a43 | |||
| 3f05ed6ffa | |||
| 090ad5323a | |||
| 3e90fd010d | |||
| 462862ba65 | |||
| 7601a72faf | |||
| 7ab14ff293 | |||
| 200106df39 | |||
| ea66e20282 | |||
| a209b39552 | |||
| 557672ba9f | |||
| a3116cd27d | |||
| 2ace3257f9 | |||
| c16ee7fc2c | |||
| fd33fe869d | |||
| b7446f8d0f | |||
| 19924cd184 | |||
| 85470a1549 | |||
| 2a604c0548 | |||
| b7f3c68eca | |||
| edd2981076 | |||
| c105a63c8b | |||
| 01fef0b9e1 | |||
| af9cfb40a4 | |||
| 6fa3bfe051 | |||
| 5e64a93d11 | |||
| 4aabf5d8be | |||
| cf6254a8d5 | |||
| 883cff5de9 | |||
| 7e79c4f249 | |||
| 504638eb41 | |||
| 2adac4a899 | |||
| 56a943bf48 | |||
| 77ebca264a | |||
| 7b94ae3a9a | |||
| bd1edc6dcc | |||
| 09d166e97d | |||
| f3e5d908d6 | |||
| 9651a7d7fc | |||
| b2914cbcb1 | |||
| d0a4d6b111 | |||
| b431703262 | |||
| 99726be9ac | |||
| 32f333a00e | |||
| be5c19b764 | |||
| dd384e4a31 | |||
| bdde195e2b | |||
| 14ea071306 | |||
| 50034301ac | |||
| 85ed712c50 | |||
| f67d682345 | |||
| 3f1427eef9 | |||
| 7d0f5e94ef | |||
| 62081aebb9 | |||
| 3f07632cd4 | |||
| 2c94587263 | |||
| 2575c17f47 | |||
| b6f13c546b | |||
| e60a69b670 | |||
| cb18eec802 | |||
| bef080c60a | |||
| de73cf300b | |||
| cbcee86d2c | |||
| cc50224d90 | |||
| ff09e1cf55 | |||
| fe2ccbdc1b | |||
| c8df1f5e1f | |||
| e71c00e6fa | |||
| dcb9839596 | |||
| f13b6d92d2 | |||
| 6595c68df1 | |||
| 5a2a0c09b6 | |||
| 9aac65ff32 | |||
| 5f2350569a | |||
| ccf05b697d | |||
| 6810243ab7 | |||
| b56b8846d9 | |||
| 8e1e4cd8fe | |||
| 9fa5c79713 | |||
| 40a72c2b7e | |||
| 6fe9a358b7 | |||
| 9f6bc13e64 | |||
| ba5ab4b091 | |||
| 17407d0127 | |||
| 30f330f4a0 | |||
| 6ca7870393 | |||
| 2a7342ec43 | |||
| fc57e91b80 | |||
| 347f36ceff | |||
| 9b9c1b999f | |||
| ec627704b2 | |||
| 9e6b2a1265 | |||
| 266a5e844f | |||
| 0822680158 | |||
| 090e258bf9 | |||
| 505fa06dc3 | |||
| 6cf53bfacb | |||
| 881dc3fcf0 | |||
| b65c8d4512 | |||
| 67371a9028 | |||
| 01b545e4ab | |||
| c2e9200626 | |||
| 9502203bbe | |||
| c0f1569ad9 | |||
| 61432480c8 | |||
| 78deee063d | |||
| 4ad003649e | |||
| 616f5a6aca | |||
| fea3ff7b2a | |||
| f938a24df0 | |||
| 45fa686a64 | |||
| 0d8c3b4940 | |||
| 64e807f27b | |||
| 9a384a2fc2 | |||
| 339b932a3d | |||
| 0b5c7f4c96 | |||
| 265e3010aa | |||
| b7a36bfe8a | |||
| 3a51c53823 | |||
| df504c5c14 | |||
| baeed2e8d3 | |||
| 2903de1561 | |||
| cca2f5c62d | |||
| ce54416e4f | |||
| bd19892aff | |||
| 14a859899c | |||
| f3cb18c836 | |||
| 7d0eb3b8c7 | |||
| 654aa6b30c | |||
| b7cdd10f9f | |||
| 9bd35cb7be | |||
| 7a86c714fc | |||
| edd090a098 | |||
| 3cd886785b | |||
| ae5a0f9774 | |||
| 074b3c735d | |||
| a118738d0f | |||
| 56fa3912ae | |||
| 2116ee1822 | |||
| 57a2eb4217 | |||
| 647af5b485 | |||
| 3f33219134 | |||
| a04bb71777 | |||
| 63992ac906 | |||
| 0187344798 | |||
| a9c6ba12e6 | |||
| ba068eae65 | |||
| 1a87ee7c19 | |||
| 3c4b01ab83 | |||
| 886ce995af | |||
| 52264b6e2a | |||
| fd7e88a518 | |||
| 854a6f805f | |||
| 1caec85f46 | |||
| c86dc20743 | |||
| ecc7a8be46 | |||
| e23ad20186 | |||
| 6cf2a8edeb | |||
| 67198aede9 | |||
| 4f33da2a3f | |||
| 8988d0b4ab | |||
| ceefa20aa2 | |||
| 89e1f2a53f | |||
| 6800a12014 | |||
| e8f63b2994 | |||
| ecfe7006e2 | |||
| 9e387dc447 | |||
| 231bbf6928 | |||
| d6eac2dc8d | |||
| b368ad764f | |||
| ffd5f0ce5d | |||
| a50beae599 | |||
| cf7f51a633 | |||
| 4d46f4c1b5 | |||
| a941c1b488 | |||
| d6b6151aea | |||
| fbc071a573 | |||
| 6cfff90b4a | |||
| 474cca921e | |||
| 1657e06be6 | |||
| c01eeb8521 | |||
| f90899d72a | |||
| 7e78a9167f | |||
| 563e11d9c1 | |||
| ef92ad4d8c | |||
| d8b006c15f | |||
| 0e2b97a886 | |||
| 1c7a5faae8 | |||
| 23868c4fad | |||
| 3b2669d148 | |||
| 1147ea5f8a | |||
| a1bf5aaf8e | |||
| 2797c1eb3a | |||
| 1791d7cf40 | |||
| 01861f0aae | |||
| a69cc94f35 | |||
| c666faed66 | |||
| 6072239a40 | |||
| a3b86d6f6d | |||
| fd831d5a90 | |||
| e83412b9a5 | |||
| 90ac416e02 | |||
| 5b63f0cab9 | |||
| 8f145bba3a | |||
| 6bb166b89f | |||
| 823e95667e | |||
| 566053da0c | |||
| 0ef007240d | |||
| 0a75dcdd85 | |||
| 4c2626ffec | |||
| 082b19e33a | |||
| b779cf053d | |||
| 212012dc62 | |||
| 7de2cf77b4 | |||
| 2b9d46439f | |||
| 79265d59b7 | |||
| 093ba5b389 | |||
| 3807b11290 | |||
| c9f25cb34e | |||
| 203b54e5aa | |||
| 403f5c5dcf | |||
| c6d0b9a9ae | |||
| 08df2c93a9 | |||
| fbbdd94999 | |||
| 0cae7d0058 | |||
| b0965653bf | |||
| e472f62523 | |||
| 69256940df | |||
| b9f686be53 | |||
| 521ff51238 | |||
| f67c97e095 | |||
| dd721ff894 | |||
| ae4290bdda | |||
| c19fec2cf8 | |||
| 669c42795a | |||
| 0d79f10c2f | |||
| d3595cd930 | |||
| 5b0525d05c | |||
| fb07677c32 | |||
| a82a3d9465 | |||
| 28bceda630 | |||
| 69829827fe | |||
| 89607fb028 | |||
| 1aa18c523d | |||
| abeb8d7fd8 | |||
| 478fae0d28 | |||
| 0ecf27f8d6 | |||
| 0a5bb34fbf | |||
| 9e38c7de2e | |||
| 9ca28d6dbf | |||
| 497f98ba90 | |||
| a948affb2d | |||
| 57b49dd5fa | |||
| 9c0ed9c424 | |||
| 70ab18052c | |||
| aeb02c79d8 | |||
| 33793d8eff | |||
| 9652906954 | |||
| 9fccc7de40 | |||
| 599be64fa8 | |||
| 50ac363682 | |||
| f84b157419 | |||
| f4536d5d2e | |||
| aed958b1be | |||
| 0a51f7d743 | |||
| 3fd9147afb | |||
| 4f86b6d9ca | |||
| a65c287075 | |||
| 1af0d1665c | |||
| 4e32788b36 | |||
| 068c3e6f0d | |||
| dd6640086e | |||
| be54188ba6 | |||
| a4e2339f90 | |||
| bf771ae5c8 | |||
| fa5596bb20 | |||
| eb30fc4b1a | |||
| 0446d211df | |||
| da146c2a70 | |||
| 7de5358dcd | |||
| 549c7ee97a | |||
| 5fcf342f5a | |||
| c89722a7dd | |||
| 61e10f2783 | |||
| c6912ca1d5 | |||
| 5c4f0c5503 | |||
| 4f7702b22a | |||
| 04e294b3e5 | |||
| d596d5bb8e | |||
| 8f9f0c04cc | |||
| 1bad003fe3 | |||
| ad4df6245d | |||
| 0070297fe1 | |||
| 71ec44a545 | |||
| 1efae4a588 | |||
| 650359c357 | |||
| a78211ca00 | |||
| 74f52677be | |||
| 60d5c03e65 | |||
| 5b04f388e9 | |||
| a7eb07c7a0 | |||
| d0b315f4a5 | |||
| a6051d4638 | |||
| c4ee9ea7c8 | |||
| 7c39f92538 | |||
| 51fa66f61a | |||
| 3b61ed56b0 | |||
| db904f679e | |||
| 98982515f7 | |||
| 1a7baa0639 | |||
| a9695d1756 | |||
| d78f642201 | |||
| 26dfee2ce8 | |||
| b56898858d | |||
| 503dd64e3f | |||
| 876ecf21c7 | |||
| 107672419e | |||
| 21d07c1d71 | |||
| d8d636fdbd | |||
| 743fce7829 | |||
| de2ac66f0b | |||
| 8b5d254242 | |||
| a7eb0f98ac | |||
| 4dcf737db0 | |||
| b32d0724b7 | |||
| 8deacb702e | |||
| 5be8d46d05 | |||
| fb19dd3e4e | |||
| cbf4795fd5 | |||
| 5d74ed32bd | |||
| 6afaced3cf | |||
| f3976c0792 | |||
| 22225a5119 | |||
| fe030cc022 | |||
| ca657b0482 | |||
| c1d1ace36d | |||
| 6e7d7aba93 | |||
| 388e36ed4d | |||
| 5d89d0b36a | |||
| 55095a50b5 | |||
| ee4b4de7b1 | |||
| 92c6301285 | |||
| 5c6adb25fc | |||
| 8dd3ca5bb6 | |||
| be778ba370 | |||
| 52d48fa63e | |||
| df3ef54b41 | |||
| 1e40e60dbf | |||
| 133a10ecf2 | |||
| 6a84ae42a5 | |||
| b2d79b62d1 | |||
| a09a342f58 | |||
| 3e1bd8e3bc | |||
| 8a076e175f |
3
.gitignore
vendored
3
.gitignore
vendored
@ -37,7 +37,8 @@ nbdist/
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
||||
!*/build/*.xml
|
||||
|
||||
36
README.md
36
README.md
@ -1,14 +1,17 @@
|
||||
## 平台简介
|
||||
|
||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||
|
||||
* 前端采用Vue、Element UI。
|
||||
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
||||
* 权限认证使用Jwt,支持多终端认证系统。
|
||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
||||
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
||||
* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
|
||||
* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
||||
* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
||||
* 特别鸣谢:[element](https://github.com/ElemeFE/element),[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://github.com/elunez/eladmin-web)。
|
||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
||||
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
||||
|
||||
## 内置功能
|
||||
|
||||
@ -27,8 +30,9 @@
|
||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||
16. 缓存监控:对系统的缓存信息查询,命令统计等。
|
||||
17. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||
|
||||
## 在线体验
|
||||
|
||||
@ -46,36 +50,36 @@
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## 若依前后端分离交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) 点击按钮入群。
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) 点击按钮入群。
|
||||
130
pom.xml
130
pom.xml
@ -6,166 +6,198 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>3.0.0</ruoyi.version>
|
||||
<ruoyi.version>3.6.0</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<mybatis.boot.version>1.3.2</mybatis.boot.version>
|
||||
<druid.version>1.1.14</druid.version>
|
||||
<bitwalker.version>1.19</bitwalker.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.70</fastjson.version>
|
||||
<oshi.version>3.9.1</oshi.version>
|
||||
<commons.io.version>2.5</commons.io.version>
|
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<druid.version>1.2.6</druid.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
<swagger.version>3.0.0</swagger.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version>
|
||||
<pagehelper.boot.version>1.3.1</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.76</fastjson.version>
|
||||
<oshi.version>5.7.4</oshi.version>
|
||||
<jna.version>5.8.0</jna.version>
|
||||
<commons.io.version>2.10.0</commons.io.version>
|
||||
<commons.fileupload.version>1.4</commons.fileupload.version>
|
||||
<commons.collections.version>3.2.2</commons.collections.version>
|
||||
<poi.version>4.1.2</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<jwt.version>0.9.0</jwt.version>
|
||||
<jwt.version>0.9.1</jwt.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- SpringBoot的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>2.2.13.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!--阿里数据库连接池 -->
|
||||
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
<version>${bitwalker.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- SpringBoot集成mybatis框架 -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${mybatis-spring-boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>${pagehelper.boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>${oshi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>${jna.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<version>${jna.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger3依赖 -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<artifactId>springfox-boot-starter</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--io常用工具类 -->
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--文件上传工具类 -->
|
||||
|
||||
<!-- 文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--velocity代码生成使用模板 -->
|
||||
|
||||
<!-- velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- collections工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>${commons.collections.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Token生成与解析-->
|
||||
|
||||
<!-- Token生成与解析-->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>${jwt.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<version>${kaptcha.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 定时任务-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-quartz</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 核心模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
@ -24,29 +24,17 @@
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
<!-- swagger3-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.5.21</version>
|
||||
<artifactId>springfox-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
@ -95,7 +83,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warName>${project.artifactId}</warName>
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
package com.ruoyi.web.controller.common;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.google.code.kaptcha.Producer;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.VerifyCodeUtils;
|
||||
import com.ruoyi.common.utils.sign.Base64;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
|
||||
@ -22,8 +26,18 @@ import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
@RestController
|
||||
public class CaptchaController
|
||||
{
|
||||
@Resource(name = "captchaProducer")
|
||||
private Producer captchaProducer;
|
||||
|
||||
@Resource(name = "captchaProducerMath")
|
||||
private Producer captchaProducerMath;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
// 验证码类型
|
||||
@Value("${ruoyi.captchaType}")
|
||||
private String captchaType;
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
@ -31,32 +45,42 @@ public class CaptchaController
|
||||
@GetMapping("/captchaImage")
|
||||
public AjaxResult getCode(HttpServletResponse response) throws IOException
|
||||
{
|
||||
// 生成随机字串
|
||||
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
|
||||
// 唯一标识
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtils.simpleUUID();
|
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
||||
|
||||
redisCache.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
||||
// 生成图片
|
||||
int w = 111, h = 36;
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
VerifyCodeUtils.outputImage(w, h, stream, verifyCode);
|
||||
String capStr = null, code = null;
|
||||
BufferedImage image = null;
|
||||
|
||||
// 生成验证码
|
||||
if ("math".equals(captchaType))
|
||||
{
|
||||
String capText = captchaProducerMath.createText();
|
||||
capStr = capText.substring(0, capText.lastIndexOf("@"));
|
||||
code = capText.substring(capText.lastIndexOf("@") + 1);
|
||||
image = captchaProducerMath.createImage(capStr);
|
||||
}
|
||||
else if ("char".equals(captchaType))
|
||||
{
|
||||
capStr = code = captchaProducer.createText();
|
||||
image = captchaProducer.createImage(capStr);
|
||||
}
|
||||
|
||||
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
||||
// 转换流信息写出
|
||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("uuid", uuid);
|
||||
ajax.put("img", Base64.encode(stream.toByteArray()));
|
||||
return ajax;
|
||||
ImageIO.write(image, "jpg", os);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
stream.close();
|
||||
}
|
||||
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("uuid", uuid);
|
||||
ajax.put("img", Base64.encode(os.toByteArray()));
|
||||
return ajax;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -41,17 +42,15 @@ public class CommonController
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!FileUtils.isValidFilename(fileName))
|
||||
if (!FileUtils.checkAllowDownload(fileName))
|
||||
{
|
||||
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
||||
}
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
String filePath = RuoYiConfig.getDownloadPath() + fileName;
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, realFileName);
|
||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||
if (delete)
|
||||
{
|
||||
@ -92,18 +91,28 @@ public class CommonController
|
||||
* 本地资源通用下载
|
||||
*/
|
||||
@GetMapping("/common/download/resource")
|
||||
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception
|
||||
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception
|
||||
{
|
||||
// 本地资源路径
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
// 数据库资源地址
|
||||
String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
try
|
||||
{
|
||||
if (!FileUtils.checkAllowDownload(resource))
|
||||
{
|
||||
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
|
||||
}
|
||||
// 本地资源路径
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
// 数据库资源地址
|
||||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("下载文件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package com.ruoyi.web.controller.monitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 缓存监控
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/cache")
|
||||
public class CacheController
|
||||
{
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
||||
@GetMapping()
|
||||
public AjaxResult getInfo() throws Exception
|
||||
{
|
||||
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
|
||||
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
|
||||
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
|
||||
|
||||
Map<String, Object> result = new HashMap<>(3);
|
||||
result.put("info", info);
|
||||
result.put("dbSize", dbSize);
|
||||
|
||||
List<Map<String, String>> pieList = new ArrayList<>();
|
||||
commandStats.stringPropertyNames().forEach(key -> {
|
||||
Map<String, String> data = new HashMap<>(2);
|
||||
String property = commandStats.getProperty(key);
|
||||
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
|
||||
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
|
||||
pieList.add(data);
|
||||
});
|
||||
result.put("commandStats", pieList);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.framework.web.domain.Server;
|
||||
|
||||
@ -15,7 +14,7 @@ import com.ruoyi.framework.web.domain.Server;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/server")
|
||||
public class ServerController extends BaseController
|
||||
public class ServerController
|
||||
{
|
||||
@PreAuthorize("@ss.hasPermi('monitor:server:list')")
|
||||
@GetMapping()
|
||||
|
||||
@ -38,18 +38,18 @@ public class SysLogininforController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@Log(title = "登陆日志", businessType = BusinessType.EXPORT)
|
||||
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
|
||||
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
|
||||
@GetMapping("/export")
|
||||
public AjaxResult export(SysLogininfor logininfor)
|
||||
{
|
||||
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
|
||||
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
|
||||
return util.exportExcel(list, "登陆日志");
|
||||
return util.exportExcel(list, "登录日志");
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
|
||||
@Log(title = "登陆日志", businessType = BusinessType.DELETE)
|
||||
@Log(title = "登录日志", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{infoIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] infoIds)
|
||||
{
|
||||
@ -57,7 +57,7 @@ public class SysLogininforController extends BaseController
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
|
||||
@Log(title = "登陆日志", businessType = BusinessType.CLEAN)
|
||||
@Log(title = "登录日志", businessType = BusinessType.CLEAN)
|
||||
@DeleteMapping("/clean")
|
||||
public AjaxResult clean()
|
||||
{
|
||||
|
||||
@ -48,6 +48,7 @@ public class SysOperlogController extends BaseController
|
||||
return util.exportExcel(list, "操作日志");
|
||||
}
|
||||
|
||||
@Log(title = "操作日志", businessType = BusinessType.DELETE)
|
||||
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
|
||||
@DeleteMapping("/{operIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] operIds)
|
||||
|
||||
@ -82,7 +82,7 @@ public class SysUserOnlineController extends BaseController
|
||||
* 强退用户
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
|
||||
@Log(title = "在线用户", businessType = BusinessType.DELETE)
|
||||
@Log(title = "在线用户", businessType = BusinessType.FORCE)
|
||||
@DeleteMapping("/{tokenId}")
|
||||
public AjaxResult forceLogout(@PathVariable String tokenId)
|
||||
{
|
||||
|
||||
@ -118,18 +118,19 @@ public class SysConfigController extends BaseController
|
||||
@DeleteMapping("/{configIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] configIds)
|
||||
{
|
||||
return toAjax(configService.deleteConfigByIds(configIds));
|
||||
configService.deleteConfigByIds(configIds);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
* 刷新参数缓存
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:config:remove')")
|
||||
@Log(title = "参数管理", businessType = BusinessType.CLEAN)
|
||||
@DeleteMapping("/clearCache")
|
||||
public AjaxResult clearCache()
|
||||
@DeleteMapping("/refreshCache")
|
||||
public AjaxResult refreshCache()
|
||||
{
|
||||
configService.clearCache();
|
||||
configService.resetConfigCache();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@ -19,6 +20,7 @@ import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.service.ISysDictDataService;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
@ -73,7 +75,12 @@ public class SysDictDataController extends BaseController
|
||||
@GetMapping(value = "/type/{dictType}")
|
||||
public AjaxResult dictType(@PathVariable String dictType)
|
||||
{
|
||||
return AjaxResult.success(dictTypeService.selectDictDataByType(dictType));
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
|
||||
if (StringUtils.isNull(data))
|
||||
{
|
||||
data = new ArrayList<SysDictData>();
|
||||
}
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +115,7 @@ public class SysDictDataController extends BaseController
|
||||
@DeleteMapping("/{dictCodes}")
|
||||
public AjaxResult remove(@PathVariable Long[] dictCodes)
|
||||
{
|
||||
return toAjax(dictDataService.deleteDictDataByIds(dictCodes));
|
||||
dictDataService.deleteDictDataByIds(dictCodes);
|
||||
return success();
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,18 +104,19 @@ public class SysDictTypeController extends BaseController
|
||||
@DeleteMapping("/{dictIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] dictIds)
|
||||
{
|
||||
return toAjax(dictTypeService.deleteDictTypeByIds(dictIds));
|
||||
dictTypeService.deleteDictTypeByIds(dictIds);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
* 刷新字典缓存
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
|
||||
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
|
||||
@DeleteMapping("/clearCache")
|
||||
public AjaxResult clearCache()
|
||||
@DeleteMapping("/refreshCache")
|
||||
public AjaxResult refreshCache()
|
||||
{
|
||||
dictTypeService.clearCache();
|
||||
dictTypeService.resetDictCache();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
public class SysIndexController
|
||||
{
|
||||
/** 系统基础配置 */
|
||||
@Autowired
|
||||
private RuoYiConfig ruoyiConfig;
|
||||
|
||||
/**
|
||||
* 访问首页,提示语
|
||||
*/
|
||||
@RequestMapping("/")
|
||||
public String index()
|
||||
{
|
||||
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
@ -102,8 +101,7 @@ public class SysMenuController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
|
||||
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
|
||||
{
|
||||
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
}
|
||||
@ -123,10 +121,13 @@ public class SysMenuController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
|
||||
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
|
||||
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
|
||||
{
|
||||
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||
}
|
||||
else if (menu.getMenuId().equals(menu.getParentId()))
|
||||
{
|
||||
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
|
||||
}
|
||||
menu.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(menuService.updateMenu(menu));
|
||||
|
||||
@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
@ -19,6 +20,7 @@ import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
@ -59,6 +61,16 @@ public class SysProfileController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult updateProfile(@RequestBody SysUser user)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
if (userService.updateUserProfile(user) > 0)
|
||||
{
|
||||
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
|
||||
|
||||
@ -17,11 +17,19 @@ import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.system.domain.SysUserRole;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
@ -35,6 +43,15 @@ public class SysRoleController extends BaseController
|
||||
@Autowired
|
||||
private ISysRoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private SysPermissionService permissionService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('system:role:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SysRole role)
|
||||
@ -103,7 +120,20 @@ public class SysRoleController extends BaseController
|
||||
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||
}
|
||||
role.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(roleService.updateRole(role));
|
||||
|
||||
if (roleService.updateRole(role) > 0)
|
||||
{
|
||||
// 更新缓存用户权限
|
||||
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
|
||||
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
|
||||
{
|
||||
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
|
||||
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
|
||||
tokenService.setLoginUser(loginUser);
|
||||
}
|
||||
return AjaxResult.success();
|
||||
}
|
||||
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,4 +181,61 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
return AjaxResult.success(roleService.selectRoleAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询已分配用户角色列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:list')")
|
||||
@GetMapping("/authUser/allocatedList")
|
||||
public TableDataInfo allocatedList(SysUser user)
|
||||
{
|
||||
startPage();
|
||||
List<SysUser> list = userService.selectAllocatedList(user);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询未分配用户角色列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:list')")
|
||||
@GetMapping("/authUser/unallocatedList")
|
||||
public TableDataInfo unallocatedList(SysUser user)
|
||||
{
|
||||
startPage();
|
||||
List<SysUser> list = userService.selectUnallocatedList(user);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消授权用户
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/cancel")
|
||||
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
|
||||
{
|
||||
return toAjax(roleService.deleteAuthUser(userRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量取消授权用户
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/cancelAll")
|
||||
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
|
||||
{
|
||||
return toAjax(roleService.deleteAuthUsers(roleId, userIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量选择用户授权
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authUser/selectAll")
|
||||
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
|
||||
{
|
||||
return toAjax(roleService.insertAuthUsers(roleId, userIds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,11 +127,13 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@ -149,11 +151,13 @@ public class SysUserController extends BaseController
|
||||
public AjaxResult edit(@Validated @RequestBody SysUser user)
|
||||
{
|
||||
userService.checkUserAllowed(user);
|
||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@ -175,7 +179,7 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/resetPwd")
|
||||
public AjaxResult resetPwd(@RequestBody SysUser user)
|
||||
@ -198,4 +202,31 @@ public class SysUserController extends BaseController
|
||||
user.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(userService.updateUserStatus(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户编号获取授权角色
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:query')")
|
||||
@GetMapping("/authRole/{userId}")
|
||||
public AjaxResult authRole(@PathVariable("userId") Long userId)
|
||||
{
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
SysUser user = userService.selectUserById(userId);
|
||||
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||
ajax.put("user", user);
|
||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
return ajax;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户授权角色
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authRole")
|
||||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||
{
|
||||
userService.insertUserAuth(userId, roleIds);
|
||||
return success();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
@ -16,6 +17,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -55,34 +57,38 @@ public class TestController extends BaseController
|
||||
}
|
||||
else
|
||||
{
|
||||
return AjaxResult.error("用户不存在");
|
||||
return error("用户不存在");
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("新增用户")
|
||||
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
|
||||
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
|
||||
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
|
||||
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
|
||||
})
|
||||
@PostMapping("/save")
|
||||
public AjaxResult save(UserEntity user)
|
||||
{
|
||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||
{
|
||||
return AjaxResult.error("用户ID不能为空");
|
||||
return error("用户ID不能为空");
|
||||
}
|
||||
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||
}
|
||||
|
||||
@ApiOperation("更新用户")
|
||||
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
|
||||
@PutMapping("/update")
|
||||
public AjaxResult update(UserEntity user)
|
||||
public AjaxResult update(@RequestBody UserEntity user)
|
||||
{
|
||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||
{
|
||||
return AjaxResult.error("用户ID不能为空");
|
||||
return error("用户ID不能为空");
|
||||
}
|
||||
if (users.isEmpty() || !users.containsKey(user.getUserId()))
|
||||
{
|
||||
return AjaxResult.error("用户不存在");
|
||||
return error("用户不存在");
|
||||
}
|
||||
users.remove(user.getUserId());
|
||||
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||
@ -96,16 +102,16 @@ public class TestController extends BaseController
|
||||
if (!users.isEmpty() && users.containsKey(userId))
|
||||
{
|
||||
users.remove(userId);
|
||||
return AjaxResult.success();
|
||||
return success();
|
||||
}
|
||||
else
|
||||
{
|
||||
return AjaxResult.error("用户不存在");
|
||||
return error("用户不存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ApiModel("用户实体")
|
||||
@ApiModel(value = "UserEntity", description = "用户实体")
|
||||
class UserEntity
|
||||
{
|
||||
@ApiModelProperty("用户ID")
|
||||
|
||||
@ -8,6 +8,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.models.auth.In;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
@ -16,10 +17,10 @@ import springfox.documentation.service.ApiKey;
|
||||
import springfox.documentation.service.AuthorizationScope;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.service.SecurityReference;
|
||||
import springfox.documentation.service.SecurityScheme;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
/**
|
||||
* Swagger2的接口配置
|
||||
@ -27,7 +28,6 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig
|
||||
{
|
||||
/** 系统基础配置 */
|
||||
@ -48,7 +48,7 @@ public class SwaggerConfig
|
||||
@Bean
|
||||
public Docket createRestApi()
|
||||
{
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
// 是否启用Swagger
|
||||
.enable(enabled)
|
||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||
@ -71,10 +71,10 @@ public class SwaggerConfig
|
||||
/**
|
||||
* 安全模式,这里指定token通过Authorization头请求头传递
|
||||
*/
|
||||
private List<ApiKey> securitySchemes()
|
||||
private List<SecurityScheme> securitySchemes()
|
||||
{
|
||||
List<ApiKey> apiKeyList = new ArrayList<ApiKey>();
|
||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
|
||||
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
|
||||
return apiKeyList;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ public class SwaggerConfig
|
||||
securityContexts.add(
|
||||
SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
||||
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
||||
.build());
|
||||
return securityContexts;
|
||||
}
|
||||
|
||||
@ -43,8 +43,8 @@ spring:
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username:
|
||||
login-password:
|
||||
login-username: ruoyi
|
||||
login-password: 123456
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
|
||||
@ -3,15 +3,17 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 3.0.0
|
||||
version: 3.6.0
|
||||
# 版权年份
|
||||
copyrightYear: 2019
|
||||
copyrightYear: 2021
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||
profile: D:/ruoyi/uploadPath
|
||||
# 获取ip地址开关
|
||||
addressEnabled: false
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
captchaType: math
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
@ -60,6 +62,8 @@ spring:
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password:
|
||||
# 连接超时时间
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 自定义导出Excel数据注解
|
||||
@ -29,11 +30,31 @@ public @interface Excel
|
||||
*/
|
||||
public String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
|
||||
*/
|
||||
public String dictType() default "";
|
||||
|
||||
/**
|
||||
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
|
||||
*/
|
||||
public String readConverterExp() default "";
|
||||
|
||||
/**
|
||||
* 分隔符,读取字符串组内容
|
||||
*/
|
||||
public String separator() default ",";
|
||||
|
||||
/**
|
||||
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
|
||||
*/
|
||||
public int scale() default -1;
|
||||
|
||||
/**
|
||||
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
|
||||
*/
|
||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||
|
||||
/**
|
||||
* 导出类型(0数字 1字符串)
|
||||
*/
|
||||
@ -79,6 +100,32 @@ public @interface Excel
|
||||
*/
|
||||
public String targetAttr() default "";
|
||||
|
||||
/**
|
||||
* 是否自动统计数据,在最后追加一行统计数据总和
|
||||
*/
|
||||
public boolean isStatistics() default false;
|
||||
|
||||
/**
|
||||
* 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
|
||||
*/
|
||||
Align align() default Align.AUTO;
|
||||
|
||||
public enum Align
|
||||
{
|
||||
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
|
||||
private final int value;
|
||||
|
||||
Align(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
|
||||
*/
|
||||
@ -102,7 +149,7 @@ public @interface Excel
|
||||
|
||||
public enum ColumnType
|
||||
{
|
||||
NUMERIC(0), STRING(1);
|
||||
NUMERIC(0), STRING(1), IMAGE(2);
|
||||
private final int value;
|
||||
|
||||
ColumnType(int value)
|
||||
@ -115,4 +162,4 @@ public @interface Excel
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,6 +61,11 @@ public class Constants
|
||||
* 登录用户 redis key
|
||||
*/
|
||||
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
|
||||
|
||||
/**
|
||||
* 防重提交 redis key
|
||||
*/
|
||||
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
|
||||
|
||||
/**
|
||||
* 验证码有效期(分钟)
|
||||
@ -121,4 +126,9 @@ public class Constants
|
||||
* 资源映射路径 前缀
|
||||
*/
|
||||
public static final String RESOURCE_PREFIX = "/profile";
|
||||
|
||||
/**
|
||||
* RMI 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_RMI = "rmi://";
|
||||
}
|
||||
|
||||
@ -13,6 +13,9 @@ public class GenConstants
|
||||
/** 树表(增删改查) */
|
||||
public static final String TPL_TREE = "tree";
|
||||
|
||||
/** 主子表(增删改查) */
|
||||
public static final String TPL_SUB = "sub";
|
||||
|
||||
/** 树编码字段 */
|
||||
public static final String TREE_CODE = "treeCode";
|
||||
|
||||
@ -22,16 +25,24 @@ public class GenConstants
|
||||
/** 树名称字段 */
|
||||
public static final String TREE_NAME = "treeName";
|
||||
|
||||
/** 上级菜单ID字段 */
|
||||
public static final String PARENT_MENU_ID = "parentMenuId";
|
||||
|
||||
/** 上级菜单名称字段 */
|
||||
public static final String PARENT_MENU_NAME = "parentMenuName";
|
||||
|
||||
/** 数据库字符串类型 */
|
||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
|
||||
"mediumtext", "longtext" };
|
||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
||||
|
||||
/** 数据库文本类型 */
|
||||
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
|
||||
|
||||
/** 数据库时间类型 */
|
||||
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
|
||||
|
||||
/** 数据库数字类型 */
|
||||
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
|
||||
"bigint", "float", "float", "double", "decimal" };
|
||||
"bit", "bigint", "float", "double", "decimal" };
|
||||
|
||||
/** 页面不需要编辑字段 */
|
||||
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
|
||||
@ -68,6 +79,15 @@ public class GenConstants
|
||||
/** 日期控件 */
|
||||
public static final String HTML_DATETIME = "datetime";
|
||||
|
||||
/** 图片上传控件 */
|
||||
public static final String HTML_IMAGE_UPLOAD = "imageUpload";
|
||||
|
||||
/** 文件上传控件 */
|
||||
public static final String HTML_FILE_UPLOAD = "fileUpload";
|
||||
|
||||
/** 富文本控件 */
|
||||
public static final String HTML_EDITOR = "editor";
|
||||
|
||||
/** 字符串类型 */
|
||||
public static final String TYPE_STRING = "String";
|
||||
|
||||
|
||||
@ -54,6 +54,12 @@ public class UserConstants
|
||||
/** Layout组件标识 */
|
||||
public final static String LAYOUT = "Layout";
|
||||
|
||||
/** ParentView组件标识 */
|
||||
public final static String PARENT_VIEW = "ParentView";
|
||||
|
||||
/** InnerLink组件标识 */
|
||||
public final static String INNER_LINK = "InnerLink";
|
||||
|
||||
/** 校验返回结果码 */
|
||||
public final static String UNIQUE = "0";
|
||||
public final static String NOT_UNIQUE = "1";
|
||||
|
||||
@ -25,7 +25,7 @@ import com.ruoyi.common.utils.sql.SqlUtil;
|
||||
*/
|
||||
public class BaseController
|
||||
{
|
||||
protected final Logger logger = LoggerFactory.getLogger(BaseController.class);
|
||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
|
||||
@ -59,6 +59,19 @@ public class BaseController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求排序数据
|
||||
*/
|
||||
protected void startOrderBy()
|
||||
{
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
|
||||
{
|
||||
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
|
||||
PageHelper.orderBy(orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应请求分页数据
|
||||
*/
|
||||
@ -84,6 +97,49 @@ public class BaseController
|
||||
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应返回结果
|
||||
*
|
||||
* @param result 结果
|
||||
* @return 操作结果
|
||||
*/
|
||||
protected AjaxResult toAjax(boolean result)
|
||||
{
|
||||
return result ? success() : error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功
|
||||
*/
|
||||
public AjaxResult success()
|
||||
{
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回失败消息
|
||||
*/
|
||||
public AjaxResult error()
|
||||
{
|
||||
return AjaxResult.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*/
|
||||
public AjaxResult success(String message)
|
||||
{
|
||||
return AjaxResult.success(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回失败消息
|
||||
*/
|
||||
public AjaxResult error(String message)
|
||||
{
|
||||
return AjaxResult.error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面跳转
|
||||
*/
|
||||
|
||||
@ -5,7 +5,6 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
@ -36,14 +35,6 @@ public class BaseEntity implements Serializable
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 开始时间 */
|
||||
@JsonIgnore
|
||||
private String beginTime;
|
||||
|
||||
/** 结束时间 */
|
||||
@JsonIgnore
|
||||
private String endTime;
|
||||
|
||||
/** 请求参数 */
|
||||
private Map<String, Object> params;
|
||||
|
||||
@ -107,26 +98,6 @@ public class BaseEntity implements Serializable
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getBeginTime()
|
||||
{
|
||||
return beginTime;
|
||||
}
|
||||
|
||||
public void setBeginTime(String beginTime)
|
||||
{
|
||||
this.beginTime = beginTime;
|
||||
}
|
||||
|
||||
public String getEndTime()
|
||||
{
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime)
|
||||
{
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams()
|
||||
{
|
||||
if (params == null)
|
||||
|
||||
@ -41,6 +41,9 @@ public class SysMenu extends BaseEntity
|
||||
/** 是否为外链(0是 1否) */
|
||||
private String isFrame;
|
||||
|
||||
/** 是否缓存(0缓存 1不缓存) */
|
||||
private String isCache;
|
||||
|
||||
/** 类型(M目录 C菜单 F按钮) */
|
||||
private String menuType;
|
||||
|
||||
@ -144,6 +147,16 @@ public class SysMenu extends BaseEntity
|
||||
this.isFrame = isFrame;
|
||||
}
|
||||
|
||||
public String getIsCache()
|
||||
{
|
||||
return isCache;
|
||||
}
|
||||
|
||||
public void setIsCache(String isCache)
|
||||
{
|
||||
this.isCache = isCache;
|
||||
}
|
||||
|
||||
@NotBlank(message = "菜单类型不能为空")
|
||||
public String getMenuType()
|
||||
{
|
||||
@ -216,6 +229,7 @@ public class SysMenu extends BaseEntity
|
||||
.append("path", getPath())
|
||||
.append("component", getComponent())
|
||||
.append("isFrame", getIsFrame())
|
||||
.append("IsCache", getIsCache())
|
||||
.append("menuType", getMenuType())
|
||||
.append("visible", getVisible())
|
||||
.append("status ", getStatus())
|
||||
|
||||
@ -33,10 +33,16 @@ public class SysRole extends BaseEntity
|
||||
@Excel(name = "角色排序")
|
||||
private String roleSort;
|
||||
|
||||
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限) */
|
||||
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限")
|
||||
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
|
||||
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
|
||||
private String dataScope;
|
||||
|
||||
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
|
||||
private boolean menuCheckStrictly;
|
||||
|
||||
/** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
|
||||
private boolean deptCheckStrictly;
|
||||
|
||||
/** 角色状态(0正常 1停用) */
|
||||
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
|
||||
private String status;
|
||||
@ -128,6 +134,26 @@ public class SysRole extends BaseEntity
|
||||
this.dataScope = dataScope;
|
||||
}
|
||||
|
||||
public boolean isMenuCheckStrictly()
|
||||
{
|
||||
return menuCheckStrictly;
|
||||
}
|
||||
|
||||
public void setMenuCheckStrictly(boolean menuCheckStrictly)
|
||||
{
|
||||
this.menuCheckStrictly = menuCheckStrictly;
|
||||
}
|
||||
|
||||
public boolean isDeptCheckStrictly()
|
||||
{
|
||||
return deptCheckStrictly;
|
||||
}
|
||||
|
||||
public void setDeptCheckStrictly(boolean deptCheckStrictly)
|
||||
{
|
||||
this.deptCheckStrictly = deptCheckStrictly;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
@ -186,6 +212,8 @@ public class SysRole extends BaseEntity
|
||||
.append("roleKey", getRoleKey())
|
||||
.append("roleSort", getRoleSort())
|
||||
.append("dataScope", getDataScope())
|
||||
.append("menuCheckStrictly", isMenuCheckStrictly())
|
||||
.append("deptCheckStrictly", isDeptCheckStrictly())
|
||||
.append("status", getStatus())
|
||||
.append("delFlag", getDelFlag())
|
||||
.append("createBy", getCreateBy())
|
||||
|
||||
@ -68,12 +68,12 @@ public class SysUser extends BaseEntity
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 最后登陆IP */
|
||||
@Excel(name = "最后登陆IP", type = Type.EXPORT)
|
||||
/** 最后登录IP */
|
||||
@Excel(name = "最后登录IP", type = Type.EXPORT)
|
||||
private String loginIp;
|
||||
|
||||
/** 最后登陆时间 */
|
||||
@Excel(name = "最后登陆时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
||||
/** 最后登录时间 */
|
||||
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
||||
private Date loginDate;
|
||||
|
||||
/** 部门对象 */
|
||||
@ -92,6 +92,9 @@ public class SysUser extends BaseEntity
|
||||
/** 岗位组 */
|
||||
private Long[] postIds;
|
||||
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
|
||||
public SysUser()
|
||||
{
|
||||
|
||||
@ -300,6 +303,16 @@ public class SysUser extends BaseEntity
|
||||
this.postIds = postIds;
|
||||
}
|
||||
|
||||
public Long getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId)
|
||||
{
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
|
||||
@ -22,7 +22,7 @@ public class LoginUser implements UserDetails
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 登陆时间
|
||||
* 登录时间
|
||||
*/
|
||||
private Long loginTime;
|
||||
|
||||
|
||||
@ -1,72 +1,84 @@
|
||||
package com.ruoyi.common.core.page;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 分页数据
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class PageDomain
|
||||
{
|
||||
/** 当前记录起始索引 */
|
||||
private Integer pageNum;
|
||||
|
||||
/** 每页显示记录数 */
|
||||
private Integer pageSize;
|
||||
|
||||
/** 排序列 */
|
||||
private String orderByColumn;
|
||||
|
||||
/** 排序的方向 "desc" 或者 "asc". */
|
||||
private String isAsc;
|
||||
|
||||
public String getOrderBy()
|
||||
{
|
||||
if (StringUtils.isEmpty(orderByColumn))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
|
||||
}
|
||||
|
||||
public Integer getPageNum()
|
||||
{
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(Integer pageNum)
|
||||
{
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public Integer getPageSize()
|
||||
{
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize)
|
||||
{
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public String getOrderByColumn()
|
||||
{
|
||||
return orderByColumn;
|
||||
}
|
||||
|
||||
public void setOrderByColumn(String orderByColumn)
|
||||
{
|
||||
this.orderByColumn = orderByColumn;
|
||||
}
|
||||
|
||||
public String getIsAsc()
|
||||
{
|
||||
return isAsc;
|
||||
}
|
||||
|
||||
public void setIsAsc(String isAsc)
|
||||
{
|
||||
this.isAsc = isAsc;
|
||||
}
|
||||
}
|
||||
package com.ruoyi.common.core.page;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 分页数据
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class PageDomain
|
||||
{
|
||||
/** 当前记录起始索引 */
|
||||
private Integer pageNum;
|
||||
|
||||
/** 每页显示记录数 */
|
||||
private Integer pageSize;
|
||||
|
||||
/** 排序列 */
|
||||
private String orderByColumn;
|
||||
|
||||
/** 排序的方向desc或者asc */
|
||||
private String isAsc = "asc";
|
||||
|
||||
public String getOrderBy()
|
||||
{
|
||||
if (StringUtils.isEmpty(orderByColumn))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
|
||||
}
|
||||
|
||||
public Integer getPageNum()
|
||||
{
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(Integer pageNum)
|
||||
{
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public Integer getPageSize()
|
||||
{
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize)
|
||||
{
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public String getOrderByColumn()
|
||||
{
|
||||
return orderByColumn;
|
||||
}
|
||||
|
||||
public void setOrderByColumn(String orderByColumn)
|
||||
{
|
||||
this.orderByColumn = orderByColumn;
|
||||
}
|
||||
|
||||
public String getIsAsc()
|
||||
{
|
||||
return isAsc;
|
||||
}
|
||||
|
||||
public void setIsAsc(String isAsc)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(isAsc))
|
||||
{
|
||||
// 兼容前端排序类型
|
||||
if ("ascending".equals(isAsc))
|
||||
{
|
||||
isAsc = "asc";
|
||||
}
|
||||
else if ("descending".equals(isAsc))
|
||||
{
|
||||
isAsc = "desc";
|
||||
}
|
||||
this.isAsc = isAsc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package com.ruoyi.common.core.redis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
@ -13,7 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* spring redis 工具类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
**/
|
||||
@SuppressWarnings(value = { "unchecked", "rawtypes" })
|
||||
@ -109,7 +111,7 @@ public class RedisCache
|
||||
* 缓存List数据
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param values 待缓存的List数据
|
||||
* @param dataList 待缓存的List数据
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> long setCacheList(final String key, final List<T> dataList)
|
||||
@ -136,10 +138,15 @@ public class RedisCache
|
||||
* @param dataSet 缓存的数据
|
||||
* @return 缓存数据的对象
|
||||
*/
|
||||
public <T> long setCacheSet(final String key, final Set<T> dataSet)
|
||||
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
||||
{
|
||||
Long count = redisTemplate.opsForSet().add(key, dataSet);
|
||||
return count == null ? 0 : count;
|
||||
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||
Iterator<T> it = dataSet.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
setOperation.add(it.next());
|
||||
}
|
||||
return setOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,7 +223,7 @@ public class RedisCache
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象列表
|
||||
*
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
*/
|
||||
|
||||
@ -66,7 +66,7 @@ public class CharsetKit
|
||||
|
||||
if (null == destCharset)
|
||||
{
|
||||
srcCharset = StandardCharsets.UTF_8;
|
||||
destCharset = StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
|
||||
|
||||
@ -7,10 +7,11 @@ import java.nio.charset.Charset;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Set;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Convert
|
||||
@ -19,7 +20,7 @@ public class Convert
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -41,7 +42,7 @@ public class Convert
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -54,7 +55,7 @@ public class Convert
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -78,7 +79,7 @@ public class Convert
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -91,7 +92,7 @@ public class Convert
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -129,7 +130,7 @@ public class Convert
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -142,7 +143,7 @@ public class Convert
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -180,7 +181,7 @@ public class Convert
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -193,7 +194,7 @@ public class Convert
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -227,7 +228,7 @@ public class Convert
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -240,7 +241,7 @@ public class Convert
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -278,7 +279,7 @@ public class Convert
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -289,7 +290,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为Integer数组<br>
|
||||
*
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -300,7 +301,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -311,7 +312,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为Integer数组<br>
|
||||
*
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param split 被转换的值
|
||||
* @return 结果
|
||||
@ -334,7 +335,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
@ -357,7 +358,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为String数组<br>
|
||||
*
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -368,7 +369,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为String数组<br>
|
||||
*
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param split 被转换的值
|
||||
* @return 结果
|
||||
@ -382,7 +383,7 @@ public class Convert
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -421,7 +422,7 @@ public class Convert
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -434,7 +435,7 @@ public class Convert
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -473,7 +474,7 @@ public class Convert
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -486,7 +487,7 @@ public class Convert
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -524,7 +525,7 @@ public class Convert
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -537,7 +538,7 @@ public class Convert
|
||||
* 转换为boolean<br>
|
||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -583,7 +584,7 @@ public class Convert
|
||||
* 转换为boolean<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -595,7 +596,7 @@ public class Convert
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
*
|
||||
*
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
* @param defaultValue 默认值
|
||||
@ -631,7 +632,7 @@ public class Convert
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
*
|
||||
*
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
* @return Enum
|
||||
@ -645,7 +646,7 @@ public class Convert
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -683,7 +684,7 @@ public class Convert
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -696,7 +697,7 @@ public class Convert
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -742,7 +743,7 @@ public class Convert
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -754,7 +755,7 @@ public class Convert
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 字符串
|
||||
*/
|
||||
@ -766,7 +767,7 @@ public class Convert
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param charsetName 字符集
|
||||
* @return 字符串
|
||||
@ -779,7 +780,7 @@ public class Convert
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param charset 字符集
|
||||
* @return 字符串
|
||||
@ -795,9 +796,14 @@ public class Convert
|
||||
{
|
||||
return (String) obj;
|
||||
}
|
||||
else if (obj instanceof byte[] || obj instanceof Byte[])
|
||||
else if (obj instanceof byte[])
|
||||
{
|
||||
return str((Byte[]) obj, charset);
|
||||
return str((byte[]) obj, charset);
|
||||
}
|
||||
else if (obj instanceof Byte[])
|
||||
{
|
||||
byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
|
||||
return str(bytes, charset);
|
||||
}
|
||||
else if (obj instanceof ByteBuffer)
|
||||
{
|
||||
@ -808,7 +814,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 将byte数组转为字符串
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @param charset 字符集
|
||||
* @return 字符串
|
||||
@ -820,7 +826,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 解码字节码
|
||||
*
|
||||
*
|
||||
* @param data 字符串
|
||||
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
|
||||
* @return 解码后的字符串
|
||||
@ -841,7 +847,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 将编码的byteBuffer数据转换为字符串
|
||||
*
|
||||
*
|
||||
* @param data 数据
|
||||
* @param charset 字符集,如果为空使用当前系统字符集
|
||||
* @return 字符串
|
||||
@ -858,7 +864,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 将编码的byteBuffer数据转换为字符串
|
||||
*
|
||||
*
|
||||
* @param data 数据
|
||||
* @param charset 字符集,如果为空使用当前系统字符集
|
||||
* @return 字符串
|
||||
@ -875,7 +881,7 @@ public class Convert
|
||||
// ----------------------------------------------------------------------- 全角半角转换
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
@ -886,7 +892,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 全角字符串.
|
||||
@ -917,7 +923,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 全角转半角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 半角字符串
|
||||
*/
|
||||
@ -928,7 +934,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 替换全角为半角
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 替换后的字符
|
||||
@ -960,7 +966,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 数字金额大写转换 先写个完整的然后将如零拾替换成零
|
||||
*
|
||||
*
|
||||
* @param n 数字
|
||||
* @return 中文大写数字
|
||||
*/
|
||||
|
||||
@ -68,4 +68,14 @@ public class InvalidExtensionException extends FileUploadException
|
||||
super(allowedExtension, extension, filename);
|
||||
}
|
||||
}
|
||||
|
||||
public static class InvalidVideoExtensionException extends InvalidExtensionException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
|
||||
{
|
||||
super(allowedExtension, extension, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,8 +29,8 @@ public class RepeatableFilter implements Filter
|
||||
throws IOException, ServletException
|
||||
{
|
||||
ServletRequest requestWrapper = null;
|
||||
if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(),
|
||||
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
if (request instanceof HttpServletRequest
|
||||
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
|
||||
{
|
||||
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
|
||||
}
|
||||
|
||||
@ -38,18 +38,21 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException
|
||||
{
|
||||
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
|
||||
|
||||
return new ServletInputStream()
|
||||
{
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
return bais.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException
|
||||
{
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished()
|
||||
{
|
||||
|
||||
@ -99,7 +99,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
|
||||
public boolean isJsonRequest()
|
||||
{
|
||||
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
|
||||
return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header)
|
||||
|| MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(header);
|
||||
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
|
||||
}
|
||||
}
|
||||
@ -1,114 +1,114 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 精确的浮点数运算
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Arith
|
||||
{
|
||||
|
||||
/** 默认除法运算精度 */
|
||||
private static final int DEF_DIV_SCALE = 10;
|
||||
|
||||
/** 这个类不能实例化 */
|
||||
private Arith()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的加法运算。
|
||||
* @param v1 被加数
|
||||
* @param v2 加数
|
||||
* @return 两个参数的和
|
||||
*/
|
||||
public static double add(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.add(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的减法运算。
|
||||
* @param v1 被减数
|
||||
* @param v2 减数
|
||||
* @return 两个参数的差
|
||||
*/
|
||||
public static double sub(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.subtract(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的乘法运算。
|
||||
* @param v1 被乘数
|
||||
* @param v2 乘数
|
||||
* @return 两个参数的积
|
||||
*/
|
||||
public static double mul(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.multiply(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
|
||||
* 小数点以后10位,以后的数字四舍五入。
|
||||
* @param v1 被除数
|
||||
* @param v2 除数
|
||||
* @return 两个参数的商
|
||||
*/
|
||||
public static double div(double v1, double v2)
|
||||
{
|
||||
return div(v1, v2, DEF_DIV_SCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
|
||||
* 定精度,以后的数字四舍五入。
|
||||
* @param v1 被除数
|
||||
* @param v2 除数
|
||||
* @param scale 表示表示需要精确到小数点以后几位。
|
||||
* @return 两个参数的商
|
||||
*/
|
||||
public static double div(double v1, double v2, int scale)
|
||||
{
|
||||
if (scale < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"The scale must be a positive integer or zero");
|
||||
}
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
if (b1.compareTo(BigDecimal.ZERO) == 0)
|
||||
{
|
||||
return BigDecimal.ZERO.doubleValue();
|
||||
}
|
||||
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的小数位四舍五入处理。
|
||||
* @param v 需要四舍五入的数字
|
||||
* @param scale 小数点后保留几位
|
||||
* @return 四舍五入后的结果
|
||||
*/
|
||||
public static double round(double v, int scale)
|
||||
{
|
||||
if (scale < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"The scale must be a positive integer or zero");
|
||||
}
|
||||
BigDecimal b = new BigDecimal(Double.toString(v));
|
||||
BigDecimal one = new BigDecimal("1");
|
||||
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
}
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 精确的浮点数运算
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Arith
|
||||
{
|
||||
|
||||
/** 默认除法运算精度 */
|
||||
private static final int DEF_DIV_SCALE = 10;
|
||||
|
||||
/** 这个类不能实例化 */
|
||||
private Arith()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的加法运算。
|
||||
* @param v1 被加数
|
||||
* @param v2 加数
|
||||
* @return 两个参数的和
|
||||
*/
|
||||
public static double add(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.add(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的减法运算。
|
||||
* @param v1 被减数
|
||||
* @param v2 减数
|
||||
* @return 两个参数的差
|
||||
*/
|
||||
public static double sub(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.subtract(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的乘法运算。
|
||||
* @param v1 被乘数
|
||||
* @param v2 乘数
|
||||
* @return 两个参数的积
|
||||
*/
|
||||
public static double mul(double v1, double v2)
|
||||
{
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
return b1.multiply(b2).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
|
||||
* 小数点以后10位,以后的数字四舍五入。
|
||||
* @param v1 被除数
|
||||
* @param v2 除数
|
||||
* @return 两个参数的商
|
||||
*/
|
||||
public static double div(double v1, double v2)
|
||||
{
|
||||
return div(v1, v2, DEF_DIV_SCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
|
||||
* 定精度,以后的数字四舍五入。
|
||||
* @param v1 被除数
|
||||
* @param v2 除数
|
||||
* @param scale 表示表示需要精确到小数点以后几位。
|
||||
* @return 两个参数的商
|
||||
*/
|
||||
public static double div(double v1, double v2, int scale)
|
||||
{
|
||||
if (scale < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"The scale must be a positive integer or zero");
|
||||
}
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
if (b1.compareTo(BigDecimal.ZERO) == 0)
|
||||
{
|
||||
return BigDecimal.ZERO.doubleValue();
|
||||
}
|
||||
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供精确的小数位四舍五入处理。
|
||||
* @param v 需要四舍五入的数字
|
||||
* @param scale 小数点后保留几位
|
||||
* @return 四舍五入后的结果
|
||||
*/
|
||||
public static double round(double v, int scale)
|
||||
{
|
||||
if (scale < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"The scale must be a positive integer or zero");
|
||||
}
|
||||
BigDecimal b = new BigDecimal(Double.toString(v));
|
||||
BigDecimal one = BigDecimal.ONE;
|
||||
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.ruoyi.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
@ -15,6 +14,11 @@ import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
*/
|
||||
public class DictUtils
|
||||
{
|
||||
/**
|
||||
* 分隔符
|
||||
*/
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* 设置字典缓存
|
||||
*
|
||||
@ -37,12 +41,126 @@ public class DictUtils
|
||||
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
||||
if (StringUtils.isNotNull(cacheObj))
|
||||
{
|
||||
List<SysDictData> DictDatas = StringUtils.cast(cacheObj);
|
||||
return DictDatas;
|
||||
List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
|
||||
return dictDatas;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue)
|
||||
{
|
||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel)
|
||||
{
|
||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue, String separator)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
for (String value : dictValue.split(separator))
|
||||
{
|
||||
if (value.equals(dict.getDictValue()))
|
||||
{
|
||||
propertyString.append(dict.getDictLabel() + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
if (dictValue.equals(dict.getDictValue()))
|
||||
{
|
||||
return dict.getDictLabel();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel, String separator)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
for (String label : dictLabel.split(separator))
|
||||
{
|
||||
if (label.equals(dict.getDictLabel()))
|
||||
{
|
||||
propertyString.append(dict.getDictValue() + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
if (dictLabel.equals(dict.getDictLabel()))
|
||||
{
|
||||
return dict.getDictValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定字典缓存
|
||||
*
|
||||
* @param key 字典键
|
||||
*/
|
||||
public static void removeDictCache(String key)
|
||||
{
|
||||
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空字典缓存
|
||||
*/
|
||||
|
||||
@ -22,7 +22,7 @@ public class ExceptionUtil
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String getRootErrorMseeage(Exception e)
|
||||
public static String getRootErrorMessage(Exception e)
|
||||
{
|
||||
Throwable root = ExceptionUtils.getRootCause(e);
|
||||
root = (root == null ? e : root);
|
||||
|
||||
@ -6,6 +6,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.text.StrFormatter;
|
||||
|
||||
/**
|
||||
@ -260,6 +261,17 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
return StrFormatter.format(template, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为http(s)://开头
|
||||
*
|
||||
* @param link 链接
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean ishttp(String link)
|
||||
{
|
||||
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转set
|
||||
*
|
||||
@ -312,7 +324,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰命名
|
||||
* 驼峰转下划线命名
|
||||
*/
|
||||
public static String toUnderScoreCase(String str)
|
||||
{
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package com.ruoyi.common.utils.file;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 文件类型工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileTypeUtils
|
||||
{
|
||||
/**
|
||||
* 获取文件类型
|
||||
* <p>
|
||||
* 例如: ruoyi.txt, 返回: txt
|
||||
*
|
||||
* @param file 文件名
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileType(File file)
|
||||
{
|
||||
if (null == file)
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getFileType(file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
* <p>
|
||||
* 例如: ruoyi.txt, 返回: txt
|
||||
*
|
||||
* @param fileName 文件名
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileType(String fileName)
|
||||
{
|
||||
int separatorIndex = fileName.lastIndexOf(".");
|
||||
if (separatorIndex < 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(separatorIndex + 1).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
*
|
||||
* @param photoByte 文件字节码
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileExtendName(byte[] photoByte)
|
||||
{
|
||||
String strFileExtendName = "JPG";
|
||||
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
|
||||
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
|
||||
{
|
||||
strFileExtendName = "GIF";
|
||||
}
|
||||
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
|
||||
{
|
||||
strFileExtendName = "JPG";
|
||||
}
|
||||
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
|
||||
{
|
||||
strFileExtendName = "BMP";
|
||||
}
|
||||
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
|
||||
{
|
||||
strFileExtendName = "PNG";
|
||||
}
|
||||
return strFileExtendName;
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
|
||||
/**
|
||||
* 文件上传工具类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileUploadUtils
|
||||
@ -89,7 +89,7 @@ public class FileUploadUtils
|
||||
*
|
||||
* @param baseDir 相对应用的基目录
|
||||
* @param file 上传的文件
|
||||
* @param extension 上传文件类型
|
||||
* @param allowedExtension 上传文件类型
|
||||
* @return 返回上传成功的文件名
|
||||
* @throws FileSizeLimitExceededException 如果超出最大大小
|
||||
* @throws FileNameLengthLimitExceededException 文件名太长
|
||||
@ -131,13 +131,12 @@ public class FileUploadUtils
|
||||
{
|
||||
File desc = new File(uploadDir + File.separator + fileName);
|
||||
|
||||
if (!desc.getParentFile().exists())
|
||||
{
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
if (!desc.exists())
|
||||
{
|
||||
desc.createNewFile();
|
||||
if (!desc.getParentFile().exists())
|
||||
{
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
@ -186,6 +185,11 @@ public class FileUploadUtils
|
||||
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
|
||||
fileName);
|
||||
}
|
||||
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
|
||||
{
|
||||
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
|
||||
fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidExtensionException(allowedExtension, extension, fileName);
|
||||
@ -215,7 +219,7 @@ public class FileUploadUtils
|
||||
|
||||
/**
|
||||
* 获取文件名的后缀
|
||||
*
|
||||
*
|
||||
* @param file 表单文件
|
||||
* @return 后缀名
|
||||
*/
|
||||
@ -228,4 +232,4 @@ public class FileUploadUtils
|
||||
}
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,11 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 文件处理工具类
|
||||
@ -104,6 +108,30 @@ public class FileUtils
|
||||
return filename.matches(FILENAME_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否可下载
|
||||
*
|
||||
* @param resource 需要下载的文件
|
||||
* @return true 正常 false 非法
|
||||
*/
|
||||
public static boolean checkAllowDownload(String resource)
|
||||
{
|
||||
// 禁止目录上跳级别
|
||||
if (StringUtils.contains(resource, ".."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查允许下载的文件规则
|
||||
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 不在允许下载的文件规则
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
@ -111,8 +139,7 @@ public class FileUtils
|
||||
* @param fileName 文件名
|
||||
* @return 编码后的文件名
|
||||
*/
|
||||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
|
||||
throws UnsupportedEncodingException
|
||||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
|
||||
{
|
||||
final String agent = request.getHeader("USER-AGENT");
|
||||
String filename = fileName;
|
||||
@ -139,4 +166,38 @@ public class FileUtils
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
* @param response 响应对象
|
||||
* @param realFileName 真实文件名
|
||||
* @return
|
||||
*/
|
||||
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
|
||||
{
|
||||
String percentEncodedFileName = percentEncode(realFileName);
|
||||
|
||||
StringBuilder contentDispositionValue = new StringBuilder();
|
||||
contentDispositionValue.append("attachment; filename=")
|
||||
.append(percentEncodedFileName)
|
||||
.append(";")
|
||||
.append("filename*=")
|
||||
.append("utf-8''")
|
||||
.append(percentEncodedFileName);
|
||||
|
||||
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 百分号编码工具方法
|
||||
*
|
||||
* @param s 需要百分号编码的字符串
|
||||
* @return 百分号编码后的字符串
|
||||
*/
|
||||
public static String percentEncode(String s) throws UnsupportedEncodingException
|
||||
{
|
||||
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
|
||||
return encode.replaceAll("\\+", "%20");
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
package com.ruoyi.common.utils.file;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Arrays;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 图片处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ImageUtils
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
|
||||
|
||||
public static byte[] getImage(String imagePath)
|
||||
{
|
||||
InputStream is = getFile(imagePath);
|
||||
try
|
||||
{
|
||||
return IOUtils.toByteArray(is);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("图片加载异常 {}", e);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getFile(String imagePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] result = readFile(imagePath);
|
||||
result = Arrays.copyOf(result, result.length);
|
||||
return new ByteArrayInputStream(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("获取图片异常 {}", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件为字节数据
|
||||
*
|
||||
* @param key 地址
|
||||
* @return 字节数据
|
||||
*/
|
||||
public static byte[] readFile(String url)
|
||||
{
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
try
|
||||
{
|
||||
if (url.startsWith("http"))
|
||||
{
|
||||
// 网络地址
|
||||
URL urlObj = new URL(url);
|
||||
URLConnection urlConnection = urlObj.openConnection();
|
||||
urlConnection.setConnectTimeout(30 * 1000);
|
||||
urlConnection.setReadTimeout(60 * 1000);
|
||||
urlConnection.setDoInput(true);
|
||||
in = urlConnection.getInputStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 本机地址
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
|
||||
in = new FileInputStream(downloadPath);
|
||||
}
|
||||
return IOUtils.toByteArray(in);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("获取文件路径异常 {}", e);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(baos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,8 @@ public class MimeTypeUtils
|
||||
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
|
||||
"asf", "rm", "rmvb" };
|
||||
|
||||
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
|
||||
|
||||
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
|
||||
// 图片
|
||||
"bmp", "gif", "jpg", "jpeg", "png",
|
||||
@ -31,6 +33,8 @@ public class MimeTypeUtils
|
||||
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
|
||||
// 压缩文件
|
||||
"rar", "zip", "gz", "bz2",
|
||||
// 视频格式
|
||||
"mp4", "avi", "rmvb",
|
||||
// pdf
|
||||
"pdf" };
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ public class EscapeUtil
|
||||
|
||||
// special HTML characters
|
||||
TEXT['\''] = "'".toCharArray(); // 单引号
|
||||
TEXT['"'] = """.toCharArray(); // 单引号
|
||||
TEXT['"'] = """.toCharArray(); // 双引号
|
||||
TEXT['&'] = "&".toCharArray(); // &符
|
||||
TEXT['<'] = "<".toCharArray(); // 小于号
|
||||
TEXT['>'] = ">".toCharArray(); // 大于号
|
||||
@ -144,7 +144,10 @@ public class EscapeUtil
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String html = "alert('11111');";
|
||||
String html = "<script>alert(1);</script>";
|
||||
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
|
||||
// String html = "<123";
|
||||
// String html = "123>";
|
||||
System.out.println(EscapeUtil.clean(html));
|
||||
System.out.println(EscapeUtil.escape(html));
|
||||
System.out.println(EscapeUtil.unescape(html));
|
||||
|
||||
@ -131,7 +131,7 @@ public final class HTMLFilter
|
||||
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
|
||||
stripComment = true;
|
||||
encodeQuotes = true;
|
||||
alwaysMakeTags = true;
|
||||
alwaysMakeTags = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +208,7 @@ public final class HTMLFilter
|
||||
|
||||
s = processRemoveBlanks(s);
|
||||
|
||||
s = validateEntities(s);
|
||||
// s = validateEntities(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -245,6 +245,7 @@ public final class HTMLFilter
|
||||
// try and form html
|
||||
//
|
||||
s = regexReplace(P_END_ARROW, "", s);
|
||||
// 不追加结束标签
|
||||
s = regexReplace(P_BODY_TO_END, "<$1>", s);
|
||||
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -16,17 +15,19 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.DataValidation;
|
||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
@ -38,6 +39,7 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -50,7 +52,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.exception.CustomException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileTypeUtils;
|
||||
import com.ruoyi.common.utils.file.ImageUtils;
|
||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||
|
||||
/**
|
||||
@ -102,6 +107,21 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
private List<Object[]> fields;
|
||||
|
||||
/**
|
||||
* 最大高度
|
||||
*/
|
||||
private short maxHeight;
|
||||
|
||||
/**
|
||||
* 统计列表
|
||||
*/
|
||||
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
|
||||
|
||||
/**
|
||||
* 数字格式
|
||||
*/
|
||||
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
|
||||
|
||||
/**
|
||||
* 实体对象
|
||||
*/
|
||||
@ -199,13 +219,20 @@ public class ExcelUtil<T>
|
||||
// 设置类的私有字段属性可访问.
|
||||
field.setAccessible(true);
|
||||
Integer column = cellMap.get(attr.name());
|
||||
fieldsMap.put(column, field);
|
||||
if (column != null)
|
||||
{
|
||||
fieldsMap.put(column, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < rows; i++)
|
||||
{
|
||||
// 从第2行开始取数据,默认第一行是表头.
|
||||
Row row = sheet.getRow(i);
|
||||
if(row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
T entity = null;
|
||||
for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet())
|
||||
{
|
||||
@ -226,22 +253,30 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Convert.toStr(val);
|
||||
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
|
||||
if (StringUtils.isNotEmpty(dateFormat))
|
||||
{
|
||||
val = DateUtils.parseDateToStr(dateFormat, (Date) val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Convert.toStr(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
|
||||
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
|
||||
{
|
||||
val = Convert.toInt(val);
|
||||
}
|
||||
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
|
||||
else if (Long.TYPE == fieldType || Long.class == fieldType)
|
||||
{
|
||||
val = Convert.toLong(val);
|
||||
}
|
||||
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
|
||||
else if (Double.TYPE == fieldType || Double.class == fieldType)
|
||||
{
|
||||
val = Convert.toDouble(val);
|
||||
}
|
||||
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
|
||||
else if (Float.TYPE == fieldType || Float.class == fieldType)
|
||||
{
|
||||
val = Convert.toFloat(val);
|
||||
}
|
||||
@ -260,6 +295,10 @@ public class ExcelUtil<T>
|
||||
val = DateUtil.getJavaDate((Double) val);
|
||||
}
|
||||
}
|
||||
else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
|
||||
{
|
||||
val = Convert.toBool(val, false);
|
||||
}
|
||||
if (StringUtils.isNotNull(fieldType))
|
||||
{
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
@ -270,7 +309,11 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
||||
{
|
||||
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
|
||||
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.dictType()))
|
||||
{
|
||||
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
|
||||
}
|
||||
ReflectUtils.invokeSetter(entity, propertyName, val);
|
||||
}
|
||||
@ -334,6 +377,7 @@ public class ExcelUtil<T>
|
||||
if (Type.EXPORT.equals(type))
|
||||
{
|
||||
fillExcelData(index, row);
|
||||
addStatisticsRow();
|
||||
}
|
||||
}
|
||||
String filename = encodingFilename(sheetName);
|
||||
@ -440,6 +484,30 @@ public class ExcelUtil<T>
|
||||
headerFont.setColor(IndexedColors.WHITE.getIndex());
|
||||
style.setFont(headerFont);
|
||||
styles.put("header", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
Font totalFont = wb.createFont();
|
||||
totalFont.setFontName("Arial");
|
||||
totalFont.setFontHeightInPoints((short) 10);
|
||||
style.setFont(totalFont);
|
||||
styles.put("total", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.LEFT);
|
||||
styles.put("data1", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
styles.put("data2", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.RIGHT);
|
||||
styles.put("data3", style);
|
||||
|
||||
return styles;
|
||||
}
|
||||
@ -469,14 +537,56 @@ public class ExcelUtil<T>
|
||||
{
|
||||
if (ColumnType.STRING == attr.cellType())
|
||||
{
|
||||
cell.setCellType(CellType.NUMERIC);
|
||||
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
|
||||
}
|
||||
else if (ColumnType.NUMERIC == attr.cellType())
|
||||
{
|
||||
cell.setCellType(CellType.NUMERIC);
|
||||
cell.setCellValue(Integer.parseInt(value + ""));
|
||||
if (StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
|
||||
}
|
||||
}
|
||||
else if (ColumnType.IMAGE == attr.cellType())
|
||||
{
|
||||
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
|
||||
cell.getRow().getRowNum() + 1);
|
||||
String imagePath = Convert.toStr(value);
|
||||
if (StringUtils.isNotEmpty(imagePath))
|
||||
{
|
||||
byte[] data = ImageUtils.getImage(imagePath);
|
||||
getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
|
||||
cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取画布
|
||||
*/
|
||||
public static Drawing<?> getDrawingPatriarch(Sheet sheet)
|
||||
{
|
||||
if (sheet.getDrawingPatriarch() == null)
|
||||
{
|
||||
sheet.createDrawingPatriarch();
|
||||
}
|
||||
return sheet.getDrawingPatriarch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片类型,设置图片插入类型
|
||||
*/
|
||||
public int getImageType(byte[] value)
|
||||
{
|
||||
String type = FileTypeUtils.getFileExtendName(value);
|
||||
if ("JPG".equalsIgnoreCase(type))
|
||||
{
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
}
|
||||
else if ("PNG".equalsIgnoreCase(type))
|
||||
{
|
||||
return Workbook.PICTURE_TYPE_PNG;
|
||||
}
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -492,7 +602,6 @@ public class ExcelUtil<T>
|
||||
{
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
}
|
||||
// 如果设置了提示信息则鼠标放上去提示.
|
||||
if (StringUtils.isNotEmpty(attr.prompt()))
|
||||
@ -517,31 +626,43 @@ public class ExcelUtil<T>
|
||||
try
|
||||
{
|
||||
// 设置行高
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
row.setHeight(maxHeight);
|
||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||
if (attr.isExport())
|
||||
{
|
||||
// 创建cell
|
||||
cell = row.createCell(column);
|
||||
cell.setCellStyle(styles.get("data"));
|
||||
int align = attr.align().value();
|
||||
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
|
||||
|
||||
// 用于读取对象中的属性
|
||||
Object value = getTargetValue(vo, field, attr);
|
||||
String dateFormat = attr.dateFormat();
|
||||
String readConverterExp = attr.readConverterExp();
|
||||
String separator = attr.separator();
|
||||
String dictType = attr.dictType();
|
||||
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
|
||||
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
|
||||
}
|
||||
else if (value instanceof BigDecimal && -1 != attr.scale())
|
||||
{
|
||||
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置列类型
|
||||
setCellVo(value, attr, cell);
|
||||
}
|
||||
addStatisticsData(column, Convert.toStr(value), attr);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -613,28 +734,36 @@ public class ExcelUtil<T>
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String convertByExp(String propertyValue, String converterExp) throws Exception
|
||||
public static String convertByExp(String propertyValue, String converterExp, String separator)
|
||||
{
|
||||
try
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
String[] itemArray = item.split("=");
|
||||
if (StringUtils.containsAny(separator, propertyValue))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
if (itemArray[0].equals(value))
|
||||
{
|
||||
propertyString.append(itemArray[1] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[0].equals(propertyValue))
|
||||
{
|
||||
return itemArray[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -642,28 +771,109 @@ public class ExcelUtil<T>
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String reverseByExp(String propertyValue, String converterExp) throws Exception
|
||||
public static String reverseByExp(String propertyValue, String converterExp, String separator)
|
||||
{
|
||||
try
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
String[] itemArray = item.split("=");
|
||||
if (StringUtils.containsAny(separator, propertyValue))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
if (itemArray[1].equals(value))
|
||||
{
|
||||
propertyString.append(itemArray[0] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[1].equals(propertyValue))
|
||||
{
|
||||
return itemArray[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析字典值
|
||||
*
|
||||
* @param dictValue 字典值
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String convertDictByExp(String dictValue, String dictType, String separator)
|
||||
{
|
||||
return DictUtils.getDictLabel(dictType, dictValue, separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反向解析值字典值
|
||||
*
|
||||
* @param dictLabel 字典标签
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String reverseDictByExp(String dictLabel, String dictType, String separator)
|
||||
{
|
||||
return DictUtils.getDictValue(dictType, dictLabel, separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合计统计信息
|
||||
*/
|
||||
private void addStatisticsData(Integer index, String text, Excel entity)
|
||||
{
|
||||
if (entity != null && entity.isStatistics())
|
||||
{
|
||||
throw e;
|
||||
Double temp = 0D;
|
||||
if (!statistics.containsKey(index))
|
||||
{
|
||||
statistics.put(index, temp);
|
||||
}
|
||||
try
|
||||
{
|
||||
temp = Double.valueOf(text);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
}
|
||||
statistics.put(index, statistics.get(index) + temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建统计行
|
||||
*/
|
||||
public void addStatisticsRow()
|
||||
{
|
||||
if (statistics.size() > 0)
|
||||
{
|
||||
Cell cell = null;
|
||||
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
|
||||
Set<Integer> keys = statistics.keySet();
|
||||
cell = row.createCell(0);
|
||||
cell.setCellStyle(styles.get("total"));
|
||||
cell.setCellValue("合计");
|
||||
|
||||
for (Integer key : keys)
|
||||
{
|
||||
cell = row.createCell(key);
|
||||
cell.setCellStyle(styles.get("total"));
|
||||
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
|
||||
}
|
||||
statistics.clear();
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -732,12 +942,12 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
private Object getValue(Object o, String name) throws Exception
|
||||
{
|
||||
if (StringUtils.isNotEmpty(name))
|
||||
if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
|
||||
{
|
||||
Class<?> clazz = o.getClass();
|
||||
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
Method method = clazz.getMethod(methodName);
|
||||
o = method.invoke(o);
|
||||
Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
o = field.get(o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@ -771,6 +981,21 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||
this.maxHeight = getRowHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解获取最大行高
|
||||
*/
|
||||
public short getRowHeight()
|
||||
{
|
||||
double maxHeight = 0;
|
||||
for (Object[] os : this.fields)
|
||||
{
|
||||
Excel excel = (Excel) os[1];
|
||||
maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
|
||||
}
|
||||
return (short) (maxHeight * 20);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -832,18 +1057,18 @@ public class ExcelUtil<T>
|
||||
Cell cell = row.getCell(column);
|
||||
if (StringUtils.isNotNull(cell))
|
||||
{
|
||||
if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA)
|
||||
if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
|
||||
{
|
||||
val = cell.getNumericCellValue();
|
||||
if (HSSFDateUtil.isCellDateFormatted(cell))
|
||||
if (DateUtil.isCellDateFormatted(cell))
|
||||
{
|
||||
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Double) val % 1 > 0)
|
||||
if ((Double) val % 1 != 0)
|
||||
{
|
||||
val = new DecimalFormat("0.00").format(val);
|
||||
val = new BigDecimal(val.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -851,15 +1076,15 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.STRING)
|
||||
else if (cell.getCellType() == CellType.STRING)
|
||||
{
|
||||
val = cell.getStringCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.BOOLEAN)
|
||||
else if (cell.getCellType() == CellType.BOOLEAN)
|
||||
{
|
||||
val = cell.getBooleanCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.ERROR)
|
||||
else if (cell.getCellType() == CellType.ERROR)
|
||||
{
|
||||
val = cell.getErrorCellValue();
|
||||
}
|
||||
|
||||
@ -204,6 +204,10 @@ public class ReflectUtils
|
||||
args[i] = DateUtil.getJavaDate((Double) args[i]);
|
||||
}
|
||||
}
|
||||
else if (cs[i] == boolean.class || cs[i] == Boolean.class)
|
||||
{
|
||||
args[i] = Convert.toBool(args[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (E) method.invoke(obj, args);
|
||||
|
||||
@ -5,7 +5,10 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* spring工具类 方便在非spring管理环境中获取bean
|
||||
@ -13,17 +16,25 @@ import org.springframework.stereotype.Component;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
|
||||
{
|
||||
/** Spring应用上下文环境 */
|
||||
private static ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
{
|
||||
SpringUtils.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
SpringUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
*
|
||||
@ -111,4 +122,25 @@ public final class SpringUtils implements BeanFactoryPostProcessor
|
||||
{
|
||||
return (T) AopContext.currentProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的环境配置,无配置返回null
|
||||
*
|
||||
* @return 当前的环境配置
|
||||
*/
|
||||
public static String[] getActiveProfiles()
|
||||
{
|
||||
return applicationContext.getEnvironment().getActiveProfiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
|
||||
*
|
||||
* @return 当前的环境配置
|
||||
*/
|
||||
public static String getActiveProfile()
|
||||
{
|
||||
final String[] activeProfiles = getActiveProfiles();
|
||||
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.ruoyi.common.utils.sql;
|
||||
|
||||
import com.ruoyi.common.exception.BaseException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
@ -10,9 +11,9 @@ import com.ruoyi.common.utils.StringUtils;
|
||||
public class SqlUtil
|
||||
{
|
||||
/**
|
||||
* 仅支持字母、数字、下划线、空格、逗号(支持多个字段排序)
|
||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||
*/
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,]+";
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
||||
|
||||
/**
|
||||
* 检查字符,防止注入绕过
|
||||
@ -21,7 +22,7 @@ public class SqlUtil
|
||||
{
|
||||
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
throw new BaseException("参数不符合规范,不能进行查询");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.ruoyi.common.utils.uuid;
|
||||
|
||||
import com.ruoyi.common.utils.uuid.UUID;
|
||||
|
||||
/**
|
||||
* ID生成器工具类
|
||||
*
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -35,22 +35,24 @@
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
||||
@ -20,7 +20,7 @@ import com.ruoyi.framework.web.service.TokenService;
|
||||
|
||||
/**
|
||||
* 数据过滤处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@ -66,6 +66,7 @@ public class DataScopeAspect
|
||||
@Before("dataScopePointCut()")
|
||||
public void doBefore(JoinPoint point) throws Throwable
|
||||
{
|
||||
clearDataScope(point);
|
||||
handleDataScope(point);
|
||||
}
|
||||
|
||||
@ -79,11 +80,11 @@ public class DataScopeAspect
|
||||
}
|
||||
// 获取当前的用户
|
||||
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
if (currentUser != null)
|
||||
if (StringUtils.isNotNull(loginUser))
|
||||
{
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
// 如果是超级管理员,则不过滤数据
|
||||
if (!currentUser.isAdmin())
|
||||
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
|
||||
{
|
||||
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
|
||||
controllerDataScope.userAlias());
|
||||
@ -93,10 +94,10 @@ public class DataScopeAspect
|
||||
|
||||
/**
|
||||
* 数据范围过滤
|
||||
*
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param user 用户
|
||||
* @param alias 别名
|
||||
* @param userAlias 别名
|
||||
*/
|
||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
|
||||
{
|
||||
@ -142,8 +143,12 @@ public class DataScopeAspect
|
||||
|
||||
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||
{
|
||||
BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0];
|
||||
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
|
||||
{
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,4 +167,17 @@ public class DataScopeAspect
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接权限sql前先清空params.dataScope参数防止注入
|
||||
*/
|
||||
private void clearDataScope(final JoinPoint joinPoint)
|
||||
{
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
|
||||
{
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.ruoyi.framework.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -14,6 +16,7 @@ import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -194,7 +197,7 @@ public class LogAspect
|
||||
{
|
||||
for (int i = 0; i < paramsArray.length; i++)
|
||||
{
|
||||
if (!isFilterObject(paramsArray[i]))
|
||||
if (StringUtils.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i]))
|
||||
{
|
||||
Object jsonObj = JSON.toJSON(paramsArray[i]);
|
||||
params += jsonObj.toString() + " ";
|
||||
@ -210,8 +213,32 @@ public class LogAspect
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean isFilterObject(final Object o)
|
||||
{
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray())
|
||||
{
|
||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||
}
|
||||
else if (Collection.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Collection collection = (Collection) o;
|
||||
for (Iterator iter = collection.iterator(); iter.hasNext();)
|
||||
{
|
||||
return iter.next() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Map map = (Map) o;
|
||||
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
return entry.getValue() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
||||
|| o instanceof BindingResult;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,83 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import static com.google.code.kaptcha.Constants.*;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class CaptchaConfig
|
||||
{
|
||||
@Bean(name = "captchaProducer")
|
||||
public DefaultKaptcha getKaptchaBean()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
|
||||
@Bean(name = "captchaProducerMath")
|
||||
public DefaultKaptcha getKaptchaBeanMath()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
|
||||
// 验证码文本生成器
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
|
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
|
||||
// 干扰实现类
|
||||
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.Random;
|
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
|
||||
|
||||
/**
|
||||
* 验证码文本生成器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class KaptchaTextCreator extends DefaultTextCreator
|
||||
{
|
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
Integer result = 0;
|
||||
Random random = new Random();
|
||||
int x = random.nextInt(10);
|
||||
int y = random.nextInt(10);
|
||||
StringBuilder suChinese = new StringBuilder();
|
||||
int randomoperands = (int) Math.round(Math.random() * 2);
|
||||
if (randomoperands == 0)
|
||||
{
|
||||
result = x * y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("*");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else if (randomoperands == 1)
|
||||
{
|
||||
if (!(x == 0) && y % x == 0)
|
||||
{
|
||||
result = y / x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("/");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
}
|
||||
else if (randomoperands == 2)
|
||||
{
|
||||
if (x >= y)
|
||||
{
|
||||
result = x - y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = y - x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
suChinese.append("=?@" + result);
|
||||
return suChinese.toString();
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.ruoyi.framework.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import javax.sql.DataSource;
|
||||
@ -21,6 +22,7 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Mybatis支持*匹配扫描包
|
||||
@ -89,6 +91,28 @@ public class MyBatisConfig
|
||||
return typeAliasesPackage;
|
||||
}
|
||||
|
||||
public Resource[] resolveMapperLocations(String[] mapperLocations)
|
||||
{
|
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
if (mapperLocations != null)
|
||||
{
|
||||
for (String mapperLocation : mapperLocations)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource[] mappers = resourceResolver.getResources(mapperLocation);
|
||||
resources.addAll(Arrays.asList(mappers));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return resources.toArray(new Resource[resources.size()]);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
||||
{
|
||||
@ -101,7 +125,7 @@ public class MyBatisConfig
|
||||
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||
sessionFactory.setDataSource(dataSource);
|
||||
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
|
||||
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
|
||||
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||
return sessionFactory.getObject();
|
||||
}
|
||||
|
||||
@ -8,8 +8,10 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
@ -31,12 +33,17 @@ public class RedisConfig extends CachingConfigurerSupport
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
serializer.setObjectMapper(mapper);
|
||||
|
||||
template.setValueSerializer(serializer);
|
||||
// 使用StringRedisSerializer来序列化和反序列化redis的key值
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(serializer);
|
||||
|
||||
// Hash的key也采用StringRedisSerializer的序列化方式
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
template.setHashValueSerializer(serializer);
|
||||
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@ -27,8 +31,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
|
||||
|
||||
/** swagger配置 */
|
||||
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,4 +42,24 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
{
|
||||
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
||||
}
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*/
|
||||
@Bean
|
||||
public CorsFilter corsFilter()
|
||||
{
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
// 设置访问源地址
|
||||
config.addAllowedOrigin("*");
|
||||
// 设置访问源请求头
|
||||
config.addAllowedHeader("*");
|
||||
// 设置访问源请求方法
|
||||
config.addAllowedMethod("*");
|
||||
// 对接口配置跨域设置
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
@ -47,6 +49,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
*/
|
||||
@Autowired
|
||||
private JwtAuthenticationTokenFilter authenticationTokenFilter;
|
||||
|
||||
/**
|
||||
* 跨域过滤器
|
||||
*/
|
||||
@Autowired
|
||||
private CorsFilter corsFilter;
|
||||
|
||||
/**
|
||||
* 解决 无法直接注入 AuthenticationManager
|
||||
@ -80,7 +88,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception
|
||||
{
|
||||
httpSecurity
|
||||
// CRSF禁用,因为不使用session
|
||||
// CSRF禁用,因为不使用session
|
||||
.csrf().disable()
|
||||
// 认证失败处理类
|
||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
||||
@ -92,12 +100,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
.antMatchers("/login", "/captchaImage").anonymous()
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/",
|
||||
"/*.html",
|
||||
"/**/*.html",
|
||||
"/**/*.css",
|
||||
"/**/*.js"
|
||||
"/**/*.js",
|
||||
"/profile/**"
|
||||
).permitAll()
|
||||
.antMatchers("/profile/**").anonymous()
|
||||
.antMatchers("/common/download**").anonymous()
|
||||
.antMatchers("/common/download/resource**").anonymous()
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
@ -112,6 +121,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
||||
// 添加JWT filter
|
||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
// 添加CORS filter
|
||||
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
|
||||
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import com.ruoyi.common.utils.ServletUtils;
|
||||
|
||||
/**
|
||||
* 防止重复提交拦截器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
@ -46,8 +46,8 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
|
||||
|
||||
/**
|
||||
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
||||
*
|
||||
* @param httpServletRequest
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@ -5,8 +5,10 @@ import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
@ -26,7 +28,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
|
||||
public final String REPEAT_TIME = "repeatTime";
|
||||
|
||||
public final String CACHE_REPEAT_KEY = "repeatData";
|
||||
// 令牌自定义标识
|
||||
@Value("${token.header}")
|
||||
private String header;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@ -47,8 +51,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
@Override
|
||||
public boolean isRepeatSubmit(HttpServletRequest request)
|
||||
{
|
||||
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
|
||||
String nowParams = HttpHelper.getBodyString(repeatedlyRequest);
|
||||
String nowParams = "";
|
||||
if (request instanceof RepeatedlyRequestWrapper)
|
||||
{
|
||||
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
|
||||
nowParams = HttpHelper.getBodyString(repeatedlyRequest);
|
||||
}
|
||||
|
||||
// body参数为空,获取Parameter的数据
|
||||
if (StringUtils.isEmpty(nowParams))
|
||||
@ -62,7 +70,17 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
// 请求地址(作为存放cache的key值)
|
||||
String url = request.getRequestURI();
|
||||
|
||||
Object sessionObj = redisCache.getCacheObject(CACHE_REPEAT_KEY);
|
||||
// 唯一值(没有消息头则使用请求地址)
|
||||
String submitKey = request.getHeader(header);
|
||||
if (StringUtils.isEmpty(submitKey))
|
||||
{
|
||||
submitKey = url;
|
||||
}
|
||||
|
||||
// 唯一标识(指定key + 消息头)
|
||||
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
|
||||
|
||||
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
|
||||
if (sessionObj != null)
|
||||
{
|
||||
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
|
||||
@ -77,7 +95,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
}
|
||||
Map<String, Object> cacheMap = new HashMap<String, Object>();
|
||||
cacheMap.put(url, nowDataMap);
|
||||
redisCache.setCacheObject(CACHE_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS);
|
||||
redisCache.setCacheObject(cacheRepeatKey, cacheMap, intervalTime, TimeUnit.SECONDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ public class AsyncFactory
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* 记录登陆信息
|
||||
* 记录登录信息
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param status 状态
|
||||
|
||||
@ -189,7 +189,7 @@ public class Server
|
||||
private void setSysFiles(OperatingSystem os)
|
||||
{
|
||||
FileSystem fileSystem = os.getFileSystem();
|
||||
OSFileStore[] fsArray = fileSystem.getFileStores();
|
||||
List<OSFileStore> fsArray = fileSystem.getFileStores();
|
||||
for (OSFileStore fs : fsArray)
|
||||
{
|
||||
long free = fs.getUsableSpace();
|
||||
|
||||
@ -109,7 +109,7 @@ public class PermissionService
|
||||
for (SysRole sysRole : loginUser.getUser().getRoles())
|
||||
{
|
||||
String roleKey = sysRole.getRoleKey();
|
||||
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(StringUtils.trim(role)))
|
||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8,15 +8,20 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.exception.CustomException;
|
||||
import com.ruoyi.common.exception.user.CaptchaException;
|
||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.ip.IpUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
@ -34,6 +39,9 @@ public class SysLoginService
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
@ -82,7 +90,18 @@ public class SysLoginService
|
||||
}
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
|
||||
recordLoginInfo(loginUser.getUser());
|
||||
// 生成token
|
||||
return tokenService.createToken(loginUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(SysUser user)
|
||||
{
|
||||
user.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
||||
user.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUserProfile(user);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
||||
/**
|
||||
* token验证处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
@ -51,7 +51,7 @@ public class TokenService
|
||||
|
||||
/**
|
||||
* 获取用户身份信息
|
||||
*
|
||||
*
|
||||
* @return 用户信息
|
||||
*/
|
||||
public LoginUser getLoginUser(HttpServletRequest request)
|
||||
@ -95,7 +95,7 @@ public class TokenService
|
||||
|
||||
/**
|
||||
* 创建令牌
|
||||
*
|
||||
*
|
||||
* @param loginUser 用户信息
|
||||
* @return 令牌
|
||||
*/
|
||||
@ -113,8 +113,8 @@ public class TokenService
|
||||
|
||||
/**
|
||||
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
|
||||
*
|
||||
* @param token 令牌
|
||||
*
|
||||
* @param loginUser
|
||||
* @return 令牌
|
||||
*/
|
||||
public void verifyToken(LoginUser loginUser)
|
||||
@ -129,7 +129,7 @@ public class TokenService
|
||||
|
||||
/**
|
||||
* 刷新令牌有效期
|
||||
*
|
||||
*
|
||||
* @param loginUser 登录信息
|
||||
*/
|
||||
public void refreshToken(LoginUser loginUser)
|
||||
@ -140,10 +140,10 @@ public class TokenService
|
||||
String userKey = getTokenKey(loginUser.getToken());
|
||||
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置用户代理信息
|
||||
*
|
||||
*
|
||||
* @param loginUser 登录信息
|
||||
*/
|
||||
public void setUserAgent(LoginUser loginUser)
|
||||
@ -155,7 +155,7 @@ public class TokenService
|
||||
loginUser.setBrowser(userAgent.getBrowser().getName());
|
||||
loginUser.setOs(userAgent.getOperatingSystem().getName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从数据声明生成令牌
|
||||
*
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -23,6 +23,12 @@
|
||||
<artifactId>velocity</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- collections工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
||||
@ -63,10 +63,12 @@ public class GenController extends BaseController
|
||||
public AjaxResult getInfo(@PathVariable Long talbleId)
|
||||
{
|
||||
GenTable table = genTableService.selectGenTableById(talbleId);
|
||||
List<GenTable> tables = genTableService.selectGenTableAll();
|
||||
List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(talbleId);
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("info", table);
|
||||
map.put("rows", list);
|
||||
map.put("tables", tables);
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
|
||||
@ -99,7 +101,7 @@ public class GenController extends BaseController
|
||||
/**
|
||||
* 导入表结构(保存)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:list')")
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:import')")
|
||||
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importTable")
|
||||
public AjaxResult importTableSave(String tables)
|
||||
@ -148,15 +150,39 @@ public class GenController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
|
||||
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
|
||||
@GetMapping("/download/{tableName}")
|
||||
public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
|
||||
{
|
||||
byte[] data = genTableService.downloadCode(tableName);
|
||||
genCode(response, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码(自定义路径)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
|
||||
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
|
||||
@GetMapping("/genCode/{tableName}")
|
||||
public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
|
||||
public AjaxResult genCode(@PathVariable("tableName") String tableName)
|
||||
{
|
||||
byte[] data = genTableService.generatorCode(tableName);
|
||||
genCode(response, data);
|
||||
genTableService.generatorCode(tableName);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:edit')")
|
||||
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
|
||||
@GetMapping("/synchDb/{tableName}")
|
||||
public AjaxResult synchDb(@PathVariable("tableName") String tableName)
|
||||
{
|
||||
genTableService.synchDb(tableName);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,7 +194,7 @@ public class GenController extends BaseController
|
||||
public void batchGenCode(HttpServletResponse response, String tables) throws IOException
|
||||
{
|
||||
String[] tableNames = Convert.toStrArray(tables);
|
||||
byte[] data = genTableService.generatorCode(tableNames);
|
||||
byte[] data = genTableService.downloadCode(tableNames);
|
||||
genCode(response, data);
|
||||
}
|
||||
|
||||
@ -178,9 +204,11 @@ public class GenController extends BaseController
|
||||
private void genCode(HttpServletResponse response, byte[] data) throws IOException
|
||||
{
|
||||
response.reset();
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
|
||||
response.addHeader("Content-Length", "" + data.length);
|
||||
response.setContentType("application/octet-stream; charset=UTF-8");
|
||||
IOUtils.write(data, response.getOutputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,11 +28,17 @@ public class GenTable extends BaseEntity
|
||||
@NotBlank(message = "表描述不能为空")
|
||||
private String tableComment;
|
||||
|
||||
/** 关联父表的表名 */
|
||||
private String subTableName;
|
||||
|
||||
/** 本表关联父表的外键名 */
|
||||
private String subTableFkName;
|
||||
|
||||
/** 实体类名称(首字母大写) */
|
||||
@NotBlank(message = "实体类名称不能为空")
|
||||
private String className;
|
||||
|
||||
/** 使用的模板(crud单表操作 tree树表操作) */
|
||||
/** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */
|
||||
private String tplCategory;
|
||||
|
||||
/** 生成包路径 */
|
||||
@ -55,9 +61,18 @@ public class GenTable extends BaseEntity
|
||||
@NotBlank(message = "作者不能为空")
|
||||
private String functionAuthor;
|
||||
|
||||
/** 生成代码方式(0zip压缩包 1自定义路径) */
|
||||
private String genType;
|
||||
|
||||
/** 生成路径(不填默认项目路径) */
|
||||
private String genPath;
|
||||
|
||||
/** 主键信息 */
|
||||
private GenTableColumn pkColumn;
|
||||
|
||||
/** 子表信息 */
|
||||
private GenTable subTable;
|
||||
|
||||
/** 表列信息 */
|
||||
@Valid
|
||||
private List<GenTableColumn> columns;
|
||||
@ -74,6 +89,12 @@ public class GenTable extends BaseEntity
|
||||
/** 树名称字段 */
|
||||
private String treeName;
|
||||
|
||||
/** 上级菜单ID字段 */
|
||||
private String parentMenuId;
|
||||
|
||||
/** 上级菜单名称字段 */
|
||||
private String parentMenuName;
|
||||
|
||||
public Long getTableId()
|
||||
{
|
||||
return tableId;
|
||||
@ -104,6 +125,26 @@ public class GenTable extends BaseEntity
|
||||
this.tableComment = tableComment;
|
||||
}
|
||||
|
||||
public String getSubTableName()
|
||||
{
|
||||
return subTableName;
|
||||
}
|
||||
|
||||
public void setSubTableName(String subTableName)
|
||||
{
|
||||
this.subTableName = subTableName;
|
||||
}
|
||||
|
||||
public String getSubTableFkName()
|
||||
{
|
||||
return subTableFkName;
|
||||
}
|
||||
|
||||
public void setSubTableFkName(String subTableFkName)
|
||||
{
|
||||
this.subTableFkName = subTableFkName;
|
||||
}
|
||||
|
||||
public String getClassName()
|
||||
{
|
||||
return className;
|
||||
@ -174,6 +215,26 @@ public class GenTable extends BaseEntity
|
||||
this.functionAuthor = functionAuthor;
|
||||
}
|
||||
|
||||
public String getGenType()
|
||||
{
|
||||
return genType;
|
||||
}
|
||||
|
||||
public void setGenType(String genType)
|
||||
{
|
||||
this.genType = genType;
|
||||
}
|
||||
|
||||
public String getGenPath()
|
||||
{
|
||||
return genPath;
|
||||
}
|
||||
|
||||
public void setGenPath(String genPath)
|
||||
{
|
||||
this.genPath = genPath;
|
||||
}
|
||||
|
||||
public GenTableColumn getPkColumn()
|
||||
{
|
||||
return pkColumn;
|
||||
@ -184,6 +245,16 @@ public class GenTable extends BaseEntity
|
||||
this.pkColumn = pkColumn;
|
||||
}
|
||||
|
||||
public GenTable getSubTable()
|
||||
{
|
||||
return subTable;
|
||||
}
|
||||
|
||||
public void setSubTable(GenTable subTable)
|
||||
{
|
||||
this.subTable = subTable;
|
||||
}
|
||||
|
||||
public List<GenTableColumn> getColumns()
|
||||
{
|
||||
return columns;
|
||||
@ -234,6 +305,36 @@ public class GenTable extends BaseEntity
|
||||
this.treeName = treeName;
|
||||
}
|
||||
|
||||
public String getParentMenuId()
|
||||
{
|
||||
return parentMenuId;
|
||||
}
|
||||
|
||||
public void setParentMenuId(String parentMenuId)
|
||||
{
|
||||
this.parentMenuId = parentMenuId;
|
||||
}
|
||||
|
||||
public String getParentMenuName()
|
||||
{
|
||||
return parentMenuName;
|
||||
}
|
||||
|
||||
public void setParentMenuName(String parentMenuName)
|
||||
{
|
||||
this.parentMenuName = parentMenuName;
|
||||
}
|
||||
|
||||
public boolean isSub()
|
||||
{
|
||||
return isSub(this.tplCategory);
|
||||
}
|
||||
|
||||
public static boolean isSub(String tplCategory)
|
||||
{
|
||||
return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory);
|
||||
}
|
||||
|
||||
public boolean isTree()
|
||||
{
|
||||
return isTree(this.tplCategory);
|
||||
@ -268,4 +369,4 @@ public class GenTable extends BaseEntity
|
||||
}
|
||||
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ public class GenTableColumn extends BaseEntity
|
||||
/** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
|
||||
private String queryType;
|
||||
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件) */
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、image图片上传控件、upload文件上传控件、editor富文本控件) */
|
||||
private String htmlType;
|
||||
|
||||
/** 字典类型 */
|
||||
@ -138,6 +138,11 @@ public class GenTableColumn extends BaseEntity
|
||||
return javaField;
|
||||
}
|
||||
|
||||
public String getCapJavaField()
|
||||
{
|
||||
return StringUtils.capitalize(javaField);
|
||||
}
|
||||
|
||||
public void setIsPk(String isPk)
|
||||
{
|
||||
this.isPk = isPk;
|
||||
@ -340,7 +345,7 @@ public class GenTableColumn extends BaseEntity
|
||||
public static boolean isUsableColumn(String javaField)
|
||||
{
|
||||
// isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单
|
||||
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum");
|
||||
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
|
||||
}
|
||||
|
||||
public String readConverterExp()
|
||||
|
||||
@ -17,7 +17,7 @@ public interface GenTableColumnMapper
|
||||
* @return 列信息
|
||||
*/
|
||||
public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
|
||||
|
||||
|
||||
/**
|
||||
* 查询业务字段列表
|
||||
*
|
||||
@ -42,6 +42,14 @@ public interface GenTableColumnMapper
|
||||
*/
|
||||
public int updateGenTableColumn(GenTableColumn genTableColumn);
|
||||
|
||||
/**
|
||||
* 删除业务字段
|
||||
*
|
||||
* @param genTableColumns 列数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
|
||||
|
||||
/**
|
||||
* 批量删除业务字段
|
||||
*
|
||||
|
||||
@ -34,6 +34,13 @@ public interface GenTableMapper
|
||||
*/
|
||||
public List<GenTable> selectDbTableListByNames(String[] tableNames);
|
||||
|
||||
/**
|
||||
* 查询所有表信息
|
||||
*
|
||||
* @return 表信息集合
|
||||
*/
|
||||
public List<GenTable> selectGenTableAll();
|
||||
|
||||
/**
|
||||
* 查询表ID业务信息
|
||||
*
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
package com.ruoyi.generator.service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
@ -21,6 +24,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.GenConstants;
|
||||
import com.ruoyi.common.core.text.CharsetKit;
|
||||
import com.ruoyi.common.exception.CustomException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
@ -98,6 +102,17 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
return genTableMapper.selectDbTableListByNames(tableNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有表信息
|
||||
*
|
||||
* @return 表信息集合
|
||||
*/
|
||||
@Override
|
||||
public List<GenTable> selectGenTableAll()
|
||||
{
|
||||
return genTableMapper.selectGenTableAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改业务
|
||||
*
|
||||
@ -181,9 +196,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
Map<String, String> dataMap = new LinkedHashMap<>();
|
||||
// 查询表信息
|
||||
GenTable table = genTableMapper.selectGenTableById(tableId);
|
||||
// 查询列信息
|
||||
List<GenTableColumn> columns = table.getColumns();
|
||||
setPkColumn(table, columns);
|
||||
// 设置主子表信息
|
||||
setSubTable(table);
|
||||
// 设置主键列信息
|
||||
setPkColumn(table);
|
||||
VelocityInitializer.initVelocity();
|
||||
|
||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||
@ -202,13 +218,13 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String tableName)
|
||||
public byte[] downloadCode(String tableName)
|
||||
{
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
@ -218,13 +234,90 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成代码
|
||||
* 生成代码(自定义路径)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
@Override
|
||||
public void generatorCode(String tableName)
|
||||
{
|
||||
// 查询表信息
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
// 设置主子表信息
|
||||
setSubTable(table);
|
||||
// 设置主键列信息
|
||||
setPkColumn(table);
|
||||
|
||||
VelocityInitializer.initVelocity();
|
||||
|
||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||
|
||||
// 获取模板列表
|
||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
||||
for (String template : templates)
|
||||
{
|
||||
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
|
||||
{
|
||||
// 渲染模板
|
||||
StringWriter sw = new StringWriter();
|
||||
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
|
||||
tpl.merge(context, sw);
|
||||
try
|
||||
{
|
||||
String path = getGenPath(table, template);
|
||||
FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CustomException("渲染模板失败,表名:" + table.getTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void synchDb(String tableName)
|
||||
{
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
List<GenTableColumn> tableColumns = table.getColumns();
|
||||
List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
|
||||
|
||||
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
|
||||
if (StringUtils.isEmpty(dbTableColumns))
|
||||
{
|
||||
throw new CustomException("同步数据失败,原表结构不存在");
|
||||
}
|
||||
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
|
||||
|
||||
dbTableColumns.forEach(column -> {
|
||||
if (!tableColumnNames.contains(column.getColumnName()))
|
||||
{
|
||||
GenUtils.initColumnField(column, table);
|
||||
genTableColumnMapper.insertGenTableColumn(column);
|
||||
}
|
||||
});
|
||||
|
||||
List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
|
||||
if (StringUtils.isNotEmpty(delColumns))
|
||||
{
|
||||
genTableColumnMapper.deleteGenTableColumns(delColumns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成代码(下载方式)
|
||||
*
|
||||
* @param tableNames 表数组
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String[] tableNames)
|
||||
public byte[] downloadCode(String[] tableNames)
|
||||
{
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
@ -243,9 +336,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
{
|
||||
// 查询表信息
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
// 查询列信息
|
||||
List<GenTableColumn> columns = table.getColumns();
|
||||
setPkColumn(table, columns);
|
||||
// 设置主子表信息
|
||||
setSubTable(table);
|
||||
// 设置主键列信息
|
||||
setPkColumn(table);
|
||||
|
||||
VelocityInitializer.initVelocity();
|
||||
|
||||
@ -299,6 +393,17 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
{
|
||||
throw new CustomException("树名称字段不能为空");
|
||||
}
|
||||
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
|
||||
{
|
||||
if (StringUtils.isEmpty(genTable.getSubTableName()))
|
||||
{
|
||||
throw new CustomException("关联子表的表名不能为空");
|
||||
}
|
||||
else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
|
||||
{
|
||||
throw new CustomException("子表关联的外键名不能为空");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,11 +411,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
* 设置主键列信息
|
||||
*
|
||||
* @param table 业务表信息
|
||||
* @param columns 业务字段列表
|
||||
*/
|
||||
public void setPkColumn(GenTable table, List<GenTableColumn> columns)
|
||||
public void setPkColumn(GenTable table)
|
||||
{
|
||||
for (GenTableColumn column : columns)
|
||||
for (GenTableColumn column : table.getColumns())
|
||||
{
|
||||
if (column.isPk())
|
||||
{
|
||||
@ -320,7 +424,36 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
if (StringUtils.isNull(table.getPkColumn()))
|
||||
{
|
||||
table.setPkColumn(columns.get(0));
|
||||
table.setPkColumn(table.getColumns().get(0));
|
||||
}
|
||||
if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
|
||||
{
|
||||
for (GenTableColumn column : table.getSubTable().getColumns())
|
||||
{
|
||||
if (column.isPk())
|
||||
{
|
||||
table.getSubTable().setPkColumn(column);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNull(table.getSubTable().getPkColumn()))
|
||||
{
|
||||
table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主子表信息
|
||||
*
|
||||
* @param table 业务表信息
|
||||
*/
|
||||
public void setSubTable(GenTable table)
|
||||
{
|
||||
String subTableName = table.getSubTableName();
|
||||
if (StringUtils.isNotEmpty(subTableName))
|
||||
{
|
||||
table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,9 +470,31 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
|
||||
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
|
||||
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
|
||||
String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
|
||||
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
|
||||
|
||||
genTable.setTreeCode(treeCode);
|
||||
genTable.setTreeParentCode(treeParentCode);
|
||||
genTable.setTreeName(treeName);
|
||||
genTable.setParentMenuId(parentMenuId);
|
||||
genTable.setParentMenuName(parentMenuName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代码生成地址
|
||||
*
|
||||
* @param table 业务表信息
|
||||
* @param template 模板文件路径
|
||||
* @return 生成地址
|
||||
*/
|
||||
public static String getGenPath(GenTable table, String template)
|
||||
{
|
||||
String genPath = table.getGenPath();
|
||||
if (StringUtils.equals(genPath, "/"))
|
||||
{
|
||||
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
|
||||
}
|
||||
return genPath + File.separator + VelocityUtils.getFileName(template, table);
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,13 @@ public interface IGenTableService
|
||||
*/
|
||||
public List<GenTable> selectDbTableListByNames(String[] tableNames);
|
||||
|
||||
/**
|
||||
* 查询所有表信息
|
||||
*
|
||||
* @return 表信息集合
|
||||
*/
|
||||
public List<GenTable> selectGenTableAll();
|
||||
|
||||
/**
|
||||
* 查询业务信息
|
||||
*
|
||||
@ -75,20 +82,35 @@ public interface IGenTableService
|
||||
public Map<String, String> previewCode(Long tableId);
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
public byte[] generatorCode(String tableName);
|
||||
public byte[] downloadCode(String tableName);
|
||||
|
||||
/**
|
||||
* 批量生成代码
|
||||
* 生成代码(自定义路径)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
public void generatorCode(String tableName);
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
public void synchDb(String tableName);
|
||||
|
||||
/**
|
||||
* 批量生成代码(下载方式)
|
||||
*
|
||||
* @param tableNames 表数组
|
||||
* @return 数据
|
||||
*/
|
||||
public byte[] generatorCode(String[] tableNames);
|
||||
public byte[] downloadCode(String[] tableNames);
|
||||
|
||||
/**
|
||||
* 修改保存参数校验
|
||||
|
||||
@ -40,13 +40,14 @@ public class GenUtils
|
||||
column.setCreateBy(table.getCreateBy());
|
||||
// 设置java字段名
|
||||
column.setJavaField(StringUtils.toCamelCase(columnName));
|
||||
// 设置默认类型
|
||||
column.setJavaType(GenConstants.TYPE_STRING);
|
||||
|
||||
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType))
|
||||
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
|
||||
{
|
||||
column.setJavaType(GenConstants.TYPE_STRING);
|
||||
// 字符串长度超过500设置为文本域
|
||||
Integer columnLength = getColumnLength(column.getColumnType());
|
||||
String htmlType = columnLength >= 500 ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
||||
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
||||
column.setHtmlType(htmlType);
|
||||
}
|
||||
else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
|
||||
@ -111,6 +112,21 @@ public class GenUtils
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_SELECT);
|
||||
}
|
||||
// 图片字段设置图片上传控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
|
||||
}
|
||||
// 文件字段设置文件上传控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
|
||||
}
|
||||
// 内容字段设置富文本控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_EDITOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,7 +211,7 @@ public class GenUtils
|
||||
/**
|
||||
* 关键字替换
|
||||
*
|
||||
* @param name 需要被替换的名字
|
||||
* @param text 需要被替换的名字
|
||||
* @return 替换后的名字
|
||||
*/
|
||||
public static String replaceText(String text)
|
||||
|
||||
@ -7,7 +7,7 @@ import com.ruoyi.common.constant.Constants;
|
||||
/**
|
||||
* VelocityEngine工厂
|
||||
*
|
||||
* @author RuoYi
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class VelocityInitializer
|
||||
{
|
||||
@ -22,7 +22,7 @@ public class VelocityInitializer
|
||||
// 加载classpath目录下的vm文件
|
||||
p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||
// 定义字符集
|
||||
p.setProperty(Velocity.ENCODING_DEFAULT, Constants.UTF8);
|
||||
p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
|
||||
p.setProperty(Velocity.OUTPUT_ENCODING, Constants.UTF8);
|
||||
// 初始化Velocity引擎,指定配置Properties
|
||||
Velocity.init(p);
|
||||
|
||||
@ -12,7 +12,7 @@ import com.ruoyi.generator.domain.GenTable;
|
||||
import com.ruoyi.generator.domain.GenTableColumn;
|
||||
|
||||
/**
|
||||
* 代码生成模板处理
|
||||
* 模板处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@ -24,9 +24,12 @@ public class VelocityUtils
|
||||
/** mybatis空间路径 */
|
||||
private static final String MYBATIS_PATH = "main/resources/mapper";
|
||||
|
||||
/** 默认上级菜单,系统工具 */
|
||||
private static final String DEFAULT_PARENT_MENU_ID = "3";
|
||||
|
||||
/**
|
||||
* 设置模板变量信息
|
||||
*
|
||||
*
|
||||
* @return 模板列表
|
||||
*/
|
||||
public static VelocityContext prepareContext(GenTable genTable)
|
||||
@ -51,17 +54,30 @@ public class VelocityUtils
|
||||
velocityContext.put("author", genTable.getFunctionAuthor());
|
||||
velocityContext.put("datetime", DateUtils.getDate());
|
||||
velocityContext.put("pkColumn", genTable.getPkColumn());
|
||||
velocityContext.put("importList", getImportList(genTable.getColumns()));
|
||||
velocityContext.put("importList", getImportList(genTable));
|
||||
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
|
||||
velocityContext.put("columns", genTable.getColumns());
|
||||
velocityContext.put("table", genTable);
|
||||
setMenuVelocityContext(velocityContext, genTable);
|
||||
if (GenConstants.TPL_TREE.equals(tplCategory))
|
||||
{
|
||||
setTreeVelocityContext(velocityContext, genTable);
|
||||
}
|
||||
if (GenConstants.TPL_SUB.equals(tplCategory))
|
||||
{
|
||||
setSubVelocityContext(velocityContext, genTable);
|
||||
}
|
||||
return velocityContext;
|
||||
}
|
||||
|
||||
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
|
||||
{
|
||||
String options = genTable.getOptions();
|
||||
JSONObject paramsObj = JSONObject.parseObject(options);
|
||||
String parentMenuId = getParentMenuId(paramsObj);
|
||||
context.put("parentMenuId", parentMenuId);
|
||||
}
|
||||
|
||||
public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
|
||||
{
|
||||
String options = genTable.getOptions();
|
||||
@ -84,9 +100,27 @@ public class VelocityUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static void setSubVelocityContext(VelocityContext context, GenTable genTable)
|
||||
{
|
||||
GenTable subTable = genTable.getSubTable();
|
||||
String subTableName = genTable.getSubTableName();
|
||||
String subTableFkName = genTable.getSubTableFkName();
|
||||
String subClassName = genTable.getSubTable().getClassName();
|
||||
String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
|
||||
|
||||
context.put("subTable", subTable);
|
||||
context.put("subTableName", subTableName);
|
||||
context.put("subTableFkName", subTableFkName);
|
||||
context.put("subTableFkClassName", subTableFkClassName);
|
||||
context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
|
||||
context.put("subClassName", subClassName);
|
||||
context.put("subclassName", StringUtils.uncapitalize(subClassName));
|
||||
context.put("subImportList", getImportList(genTable.getSubTable()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板信息
|
||||
*
|
||||
*
|
||||
* @return 模板列表
|
||||
*/
|
||||
public static List<String> getTemplateList(String tplCategory)
|
||||
@ -108,6 +142,11 @@ public class VelocityUtils
|
||||
{
|
||||
templates.add("vm/vue/index-tree.vue.vm");
|
||||
}
|
||||
else if (GenConstants.TPL_SUB.equals(tplCategory))
|
||||
{
|
||||
templates.add("vm/vue/index.vue.vm");
|
||||
templates.add("vm/java/sub-domain.java.vm");
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
@ -135,6 +174,10 @@ public class VelocityUtils
|
||||
{
|
||||
fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
|
||||
}
|
||||
if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
|
||||
{
|
||||
fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
|
||||
}
|
||||
else if (template.contains("mapper.java.vm"))
|
||||
{
|
||||
fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
|
||||
@ -176,7 +219,7 @@ public class VelocityUtils
|
||||
|
||||
/**
|
||||
* 获取包前缀
|
||||
*
|
||||
*
|
||||
* @param packageName 包名称
|
||||
* @return 包前缀名称
|
||||
*/
|
||||
@ -190,12 +233,18 @@ public class VelocityUtils
|
||||
/**
|
||||
* 根据列类型获取导入包
|
||||
*
|
||||
* @param column 列集合
|
||||
* @param genTable 业务表对象
|
||||
* @return 返回需要导入的包列表
|
||||
*/
|
||||
public static HashSet<String> getImportList(List<GenTableColumn> columns)
|
||||
public static HashSet<String> getImportList(GenTable genTable)
|
||||
{
|
||||
List<GenTableColumn> columns = genTable.getColumns();
|
||||
GenTable subGenTable = genTable.getSubTable();
|
||||
HashSet<String> importList = new HashSet<String>();
|
||||
if (StringUtils.isNotNull(subGenTable))
|
||||
{
|
||||
importList.add("java.util.List");
|
||||
}
|
||||
for (GenTableColumn column : columns)
|
||||
{
|
||||
if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType()))
|
||||
@ -213,7 +262,7 @@ public class VelocityUtils
|
||||
|
||||
/**
|
||||
* 获取权限前缀
|
||||
*
|
||||
*
|
||||
* @param moduleName 模块名称
|
||||
* @param businessName 业务名称
|
||||
* @return 返回权限前缀
|
||||
@ -221,13 +270,27 @@ public class VelocityUtils
|
||||
public static String getPermissionPrefix(String moduleName, String businessName)
|
||||
{
|
||||
return StringUtils.format("{}:{}", moduleName, businessName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上级菜单ID字段
|
||||
*
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 上级菜单ID字段
|
||||
*/
|
||||
public static String getParentMenuId(JSONObject paramsObj)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
|
||||
{
|
||||
return paramsObj.getString(GenConstants.PARENT_MENU_ID);
|
||||
}
|
||||
return DEFAULT_PARENT_MENU_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树编码
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
*
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树编码
|
||||
*/
|
||||
public static String getTreecode(JSONObject paramsObj)
|
||||
@ -236,13 +299,13 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树父编码
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
*
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树父编码
|
||||
*/
|
||||
public static String getTreeParentCode(JSONObject paramsObj)
|
||||
@ -251,13 +314,13 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树名称
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
*
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树名称
|
||||
*/
|
||||
public static String getTreeName(JSONObject paramsObj)
|
||||
@ -266,12 +329,12 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取需要在哪一列上面显示展开按钮
|
||||
*
|
||||
*
|
||||
* @param genTable 业务表对象
|
||||
* @return 展开按钮列序号
|
||||
*/
|
||||
|
||||
@ -117,4 +117,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="deleteGenTableColumns">
|
||||
delete from gen_table_column where column_id in
|
||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||
#{item.columnId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
@ -5,22 +5,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
|
||||
|
||||
<resultMap type="GenTable" id="GenTableResult">
|
||||
<id property="tableId" column="table_id" />
|
||||
<result property="tableName" column="table_name" />
|
||||
<result property="tableComment" column="table_comment" />
|
||||
<result property="className" column="class_name" />
|
||||
<result property="tplCategory" column="tpl_category" />
|
||||
<result property="packageName" column="package_name" />
|
||||
<result property="moduleName" column="module_name" />
|
||||
<result property="businessName" column="business_name" />
|
||||
<result property="functionName" column="function_name" />
|
||||
<result property="functionAuthor" column="function_author" />
|
||||
<result property="options" column="options" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
<id property="tableId" column="table_id" />
|
||||
<result property="tableName" column="table_name" />
|
||||
<result property="tableComment" column="table_comment" />
|
||||
<result property="subTableName" column="sub_table_name" />
|
||||
<result property="subTableFkName" column="sub_table_fk_name" />
|
||||
<result property="className" column="class_name" />
|
||||
<result property="tplCategory" column="tpl_category" />
|
||||
<result property="packageName" column="package_name" />
|
||||
<result property="moduleName" column="module_name" />
|
||||
<result property="businessName" column="business_name" />
|
||||
<result property="functionName" column="function_name" />
|
||||
<result property="functionAuthor" column="function_author" />
|
||||
<result property="genType" column="gen_type" />
|
||||
<result property="genPath" column="gen_path" />
|
||||
<result property="options" column="options" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
<collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
|
||||
</resultMap>
|
||||
|
||||
@ -50,7 +54,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGenTableVo">
|
||||
select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, options, create_by, create_time, update_by, update_time, remark from gen_table
|
||||
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
|
||||
</sql>
|
||||
|
||||
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
|
||||
@ -62,11 +66,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">
|
||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
@ -82,11 +86,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">
|
||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</select>
|
||||
|
||||
@ -106,7 +110,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
@ -114,13 +118,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
where t.table_name = #{tableName} order by c.sort
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
order by c.sort
|
||||
</select>
|
||||
|
||||
<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
|
||||
insert into gen_table (
|
||||
<if test="tableName != null">table_name,</if>
|
||||
@ -132,6 +144,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessName != null and businessName != ''">business_name,</if>
|
||||
<if test="functionName != null and functionName != ''">function_name,</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
|
||||
<if test="genType != null and genType != ''">gen_type,</if>
|
||||
<if test="genPath != null and genPath != ''">gen_path,</if>
|
||||
<if test="remark != null and remark != ''">remark,</if>
|
||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||
create_time
|
||||
@ -145,6 +159,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessName != null and businessName != ''">#{businessName},</if>
|
||||
<if test="functionName != null and functionName != ''">#{functionName},</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
|
||||
<if test="genType != null and genType != ''">#{genType},</if>
|
||||
<if test="genPath != null and genPath != ''">#{genPath},</if>
|
||||
<if test="remark != null and remark != ''">#{remark},</if>
|
||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||
sysdate()
|
||||
@ -156,8 +172,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<set>
|
||||
<if test="tableName != null">table_name = #{tableName},</if>
|
||||
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
|
||||
<if test="subTableName != null">sub_table_name = #{subTableName},</if>
|
||||
<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
|
||||
<if test="className != null and className != ''">class_name = #{className},</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
|
||||
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
|
||||
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
|
||||
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
|
||||
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
|
||||
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
|
||||
@ -178,4 +198,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
</mapper>
|
||||
@ -1,114 +1,114 @@
|
||||
package ${packageName}.controller;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
import ${packageName}.service.I${ClassName}Service;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
#if($table.crud)
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
#elseif($table.tree)
|
||||
#end
|
||||
|
||||
/**
|
||||
* ${functionName}Controller
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/${moduleName}/${businessName}")
|
||||
public class ${ClassName}Controller extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private I${ClassName}Service ${className}Service;
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
|
||||
@GetMapping("/list")
|
||||
#if($table.crud)
|
||||
public TableDataInfo list(${ClassName} ${className})
|
||||
{
|
||||
startPage();
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
return getDataTable(list);
|
||||
}
|
||||
#elseif($table.tree)
|
||||
public AjaxResult list(${ClassName} ${className})
|
||||
{
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* 导出${functionName}列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export")
|
||||
public AjaxResult export(${ClassName} ${className})
|
||||
{
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
|
||||
return util.exportExcel(list, "${businessName}");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取${functionName}详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
|
||||
@GetMapping(value = "/{${pkColumn.javaField}}")
|
||||
public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
|
||||
{
|
||||
return AjaxResult.success(${className}Service.select${ClassName}ById(${pkColumn.javaField}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody ${ClassName} ${className})
|
||||
{
|
||||
return toAjax(${className}Service.insert${ClassName}(${className}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody ${ClassName} ${className})
|
||||
{
|
||||
return toAjax(${className}Service.update${ClassName}(${className}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{${pkColumn.javaField}s}")
|
||||
public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
|
||||
{
|
||||
return toAjax(${className}Service.delete${ClassName}ByIds(${pkColumn.javaField}s));
|
||||
}
|
||||
}
|
||||
package ${packageName}.controller;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
import ${packageName}.service.I${ClassName}Service;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
#if($table.crud || $table.sub)
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
#elseif($table.tree)
|
||||
#end
|
||||
|
||||
/**
|
||||
* ${functionName}Controller
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/${moduleName}/${businessName}")
|
||||
public class ${ClassName}Controller extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private I${ClassName}Service ${className}Service;
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
|
||||
@GetMapping("/list")
|
||||
#if($table.crud || $table.sub)
|
||||
public TableDataInfo list(${ClassName} ${className})
|
||||
{
|
||||
startPage();
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
return getDataTable(list);
|
||||
}
|
||||
#elseif($table.tree)
|
||||
public AjaxResult list(${ClassName} ${className})
|
||||
{
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* 导出${functionName}列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export")
|
||||
public AjaxResult export(${ClassName} ${className})
|
||||
{
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
|
||||
return util.exportExcel(list, "${functionName}数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取${functionName}详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
|
||||
@GetMapping(value = "/{${pkColumn.javaField}}")
|
||||
public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
|
||||
{
|
||||
return AjaxResult.success(${className}Service.select${ClassName}ById(${pkColumn.javaField}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody ${ClassName} ${className})
|
||||
{
|
||||
return toAjax(${className}Service.insert${ClassName}(${className}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody ${ClassName} ${className})
|
||||
{
|
||||
return toAjax(${className}Service.update${ClassName}(${className}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除${functionName}
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{${pkColumn.javaField}s}")
|
||||
public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
|
||||
{
|
||||
return toAjax(${className}Service.delete${ClassName}ByIds(${pkColumn.javaField}s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import ${import};
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
#if($table.crud)
|
||||
#if($table.crud || $table.sub)
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
#elseif($table.tree)
|
||||
import com.ruoyi.common.core.domain.TreeEntity;
|
||||
@ -18,7 +18,7 @@ import com.ruoyi.common.core.domain.TreeEntity;
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
#if($table.crud)
|
||||
#if($table.crud || $table.sub)
|
||||
#set($Entity="BaseEntity")
|
||||
#elseif($table.tree)
|
||||
#set($Entity="TreeEntity")
|
||||
@ -49,6 +49,11 @@ public class ${ClassName} extends ${Entity}
|
||||
private $column.javaType $column.javaField;
|
||||
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
/** $table.subTable.functionName信息 */
|
||||
private List<${subClassName}> ${subclassName}List;
|
||||
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if(!$table.isSuperColumn($column.javaField))
|
||||
@ -69,6 +74,18 @@ public class ${ClassName} extends ${Entity}
|
||||
#end
|
||||
#end
|
||||
|
||||
#if($table.sub)
|
||||
public List<${subClassName}> get${subClassName}List()
|
||||
{
|
||||
return ${subclassName}List;
|
||||
}
|
||||
|
||||
public void set${subClassName}List(List<${subClassName}> ${subclassName}List)
|
||||
{
|
||||
this.${subclassName}List = ${subclassName}List;
|
||||
}
|
||||
|
||||
#end
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
@ -79,6 +96,9 @@ public class ${ClassName} extends ${Entity}
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#end
|
||||
.append("${column.javaField}", get${AttrName}())
|
||||
#end
|
||||
#if($table.sub)
|
||||
.append("${subclassName}List", get${subClassName}List())
|
||||
#end
|
||||
.toString();
|
||||
}
|
||||
|
||||
@ -1,61 +1,91 @@
|
||||
package ${packageName}.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
|
||||
/**
|
||||
* ${functionName}Mapper接口
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
public interface ${ClassName}Mapper
|
||||
{
|
||||
/**
|
||||
* 查询${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField} ${functionName}ID
|
||||
* @return ${functionName}
|
||||
*/
|
||||
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return ${functionName}集合
|
||||
*/
|
||||
public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
public int insert${ClassName}(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
public int update${ClassName}(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 删除${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField} ${functionName}ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
|
||||
|
||||
/**
|
||||
* 批量删除${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField}s 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s);
|
||||
}
|
||||
package ${packageName}.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
#if($table.sub)
|
||||
import ${packageName}.domain.${subClassName};
|
||||
#end
|
||||
|
||||
/**
|
||||
* ${functionName}Mapper接口
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
public interface ${ClassName}Mapper
|
||||
{
|
||||
/**
|
||||
* 查询${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField} ${functionName}ID
|
||||
* @return ${functionName}
|
||||
*/
|
||||
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return ${functionName}集合
|
||||
*/
|
||||
public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
public int insert${ClassName}(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
*
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
public int update${ClassName}(${ClassName} ${className});
|
||||
|
||||
/**
|
||||
* 删除${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField} ${functionName}ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
|
||||
|
||||
/**
|
||||
* 批量删除${functionName}
|
||||
*
|
||||
* @param ${pkColumn.javaField}s 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s);
|
||||
#if($table.sub)
|
||||
|
||||
/**
|
||||
* 批量删除${subTable.functionName}
|
||||
*
|
||||
* @param customerIds 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
|
||||
|
||||
/**
|
||||
* 批量新增${subTable.functionName}
|
||||
*
|
||||
* @param ${subclassName}List ${subTable.functionName}列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batch${subClassName}(List<${subClassName}> ${subclassName}List);
|
||||
|
||||
|
||||
/**
|
||||
* 通过${functionName}ID删除${subTable.functionName}信息
|
||||
*
|
||||
* @param ${pkColumn.javaField} ${functionName}ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
|
||||
#end
|
||||
}
|
||||
|
||||
@ -9,6 +9,12 @@ import com.ruoyi.common.utils.DateUtils;
|
||||
#end
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
#if($table.sub)
|
||||
import java.util.ArrayList;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ${packageName}.domain.${subClassName};
|
||||
#end
|
||||
import ${packageName}.mapper.${ClassName}Mapper;
|
||||
import ${packageName}.domain.${ClassName};
|
||||
import ${packageName}.service.I${ClassName}Service;
|
||||
@ -55,6 +61,9 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
#if($table.sub)
|
||||
@Transactional
|
||||
#end
|
||||
@Override
|
||||
public int insert${ClassName}(${ClassName} ${className})
|
||||
{
|
||||
@ -63,7 +72,13 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
${className}.setCreateTime(DateUtils.getNowDate());
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
int rows = ${className}Mapper.insert${ClassName}(${className});
|
||||
insert${subClassName}(${className});
|
||||
return rows;
|
||||
#else
|
||||
return ${className}Mapper.insert${ClassName}(${className});
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,6 +87,9 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
* @param ${className} ${functionName}
|
||||
* @return 结果
|
||||
*/
|
||||
#if($table.sub)
|
||||
@Transactional
|
||||
#end
|
||||
@Override
|
||||
public int update${ClassName}(${ClassName} ${className})
|
||||
{
|
||||
@ -79,6 +97,10 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
#if($column.javaField == 'updateTime')
|
||||
${className}.setUpdateTime(DateUtils.getNowDate());
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}());
|
||||
insert${subClassName}(${className});
|
||||
#end
|
||||
return ${className}Mapper.update${ClassName}(${className});
|
||||
}
|
||||
@ -89,9 +111,15 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
* @param ${pkColumn.javaField}s 需要删除的${functionName}ID
|
||||
* @return 结果
|
||||
*/
|
||||
#if($table.sub)
|
||||
@Transactional
|
||||
#end
|
||||
@Override
|
||||
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s)
|
||||
{
|
||||
#if($table.sub)
|
||||
${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
|
||||
#end
|
||||
return ${className}Mapper.delete${ClassName}ByIds(${pkColumn.javaField}s);
|
||||
}
|
||||
|
||||
@ -104,6 +132,35 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
|
||||
@Override
|
||||
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField})
|
||||
{
|
||||
#if($table.sub)
|
||||
${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
|
||||
#end
|
||||
return ${className}Mapper.delete${ClassName}ById(${pkColumn.javaField});
|
||||
}
|
||||
#if($table.sub)
|
||||
|
||||
/**
|
||||
* 新增${subTable.functionName}信息
|
||||
*
|
||||
* @param ${className} ${functionName}对象
|
||||
*/
|
||||
public void insert${subClassName}(${ClassName} ${className})
|
||||
{
|
||||
List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
|
||||
Long ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
|
||||
if (StringUtils.isNotNull(${subclassName}List))
|
||||
{
|
||||
List<${subClassName}> list = new ArrayList<${subClassName}>();
|
||||
for (${subClassName} ${subclassName} : ${subclassName}List)
|
||||
{
|
||||
${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
|
||||
list.add(${subclassName});
|
||||
}
|
||||
if (list.size() > 0)
|
||||
{
|
||||
${className}Mapper.batch${subClassName}(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package ${packageName}.domain;
|
||||
|
||||
#foreach ($import in $subImportList)
|
||||
import ${import};
|
||||
#end
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* ${subTable.functionName}对象 ${subTableName}
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${datetime}
|
||||
*/
|
||||
public class ${subClassName} extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
#foreach ($column in $subTable.columns)
|
||||
#if(!$table.isSuperColumn($column.javaField))
|
||||
/** $column.columnComment */
|
||||
#if($column.list)
|
||||
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||
#if($parentheseIndex != -1)
|
||||
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||
#else
|
||||
#set($comment=$column.columnComment)
|
||||
#end
|
||||
#if($parentheseIndex != -1)
|
||||
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
|
||||
#elseif($column.javaType == 'Date')
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
#else
|
||||
@Excel(name = "${comment}")
|
||||
#end
|
||||
#end
|
||||
private $column.javaType $column.javaField;
|
||||
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $subTable.columns)
|
||||
#if(!$table.isSuperColumn($column.javaField))
|
||||
#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
|
||||
#set($AttrName=$column.javaField)
|
||||
#else
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#end
|
||||
public void set${AttrName}($column.javaType $column.javaField)
|
||||
{
|
||||
this.$column.javaField = $column.javaField;
|
||||
}
|
||||
|
||||
public $column.javaType get${AttrName}()
|
||||
{
|
||||
return $column.javaField;
|
||||
}
|
||||
#end
|
||||
#end
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
#foreach ($column in $subTable.columns)
|
||||
#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
|
||||
#set($AttrName=$column.javaField)
|
||||
#else
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#end
|
||||
.append("${column.javaField}", get${AttrName}())
|
||||
#end
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,22 @@
|
||||
-- 菜单 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
|
||||
|
||||
-- 按钮父菜单ID
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}查询', @parentId, '1', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}新增', @parentId, '2', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}修改', @parentId, '3', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}删除', @parentId, '4', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}导出', @parentId, '5', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, '');
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
#foreach($column in $columns)
|
||||
#if($column.query)
|
||||
#set($dictType=$column.dictType)
|
||||
@ -38,36 +38,50 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择${comment}">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
<el-form-item label="${comment}">
|
||||
<el-date-picker
|
||||
v-model="daterange${AttrName}"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="handleQuery"
|
||||
>搜索</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
||||
>新增</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
@ -94,8 +108,12 @@
|
||||
#elseif($column.list && "" != $column.dictType)
|
||||
<el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" />
|
||||
#elseif($column.list && "" != $javaField)
|
||||
#if(${foreach.index} == 1)
|
||||
<el-table-column label="${comment}" prop="${javaField}" />
|
||||
#else
|
||||
<el-table-column label="${comment}" align="center" prop="${javaField}" />
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
@ -106,6 +124,13 @@
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAdd(scope.row)"
|
||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
||||
>新增</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
@ -139,8 +164,20 @@
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
<el-form-item label="${comment}">
|
||||
<imageUpload v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "fileUpload")
|
||||
<el-form-item label="${comment}">
|
||||
<fileUpload v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<el-form-item label="${comment}">
|
||||
<editor v-model="form.${field}" :min-height="192"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||
<el-option
|
||||
v-for="dict in ${field}Options"
|
||||
@ -152,11 +189,28 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${field}Options"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictValue">
|
||||
{{dict.dictLabel}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-radio-group v-model="form.${field}">
|
||||
@ -176,7 +230,7 @@
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="form.${field}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
@ -207,11 +261,15 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
|
||||
export default {
|
||||
name: "${BusinessName}",
|
||||
components: { Treeselect },
|
||||
components: {
|
||||
Treeselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// ${functionName}表格数据
|
||||
${businessName}List: [],
|
||||
// ${functionName}树选项
|
||||
@ -230,13 +288,17 @@ export default {
|
||||
#if(${column.dictType} != '')
|
||||
// $comment字典
|
||||
${column.javaField}Options: [],
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
// $comment时间范围
|
||||
daterange${AttrName}: [],
|
||||
#end
|
||||
#end
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.query)
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@ -253,9 +315,8 @@ export default {
|
||||
#else
|
||||
#set($comment=$column.columnComment)
|
||||
#end
|
||||
#set($comment=$column.columnComment)
|
||||
$column.javaField: [
|
||||
{ required: true, message: "$comment不能为空", trigger: "blur" }
|
||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
||||
]#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
@ -277,6 +338,21 @@ export default {
|
||||
/** 查询${functionName}列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
this.queryParams.params = {};
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
||||
}
|
||||
#end
|
||||
#end
|
||||
list${BusinessName}(this.queryParams).then(response => {
|
||||
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
||||
this.loading = false;
|
||||
@ -293,7 +369,7 @@ export default {
|
||||
children: node.children
|
||||
};
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
/** 查询${functionName}下拉树结构 */
|
||||
getTreeselect() {
|
||||
list${BusinessName}().then(response => {
|
||||
this.${businessName}Options = [];
|
||||
@ -312,7 +388,7 @@ export default {
|
||||
#end
|
||||
// $comment字典翻译
|
||||
${column.javaField}Format(row, column) {
|
||||
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
|
||||
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
|
||||
},
|
||||
#end
|
||||
#end
|
||||
@ -326,10 +402,13 @@ export default {
|
||||
this.form = {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "radio")
|
||||
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#elseif($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#else
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@ -342,48 +421,65 @@ export default {
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
this.daterange${AttrName} = [];
|
||||
#end
|
||||
#end
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
handleAdd(row) {
|
||||
this.reset();
|
||||
this.getTreeselect();
|
||||
this.getTreeselect();
|
||||
if (row != null && row.${treeCode}) {
|
||||
this.form.${treeParentCode} = row.${treeCode};
|
||||
} else {
|
||||
this.form.${treeParentCode} = 0;
|
||||
}
|
||||
this.open = true;
|
||||
this.title = "添加${functionName}";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.getTreeselect();
|
||||
if (row != undefined) {
|
||||
this.getTreeselect();
|
||||
if (row != null) {
|
||||
this.form.${treeParentCode} = row.${treeCode};
|
||||
}
|
||||
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
||||
this.form = response.data;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
||||
#end
|
||||
#end
|
||||
this.open = true;
|
||||
this.title = "修改${functionName}";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
submitForm() {
|
||||
this.#[[$]]#refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.${pkColumn.javaField} != undefined) {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
||||
#end
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -400,8 +496,8 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
#foreach($column in $columns)
|
||||
#if($column.query)
|
||||
#set($dictType=$column.dictType)
|
||||
@ -38,15 +38,28 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择${comment}">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
<el-form-item label="${comment}">
|
||||
<el-date-picker
|
||||
v-model="daterange${AttrName}"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
@ -60,6 +73,7 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
@ -69,6 +83,7 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@ -79,6 +94,7 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@ -89,12 +105,15 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
:loading="exportLoading"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['${moduleName}:${businessName}:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
|
||||
@ -167,8 +186,20 @@
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
<el-form-item label="${comment}">
|
||||
<imageUpload v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "fileUpload")
|
||||
<el-form-item label="${comment}">
|
||||
<fileUpload v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<el-form-item label="${comment}">
|
||||
<editor v-model="form.${field}" :min-height="192"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||
<el-option
|
||||
v-for="dict in ${field}Options"
|
||||
@ -180,11 +211,28 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${field}Options"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictValue">
|
||||
{{dict.dictLabel}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-radio-group v-model="form.${field}">
|
||||
@ -204,7 +252,7 @@
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
<el-date-picker clearable size="small"
|
||||
v-model="form.${field}"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
@ -218,6 +266,38 @@
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd${subClassName}">添加</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDelete${subClassName}">删除</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column label="序号" align="center" prop="index" width="50"/>
|
||||
#foreach($column in $subTable.columns)
|
||||
#set($javaField=$column.javaField)
|
||||
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||
#if($parentheseIndex != -1)
|
||||
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||
#else
|
||||
#set($comment=$column.columnComment)
|
||||
#end
|
||||
#if($column.pk || $javaField == ${subTableFkclassName})
|
||||
#elseif($column.list && "" != $javaField)
|
||||
<el-table-column label="$comment" prop="${javaField}">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
#end
|
||||
#end
|
||||
</el-table>
|
||||
#end
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@ -237,16 +317,28 @@ export default {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
#if($table.sub)
|
||||
// 子表选中数据
|
||||
checked${subClassName}: [],
|
||||
#end
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// ${functionName}表格数据
|
||||
${businessName}List: [],
|
||||
#if($table.sub)
|
||||
// ${subTable.functionName}表格数据
|
||||
${subclassName}List: [],
|
||||
#end
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
@ -261,6 +353,10 @@ export default {
|
||||
#if(${column.dictType} != '')
|
||||
// $comment字典
|
||||
${column.javaField}Options: [],
|
||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
// $comment时间范围
|
||||
daterange${AttrName}: [],
|
||||
#end
|
||||
#end
|
||||
// 查询参数
|
||||
@ -269,7 +365,7 @@ export default {
|
||||
pageSize: 10,
|
||||
#foreach ($column in $columns)
|
||||
#if($column.query)
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@ -286,9 +382,8 @@ export default {
|
||||
#else
|
||||
#set($comment=$column.columnComment)
|
||||
#end
|
||||
#set($comment=$column.columnComment)
|
||||
$column.javaField: [
|
||||
{ required: true, message: "$comment不能为空", trigger: "blur" }
|
||||
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
|
||||
]#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
@ -310,6 +405,21 @@ export default {
|
||||
/** 查询${functionName}列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
this.queryParams.params = {};
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
||||
}
|
||||
#end
|
||||
#end
|
||||
list${BusinessName}(this.queryParams).then(response => {
|
||||
this.${businessName}List = response.rows;
|
||||
this.total = response.total;
|
||||
@ -326,7 +436,7 @@ export default {
|
||||
#end
|
||||
// $comment字典翻译
|
||||
${column.javaField}Format(row, column) {
|
||||
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
|
||||
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
|
||||
},
|
||||
#end
|
||||
#end
|
||||
@ -340,14 +450,20 @@ export default {
|
||||
this.form = {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "radio")
|
||||
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#elseif($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#else
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
};
|
||||
#if($table.sub)
|
||||
this.${subclassName}List = [];
|
||||
#end
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
@ -357,13 +473,19 @@ export default {
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
this.daterange${AttrName} = [];
|
||||
#end
|
||||
#end
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.${pkColumn.javaField})
|
||||
this.single = selection.length!=1
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
@ -378,29 +500,41 @@ export default {
|
||||
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
|
||||
get${BusinessName}(${pkColumn.javaField}).then(response => {
|
||||
this.form = response.data;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
this.${subclassName}List = response.data.${subclassName}List;
|
||||
#end
|
||||
this.open = true;
|
||||
this.title = "修改${functionName}";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
submitForm() {
|
||||
this.#[[$]]#refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.${pkColumn.javaField} != undefined) {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
||||
#end
|
||||
#end
|
||||
#if($table.sub)
|
||||
this.form.${subclassName}List = this.${subclassName}List;
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -418,8 +552,42 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
}).catch(() => {});
|
||||
},
|
||||
#if($table.sub)
|
||||
/** ${subTable.functionName}序号 */
|
||||
row${subClassName}Index({ row, rowIndex }) {
|
||||
row.index = rowIndex + 1;
|
||||
},
|
||||
/** ${subTable.functionName}添加按钮操作 */
|
||||
handleAdd${subClassName}() {
|
||||
let obj = {};
|
||||
#foreach($column in $subTable.columns)
|
||||
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
||||
#elseif($column.list && "" != $javaField)
|
||||
obj.$column.javaField = "";
|
||||
#end
|
||||
#end
|
||||
this.${subclassName}List.push(obj);
|
||||
},
|
||||
/** ${subTable.functionName}删除按钮操作 */
|
||||
handleDelete${subClassName}() {
|
||||
if (this.checked${subClassName}.length == 0) {
|
||||
this.$alert("请先选择要删除的${subTable.functionName}数据", "提示", { confirmButtonText: "确定", });
|
||||
} else {
|
||||
this.${subclassName}List.splice(this.checked${subClassName}[0].index - 1, 1);
|
||||
}
|
||||
},
|
||||
/** 单选框选中数据 */
|
||||
handle${subClassName}SelectionChange(selection) {
|
||||
if (selection.length > 1) {
|
||||
this.$refs.${subclassName}.clearSelection();
|
||||
this.$refs.${subclassName}.toggleRowSelection(selection.pop());
|
||||
} else {
|
||||
this.checked${subClassName} = selection;
|
||||
}
|
||||
},
|
||||
#end
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
@ -427,12 +595,14 @@ export default {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
}).then(() => {
|
||||
this.exportLoading = true;
|
||||
return export${BusinessName}(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
this.exportLoading = false;
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@ -9,6 +9,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="${column.javaField}" column="${column.columnName}" />
|
||||
#end
|
||||
</resultMap>
|
||||
#if($table.sub)
|
||||
|
||||
<resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
|
||||
<collection property="${subclassName}List" notNullColumn="sub_${subTable.pkColumn.columnName}" javaType="java.util.List" resultMap="${subClassName}Result" />
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="${subClassName}" id="${subClassName}Result">
|
||||
#foreach ($column in $subTable.columns)
|
||||
<result property="${column.javaField}" column="sub_${column.columnName}" />
|
||||
#end
|
||||
</resultMap>
|
||||
#end
|
||||
|
||||
<sql id="select${ClassName}Vo">
|
||||
select#foreach($column in $columns) $column.columnName#if($velocityCount != $columns.size()),#end#end from ${tableName}
|
||||
@ -46,9 +58,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="select${ClassName}ById" parameterType="${pkColumn.javaType}" resultMap="${ClassName}Result">
|
||||
<select id="select${ClassName}ById" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
|
||||
#if($table.crud || $table.tree)
|
||||
<include refid="select${ClassName}Vo"/>
|
||||
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
|
||||
#elseif($table.sub)
|
||||
select#foreach($column in $columns) a.$column.columnName#if($velocityCount != $columns.size()),#end#end,
|
||||
#foreach($column in $subTable.columns) b.$column.columnName as sub_$column.columnName#if($velocityCount != $subTable.columns.size()),#end#end
|
||||
|
||||
from ${tableName} a
|
||||
left join ${subTableName} b on b.${subTableFkName} = a.${pkColumn.columnName}
|
||||
where a.${pkColumn.columnName} = #{${pkColumn.javaField}}
|
||||
#end
|
||||
</select>
|
||||
|
||||
<insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
|
||||
@ -91,5 +112,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{${pkColumn.javaField}}
|
||||
</foreach>
|
||||
</delete>
|
||||
#if($table.sub)
|
||||
|
||||
<delete id="delete${subClassName}By${subTableFkClassName}s" parameterType="String">
|
||||
delete from ${subTableName} where ${subTableFkName} in
|
||||
<foreach item="${subTableFkclassName}" collection="array" open="(" separator="," close=")">
|
||||
#{${subTableFkclassName}}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="delete${subClassName}By${subTableFkClassName}" parameterType="Long">
|
||||
delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}}
|
||||
</delete>
|
||||
|
||||
<insert id="batch${subClassName}">
|
||||
insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($velocityCount != $subTable.columns.size()),#end#end) values
|
||||
<foreach item="item" index="index" collection="list" separator=",">
|
||||
(#foreach($column in $subTable.columns) #{item.$column.javaField}#if($velocityCount != $subTable.columns.size()),#end#end)
|
||||
</foreach>
|
||||
</insert>
|
||||
#end
|
||||
</mapper>
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.6.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -13,12 +13,14 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.exception.job.TaskException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.quartz.domain.SysJob;
|
||||
import com.ruoyi.quartz.service.ISysJobService;
|
||||
@ -81,7 +83,11 @@ public class SysJobController extends BaseController
|
||||
{
|
||||
if (!CronUtils.isValid(sysJob.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,Cron表达式不正确");
|
||||
}
|
||||
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
|
||||
{
|
||||
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
|
||||
}
|
||||
sysJob.setCreateBy(SecurityUtils.getUsername());
|
||||
return toAjax(jobService.insertJob(sysJob));
|
||||
@ -97,7 +103,11 @@ public class SysJobController extends BaseController
|
||||
{
|
||||
if (!CronUtils.isValid(sysJob.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,Cron表达式不正确");
|
||||
}
|
||||
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
|
||||
{
|
||||
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
|
||||
}
|
||||
sysJob.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(jobService.updateJob(sysJob));
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.ruoyi.quartz.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
@ -19,7 +18,7 @@ import com.ruoyi.quartz.util.CronUtils;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SysJob extends BaseEntity implements Serializable
|
||||
public class SysJob extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -88,7 +87,7 @@ public class SysJob extends BaseEntity implements Serializable
|
||||
}
|
||||
|
||||
@NotBlank(message = "调用目标字符串不能为空")
|
||||
@Size(min = 0, max = 1000, message = "调用目标字符串长度不能超过500个字符")
|
||||
@Size(min = 0, max = 500, message = "调用目标字符串长度不能超过500个字符")
|
||||
public String getInvokeTarget()
|
||||
{
|
||||
return invokeTarget;
|
||||
|
||||
@ -66,7 +66,7 @@ public abstract class AbstractQuartzJob implements Job
|
||||
* 执行后
|
||||
*
|
||||
* @param context 工作执行上下文对象
|
||||
* @param sysScheduleJob 系统计划任务
|
||||
* @param sysJob 系统计划任务
|
||||
*/
|
||||
protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user