mirror of
https://gitee.com/y_project/RuoYi-Vue.git
synced 2026-04-30 00:00:08 +08:00
Compare commits
349 Commits
v3.8.6
...
springboot2
| Author | SHA1 | Date | |
|---|---|---|---|
| 19f3c447a1 | |||
| b9f138df36 | |||
| 65d02b8866 | |||
| 026f678134 | |||
| 1394a669e5 | |||
| b5f2bc10a3 | |||
| 5091b0694a | |||
| f7fee02af8 | |||
| c36e6c1f5d | |||
| d412a02be2 | |||
| 71abdbb3c2 | |||
| d1179b88f3 | |||
| 8359b989d6 | |||
| f11ca242f4 | |||
| 5bf798f142 | |||
| 29840618a7 | |||
| 47cc26f2e5 | |||
| 61b6ec361a | |||
| 9e8b0cdca6 | |||
| 5c6b935181 | |||
| 05f245a928 | |||
| 1ac34f0edc | |||
| 609112b384 | |||
| a8c0580c8a | |||
| 532f35276f | |||
| a9c244919e | |||
| e230c3eed0 | |||
| d99a58c0d1 | |||
| 18cbdd6fdc | |||
| 7c0df77713 | |||
| bcc2b32385 | |||
| b1d905b556 | |||
| 9ab9feba1c | |||
| b0165be442 | |||
| b52fed10e2 | |||
| 201cde1566 | |||
| 95dfbd35cc | |||
| 8f54cf7f35 | |||
| ba13d53efb | |||
| 525d5fc376 | |||
| 253a438788 | |||
| 31c64494d3 | |||
| 8ba4f945c3 | |||
| 846b585f16 | |||
| cd0ee0a5cd | |||
| c204bda63a | |||
| 25dd4b1d80 | |||
| 35f22d788d | |||
| 4071111777 | |||
| 2c10516204 | |||
| 912944c0b2 | |||
| fcffc37602 | |||
| 43effcdbe9 | |||
| 1d294464a7 | |||
| 140a7fb66f | |||
| 0d85aa50a7 | |||
| ed916656dd | |||
| 85cb89f1b6 | |||
| 8aef19ba49 | |||
| 83bc1a331a | |||
| b9c7731cdb | |||
| 850b86e0de | |||
| 8a1cf9ed55 | |||
| 600e06904b | |||
| 6281609d9e | |||
| 2cf825dd3d | |||
| 245baa705b | |||
| cfe076ebd0 | |||
| 1f2f11f80f | |||
| 12fb035b2e | |||
| 98a8545ca0 | |||
| fdb1853a34 | |||
| 8c6b4a96b7 | |||
| 5e83011d56 | |||
| b12dab2d2e | |||
| 7b75f9ac0b | |||
| 4615293be9 | |||
| ba5cf9de6e | |||
| 6de392bac2 | |||
| 49f62e565a | |||
| 5579b57bef | |||
| 88609b3b24 | |||
| 03f3f47397 | |||
| b5400d962b | |||
| e7ef3241c5 | |||
| eb6878e18f | |||
| 8499225192 | |||
| 4a5e45d160 | |||
| 188e50ff1c | |||
| bd66cc7260 | |||
| 866b47000c | |||
| f38f8b2c3e | |||
| faa86ac946 | |||
| ad280e824c | |||
| 6e1aa42ebe | |||
| 315901041f | |||
| 91263711d4 | |||
| 9372d3401f | |||
| 0eaa090f4b | |||
| a5adee3c5f | |||
| 075e96466f | |||
| 41496b6d8a | |||
| 4a401984c1 | |||
| e5faee66c8 | |||
| 7558c176eb | |||
| 4a5b0e6079 | |||
| 08637e31e5 | |||
| 512b157801 | |||
| 5e8efaa94a | |||
| 5f11fed41b | |||
| b60b5de750 | |||
| 41ff3843e6 | |||
| 6a2e8a35e9 | |||
| 769165575f | |||
| 18c8d4ec9c | |||
| 191fd29301 | |||
| 47510fe2de | |||
| 725c7dcea2 | |||
| 158ccaebe0 | |||
| 7b9060af26 | |||
| 1a2f20e859 | |||
| 09faecb5d3 | |||
| d46e62a21a | |||
| fa88922637 | |||
| 65159934ab | |||
| 1642bba612 | |||
| a7a61fee8d | |||
| db6d5d34e6 | |||
| 9ceca3a68e | |||
| cf2579612c | |||
| c0355a0f5a | |||
| 8ff013552a | |||
| 673249d373 | |||
| fe3a92a812 | |||
| 67b6a0e11b | |||
| bc70351e34 | |||
| fe0c1fcb5b | |||
| 9f39dfd0c1 | |||
| 131abe876d | |||
| 46708ceee4 | |||
| ecd201550f | |||
| ff3f3f2631 | |||
| d3cc8f0fb7 | |||
| 6cafa3373e | |||
| 42fbf09dde | |||
| 88b0f5bcb2 | |||
| e852fdb687 | |||
| baf2f6f46b | |||
| e19f1abfeb | |||
| 38ed092de7 | |||
| 27a037ed3d | |||
| 87173cbe75 | |||
| 29a5b6da53 | |||
| b1d2139559 | |||
| 43d78c2cf5 | |||
| 8f4eb24bf2 | |||
| a9f9133e31 | |||
| 09810ccf1d | |||
| 0d9fb8b5c0 | |||
| c6b0efcdc2 | |||
| 84fef1f675 | |||
| 11fed08b56 | |||
| f83b6fbfa2 | |||
| eef81e6ca9 | |||
| 5a03a754e8 | |||
| 245dea7215 | |||
| 51632f8e60 | |||
| 525ebf92d2 | |||
| d3b23a831e | |||
| 89ab3bd058 | |||
| 9e16beb48f | |||
| 8d5ecc7ff4 | |||
| 6e314dd3e8 | |||
| 193c256e71 | |||
| 4df52a6b40 | |||
| 079b7eeecf | |||
| ba24010709 | |||
| bd257f85e6 | |||
| 40c7ca34a8 | |||
| 1ef73d7360 | |||
| bd233fd62f | |||
| fabddc518a | |||
| ca61b6c68d | |||
| 51e5cf2a09 | |||
| 00acc37916 | |||
| 511ff0f125 | |||
| bf46e38c29 | |||
| 698a5198d9 | |||
| 5e6c917ab0 | |||
| 9a51563144 | |||
| 3b2704c181 | |||
| 7232217061 | |||
| 25fd29c5ea | |||
| 2d6a6a162f | |||
| 164c62743f | |||
| 4ee169b0c8 | |||
| d487ffc92f | |||
| 5a1e7bae2c | |||
| 1810f30491 | |||
| 6efceac460 | |||
| 77a6350460 | |||
| 58a21ff9d7 | |||
| 7f507f5dfa | |||
| a1a45ef7ac | |||
| b343308a97 | |||
| 0bf7457eb7 | |||
| 0f77f524d0 | |||
| 747d816be2 | |||
| 262d9e1ff0 | |||
| ab37956874 | |||
| 86ab3bf600 | |||
| f76908912e | |||
| 8df4c72ad1 | |||
| 6bdcbabc09 | |||
| 58fca720a9 | |||
| e4ccbc6601 | |||
| 430e6d4dea | |||
| a0e6295693 | |||
| 52ba823328 | |||
| 91ae9a164c | |||
| d3326987a4 | |||
| 4de087b1ad | |||
| 5b959b32d7 | |||
| 4358621473 | |||
| adb8d51932 | |||
| 08a5deb285 | |||
| dc9f3ee722 | |||
| 78bb30bb5f | |||
| 5fad997d38 | |||
| 22a795d041 | |||
| 8a0a3a03fe | |||
| ad86486285 | |||
| 3ef6000794 | |||
| f812e99a0d | |||
| 2feae7619f | |||
| 212e3b4977 | |||
| 99e66bf11c | |||
| a96d4bf2ed | |||
| 8264b8fb31 | |||
| 4ec32367fd | |||
| 9e8aa14348 | |||
| 10f68b97af | |||
| 8eff83e2b4 | |||
| 7b064d84bb | |||
| 88560a7aa5 | |||
| e14f40670a | |||
| 5b98495067 | |||
| 259dc67728 | |||
| bc7a607033 | |||
| 161cd2b1ea | |||
| 7480fb4020 | |||
| 906c3a68b8 | |||
| 084bab3494 | |||
| cc0efa3330 | |||
| f46b1bbebd | |||
| e5f30b1a19 | |||
| 1140a6c333 | |||
| 86ca404dbf | |||
| 11320b2e13 | |||
| 905c08fb2c | |||
| 9386645150 | |||
| bf3e2115e3 | |||
| 61eb54e4a1 | |||
| d93e2b9df0 | |||
| 50339c6f73 | |||
| b83f2ff60b | |||
| 66128f140f | |||
| 8c990ae9fc | |||
| 8836d31d77 | |||
| 2f624ab5f4 | |||
| 80f96b4915 | |||
| 7e9d050432 | |||
| 649cfe8652 | |||
| e9ae7ae5f3 | |||
| 3cc6fb5535 | |||
| a7bfd3b2d6 | |||
| 08d0326718 | |||
| 3f4ac65a31 | |||
| 94d5c174aa | |||
| e719ac8cff | |||
| a9bcfc66c3 | |||
| 36b900cef8 | |||
| ac9302e2a2 | |||
| 0f7e3a744e | |||
| 45656b271a | |||
| 323e3b7371 | |||
| bfbaa9e7b5 | |||
| 2253a146b3 | |||
| 2070a9252a | |||
| e231d78469 | |||
| f74454b61a | |||
| d71ee5dba1 | |||
| 78b1ac4a60 | |||
| 966a17123f | |||
| 42bb8f6445 | |||
| 72e4cd9fb3 | |||
| 1525bd8b54 | |||
| b8e2eeaaf8 | |||
| cbcfabee2a | |||
| e6d0599b25 | |||
| b224cebab7 | |||
| f880dee7a4 | |||
| f16875c9af | |||
| a90355eb5e | |||
| 386f32a3b7 | |||
| 4ca30f08d6 | |||
| 73f881c7d3 | |||
| b357aedaa3 | |||
| 8cf8c8acd0 | |||
| fbab383bd7 | |||
| d8255edf84 | |||
| eff42d8b0f | |||
| 1f753e3d84 | |||
| 72d4069537 | |||
| 76205588f0 | |||
| 7b4ba0146b | |||
| 3963e86537 | |||
| 7098acc968 | |||
| 079ac841f3 | |||
| 0434b4ca7a | |||
| 8873dc9b64 | |||
| 078a3aad5a | |||
| 207a9ce855 | |||
| 9ced1e9766 | |||
| 1926840204 | |||
| 006d46ad07 | |||
| f5a1b0c550 | |||
| 4a78fe116d | |||
| 3e95dd21f2 | |||
| 491b0f3db8 | |||
| 16d8b71e21 | |||
| 90260ce2f9 | |||
| d58942c506 | |||
| 6a742e1d1b | |||
| 5b61aea064 | |||
| 45ef542687 | |||
| 4ac7a1aa1f | |||
| c5e4459bb8 | |||
| 8f67bf416b | |||
| ab99a72b65 | |||
| 7c9423657e | |||
| 128b186b8e | |||
| 68ac40eda9 | |||
| 5557433235 | |||
| 2517e9dddb | |||
| a0595711ca | |||
| 1ffb6379f7 | |||
| 4d5c204b9a | |||
| 8ee740ef49 |
@@ -1,11 +1,11 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
||||||
</p>
|
</p>
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.6</h1>
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.2</h1>
|
||||||
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.6-brightgreen.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.2-brightgreen.svg"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -13,16 +13,36 @@
|
|||||||
|
|
||||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||||
|
|
||||||
|
* 本仓库为RuoYi-Vue的Spring Boot 2 的版本,保持同步更新。
|
||||||
* 前端采用Vue、Element UI。
|
* 前端采用Vue、Element UI。
|
||||||
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
||||||
* 权限认证使用Jwt,支持多终端认证系统。
|
* 权限认证使用Jwt,支持多终端认证系统。
|
||||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
* 支持加载动态权限菜单,多方式轻松权限控制。
|
||||||
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
||||||
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://github.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
|
|
||||||
* 提供了单应用版本[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)
|
|
||||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
* 阿里云折扣场:[点我进入](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)
|
|
||||||
|
# 版本分支
|
||||||
|
|
||||||
|
RuoYi-Vue 后端项目提供 Spring Boot 2.x / 3.x / 4.x 多版本分支的并行维护。
|
||||||
|
|
||||||
|
| 名称 | 说明 | 地址 |
|
||||||
|
| :---------------- | :------------------------ | :------------------------------------------------------ |
|
||||||
|
| master 默认分支 | Spring Boot 4.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue |
|
||||||
|
| springboot3 分支 | Spring Boot 3.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot3 |
|
||||||
|
| springboot2 分支 | Spring Boot 2.x (JDK 8+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot2 |
|
||||||
|
|
||||||
|
RuoYi-Vue 前端项目提供 Vue 2.x / 3.x / JavaScript TypeScript 版本均可混用搭配
|
||||||
|
|
||||||
|
| 项目名称 | **RuoYi-Vue** | **RuoYi-Vue3** | **RuoYi-Vue3-TypeScript** |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **前端框架** | Vue 2 | Vue 3 | Vue 3 |
|
||||||
|
| **脚本语言** | JavaScript | JavaScript | TypeScript |
|
||||||
|
| **构建工具** | Vue CLI | Vite | Vite |
|
||||||
|
| **UI 组件库** | Element UI | Element Plus | Element Plus |
|
||||||
|
| **状态管理** | Vuex | Pinia | Pinia |
|
||||||
|
| **路由管理** | Vue Router 3 | Vue Router 4 | Vue Router 4 |
|
||||||
|
| **核心特点** | 1. 技术栈经典稳定<br>2. 社区资料丰富<br>3. 当前维护重心已转移 | 1. 现代前端技术栈<br>2. 开发体验与性能更优<br>3. 官方主推的活跃版本 | 1. 类型加持,减少沟通成本<br>2. 开发时有提示,效率更高<br>3. 多人协作企业级开发项目 |
|
||||||
|
| **仓库地址** | [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) | [RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3) | [RuoYi-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Vue3/tree/typescript) |
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
|
|
||||||
@@ -93,4 +113,4 @@
|
|||||||
|
|
||||||
## 若依前后端分离交流群
|
## 若依前后端分离交流群
|
||||||
|
|
||||||
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) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) 点击按钮入群。
|
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) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632) 点击按钮入群。
|
||||||
Binary file not shown.
@@ -6,45 +6,100 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
|
|
||||||
<name>ruoyi</name>
|
<name>ruoyi</name>
|
||||||
<url>http://www.ruoyi.vip</url>
|
<url>http://www.ruoyi.vip</url>
|
||||||
<description>若依管理系统</description>
|
<description>若依管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi.version>3.8.6</ruoyi.version>
|
<ruoyi.version>3.9.2</ruoyi.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<druid.version>1.2.16</druid.version>
|
<spring-boot.version>2.5.15</spring-boot.version>
|
||||||
<bitwalker.version>1.21</bitwalker.version>
|
<druid.version>1.2.28</druid.version>
|
||||||
|
<yauaa.version>7.32.0</yauaa.version>
|
||||||
<swagger.version>3.0.0</swagger.version>
|
<swagger.version>3.0.0</swagger.version>
|
||||||
<kaptcha.version>2.3.3</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
|
||||||
<fastjson.version>2.0.34</fastjson.version>
|
<fastjson.version>2.0.61</fastjson.version>
|
||||||
<oshi.version>6.4.3</oshi.version>
|
<oshi.version>6.10.0</oshi.version>
|
||||||
<commons.io.version>2.11.0</commons.io.version>
|
<commons.io.version>2.21.0</commons.io.version>
|
||||||
<commons.collections.version>3.2.2</commons.collections.version>
|
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<jwt.version>0.9.1</jwt.version>
|
<jwt.version>0.9.1</jwt.version>
|
||||||
|
<!-- override dependency version -->
|
||||||
|
<tomcat.version>9.0.112</tomcat.version>
|
||||||
|
<logback.version>1.2.13</logback.version>
|
||||||
|
<spring-security.version>5.7.14</spring-security.version>
|
||||||
|
<spring-framework.version>5.3.39</spring-framework.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- 覆盖SpringFramework的依赖配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-framework-bom</artifactId>
|
||||||
|
<version>${spring-framework.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 覆盖SpringSecurity的依赖配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-bom</artifactId>
|
||||||
|
<version>${spring-security.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- SpringBoot的依赖配置-->
|
<!-- SpringBoot的依赖配置-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<version>2.5.15</version>
|
<version>${spring-boot.version}</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 覆盖logback的依赖配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-core</artifactId>
|
||||||
|
<version>${logback.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>${logback.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 覆盖tomcat的依赖配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-core</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-el</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-websocket</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里数据库连接池 -->
|
<!-- 阿里数据库连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
@@ -54,9 +109,9 @@
|
|||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>eu.bitwalker</groupId>
|
<groupId>nl.basjes.parse.useragent</groupId>
|
||||||
<artifactId>UserAgentUtils</artifactId>
|
<artifactId>yauaa</artifactId>
|
||||||
<version>${bitwalker.version}</version>
|
<version>${yauaa.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- pagehelper 分页插件 -->
|
<!-- pagehelper 分页插件 -->
|
||||||
@@ -107,13 +162,6 @@
|
|||||||
<version>${velocity.version}</version>
|
<version>${velocity.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- collections工具类 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-collections</groupId>
|
|
||||||
<artifactId>commons-collections</artifactId>
|
|
||||||
<version>${commons.collections.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 阿里JSON解析器 -->
|
<!-- 阿里JSON解析器 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.fastjson2</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<version>2.1.1.RELEASE</version>
|
<version>2.5.15</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||||
@@ -35,7 +34,7 @@ public class CommonController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ServerConfig serverConfig;
|
private ServerConfig serverConfig;
|
||||||
|
|
||||||
private static final String FILE_DELIMETER = ",";
|
private static final String FILE_DELIMITER = ",";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用下载请求
|
* 通用下载请求
|
||||||
@@ -120,10 +119,10 @@ public class CommonController
|
|||||||
originalFilenames.add(file.getOriginalFilename());
|
originalFilenames.add(file.getOriginalFilename());
|
||||||
}
|
}
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
|
ajax.put("urls", StringUtils.join(urls, FILE_DELIMITER));
|
||||||
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
|
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMITER));
|
||||||
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
|
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMITER));
|
||||||
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
|
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMITER));
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -148,7 +147,7 @@ public class CommonController
|
|||||||
// 本地资源路径
|
// 本地资源路径
|
||||||
String localPath = RuoYiConfig.getProfile();
|
String localPath = RuoYiConfig.getProfile();
|
||||||
// 数据库资源地址
|
// 数据库资源地址
|
||||||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
String downloadPath = localPath + FileUtils.stripPrefix(resource);
|
||||||
// 下载名称
|
// 下载名称
|
||||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisCallback;
|
import org.springframework.data.redis.core.RedisCallback;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
@@ -80,7 +81,7 @@ public class CacheController
|
|||||||
public AjaxResult getCacheKeys(@PathVariable String cacheName)
|
public AjaxResult getCacheKeys(@PathVariable String cacheName)
|
||||||
{
|
{
|
||||||
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
|
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
|
||||||
return AjaxResult.success(cacheKeys);
|
return AjaxResult.success(new TreeSet<>(cacheKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -110,6 +111,20 @@ public class SysDeptController extends BaseController
|
|||||||
return toAjax(deptService.updateDept(dept));
|
return toAjax(deptService.updateDept(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存部门排序
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
|
||||||
|
@Log(title = "保存部门排序", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/updateSort")
|
||||||
|
public AjaxResult updateSort(@RequestBody Map<String, String> params)
|
||||||
|
{
|
||||||
|
String[] deptIds = params.get("deptIds").split(",");
|
||||||
|
String[] orderNums = params.get("orderNums").split(",");
|
||||||
|
deptService.updateDeptSort(deptIds, orderNums);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除部门
|
* 删除部门
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 首页
|
* 首页
|
||||||
@@ -18,6 +25,9 @@ public class SysIndexController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RuoYiConfig ruoyiConfig;
|
private RuoYiConfig ruoyiConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService userService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问首页,提示语
|
* 访问首页,提示语
|
||||||
*/
|
*/
|
||||||
@@ -26,4 +36,29 @@ public class SysIndexController
|
|||||||
{
|
{
|
||||||
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解锁屏幕
|
||||||
|
*/
|
||||||
|
@PostMapping("/unlockscreen")
|
||||||
|
public AjaxResult unlockScreen(@RequestBody Map<String, String> body)
|
||||||
|
{
|
||||||
|
String password = body.get("password");
|
||||||
|
if (StringUtils.isEmpty(password))
|
||||||
|
{
|
||||||
|
return AjaxResult.error("密码不能为空");
|
||||||
|
}
|
||||||
|
String username = SecurityUtils.getUsername();
|
||||||
|
SysUser user = userService.selectUserByUserName(username);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return AjaxResult.error("服务器超时,请重新登录");
|
||||||
|
}
|
||||||
|
if (!SecurityUtils.matchesPassword(password, user.getPassword()))
|
||||||
|
{
|
||||||
|
return AjaxResult.error("密码错误,请重新输入");
|
||||||
|
}
|
||||||
|
|
||||||
|
return AjaxResult.success("解锁成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -12,9 +13,15 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginBody;
|
import com.ruoyi.common.core.domain.model.LoginBody;
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.web.service.SysLoginService;
|
import com.ruoyi.framework.web.service.SysLoginService;
|
||||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
import com.ruoyi.framework.web.service.SysPermissionService;
|
||||||
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +41,12 @@ public class SysLoginController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SysPermissionService permissionService;
|
private SysPermissionService permissionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysConfigService configService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
*
|
*
|
||||||
@@ -59,15 +72,24 @@ public class SysLoginController
|
|||||||
@GetMapping("getInfo")
|
@GetMapping("getInfo")
|
||||||
public AjaxResult getInfo()
|
public AjaxResult getInfo()
|
||||||
{
|
{
|
||||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
SysUser user = loginUser.getUser();
|
||||||
// 角色集合
|
// 角色集合
|
||||||
Set<String> roles = permissionService.getRolePermission(user);
|
Set<String> roles = permissionService.getRolePermission(user);
|
||||||
// 权限集合
|
// 权限集合
|
||||||
Set<String> permissions = permissionService.getMenuPermission(user);
|
Set<String> permissions = permissionService.getMenuPermission(user);
|
||||||
|
if (!loginUser.getPermissions().equals(permissions))
|
||||||
|
{
|
||||||
|
loginUser.setPermissions(permissions);
|
||||||
|
tokenService.refreshToken(loginUser);
|
||||||
|
}
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
ajax.put("user", user);
|
ajax.put("user", user);
|
||||||
ajax.put("roles", roles);
|
ajax.put("roles", roles);
|
||||||
ajax.put("permissions", permissions);
|
ajax.put("permissions", permissions);
|
||||||
|
ajax.put("pwdChrtype", getSysAccountChrtype());
|
||||||
|
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
|
||||||
|
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,4 +105,34 @@ public class SysLoginController
|
|||||||
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
|
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
|
||||||
return AjaxResult.success(menuService.buildMenus(menus));
|
return AjaxResult.success(menuService.buildMenus(menus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取用户密码自定义配置规则
|
||||||
|
public String getSysAccountChrtype()
|
||||||
|
{
|
||||||
|
return Convert.toStr(configService.selectConfigByKey("sys.account.chrtype"), "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查初始密码是否提醒修改
|
||||||
|
public boolean initPasswordIsModify(Date pwdUpdateDate)
|
||||||
|
{
|
||||||
|
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
|
||||||
|
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查密码是否过期
|
||||||
|
public boolean passwordIsExpiration(Date pwdUpdateDate)
|
||||||
|
{
|
||||||
|
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
|
||||||
|
if (passwordValidateDays != null && passwordValidateDays > 0)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNull(pwdUpdateDate))
|
||||||
|
{
|
||||||
|
// 如果从未修改过初始密码,直接提醒过期
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Date nowDate = DateUtils.getNowDate();
|
||||||
|
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -93,6 +94,10 @@ public class SysMenuController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
|
||||||
}
|
}
|
||||||
|
else if (!menuService.checkRouteConfigUnique(menu))
|
||||||
|
{
|
||||||
|
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
|
||||||
|
}
|
||||||
menu.setCreateBy(getUsername());
|
menu.setCreateBy(getUsername());
|
||||||
return toAjax(menuService.insertMenu(menu));
|
return toAjax(menuService.insertMenu(menu));
|
||||||
}
|
}
|
||||||
@@ -117,10 +122,28 @@ public class SysMenuController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
|
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
|
||||||
}
|
}
|
||||||
|
else if (!menuService.checkRouteConfigUnique(menu))
|
||||||
|
{
|
||||||
|
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
|
||||||
|
}
|
||||||
menu.setUpdateBy(getUsername());
|
menu.setUpdateBy(getUsername());
|
||||||
return toAjax(menuService.updateMenu(menu));
|
return toAjax(menuService.updateMenu(menu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存菜单排序
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
|
||||||
|
@Log(title = "保存菜单排序", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/updateSort")
|
||||||
|
public AjaxResult updateSort(@RequestBody Map<String, String> params)
|
||||||
|
{
|
||||||
|
String[] menuIds = params.get("menuIds").split(",");
|
||||||
|
String[] orderNums = params.get("orderNums").split(",");
|
||||||
|
menuService.updateMenuSort(menuIds, orderNums);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除菜单
|
* 删除菜单
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,13 +11,16 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.system.domain.SysNotice;
|
import com.ruoyi.system.domain.SysNotice;
|
||||||
|
import com.ruoyi.system.service.ISysNoticeReadService;
|
||||||
import com.ruoyi.system.service.ISysNoticeService;
|
import com.ruoyi.system.service.ISysNoticeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +35,9 @@ public class SysNoticeController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysNoticeService noticeService;
|
private ISysNoticeService noticeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysNoticeReadService noticeReadService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取通知公告列表
|
* 获取通知公告列表
|
||||||
*/
|
*/
|
||||||
@@ -47,7 +53,6 @@ public class SysNoticeController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 根据通知公告编号获取详细信息
|
* 根据通知公告编号获取详细信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('system:notice:query')")
|
|
||||||
@GetMapping(value = "/{noticeId}")
|
@GetMapping(value = "/{noticeId}")
|
||||||
public AjaxResult getInfo(@PathVariable Long noticeId)
|
public AjaxResult getInfo(@PathVariable Long noticeId)
|
||||||
{
|
{
|
||||||
@@ -78,6 +83,59 @@ public class SysNoticeController extends BaseController
|
|||||||
return toAjax(noticeService.updateNotice(notice));
|
return toAjax(noticeService.updateNotice(notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页顶部公告列表(返回全部正常公告,带当前用户已读标记,最多5条)
|
||||||
|
*/
|
||||||
|
@GetMapping("/listTop")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult listTop()
|
||||||
|
{
|
||||||
|
Long userId = getUserId();
|
||||||
|
List<SysNotice> list = noticeReadService.selectNoticeListWithReadStatus(userId, 5);
|
||||||
|
long unreadCount = list.stream().filter(n -> !n.getIsRead()).count();
|
||||||
|
AjaxResult result = AjaxResult.success(list);
|
||||||
|
result.put("unreadCount", unreadCount);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记公告已读
|
||||||
|
*/
|
||||||
|
@PostMapping("/markRead")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult markRead(Long noticeId)
|
||||||
|
{
|
||||||
|
Long userId = getUserId();
|
||||||
|
noticeReadService.markRead(noticeId, userId);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量标记已读
|
||||||
|
*/
|
||||||
|
@PostMapping("/markReadAll")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult markReadAll(String ids)
|
||||||
|
{
|
||||||
|
Long userId = getUserId();
|
||||||
|
Long[] noticeIds = Convert.toLongArray(ids);
|
||||||
|
noticeReadService.markReadBatch(userId, noticeIds);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已读用户列表数据
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:notice:list')")
|
||||||
|
@GetMapping("/readUsers/list")
|
||||||
|
@ResponseBody
|
||||||
|
public TableDataInfo readUsersList(Long noticeId, String searchValue)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<?> list = noticeReadService.selectReadUsersByNoticeId(noticeId, searchValue);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除通知公告
|
* 删除通知公告
|
||||||
*/
|
*/
|
||||||
@@ -86,6 +144,7 @@ public class SysNoticeController extends BaseController
|
|||||||
@DeleteMapping("/{noticeIds}")
|
@DeleteMapping("/{noticeIds}")
|
||||||
public AjaxResult remove(@PathVariable Long[] noticeIds)
|
public AjaxResult remove(@PathVariable Long[] noticeIds)
|
||||||
{
|
{
|
||||||
|
noticeReadService.deleteByNoticeIds(noticeIds);
|
||||||
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-23
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -16,9 +17,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||||
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
@@ -60,27 +63,22 @@ public class SysProfileController extends BaseController
|
|||||||
public AjaxResult updateProfile(@RequestBody SysUser user)
|
public AjaxResult updateProfile(@RequestBody SysUser user)
|
||||||
{
|
{
|
||||||
LoginUser loginUser = getLoginUser();
|
LoginUser loginUser = getLoginUser();
|
||||||
SysUser sysUser = loginUser.getUser();
|
SysUser currentUser = loginUser.getUser();
|
||||||
user.setUserName(sysUser.getUserName());
|
currentUser.setNickName(user.getNickName());
|
||||||
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
currentUser.setEmail(user.getEmail());
|
||||||
|
currentUser.setPhonenumber(user.getPhonenumber());
|
||||||
|
currentUser.setSex(user.getSex());
|
||||||
|
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
user.setUserId(sysUser.getUserId());
|
if (userService.updateUserProfile(currentUser) > 0)
|
||||||
user.setPassword(null);
|
|
||||||
user.setAvatar(null);
|
|
||||||
user.setDeptId(null);
|
|
||||||
if (userService.updateUserProfile(user) > 0)
|
|
||||||
{
|
{
|
||||||
// 更新缓存用户信息
|
// 更新缓存用户信息
|
||||||
sysUser.setNickName(user.getNickName());
|
|
||||||
sysUser.setPhonenumber(user.getPhonenumber());
|
|
||||||
sysUser.setEmail(user.getEmail());
|
|
||||||
sysUser.setSex(user.getSex());
|
|
||||||
tokenService.setLoginUser(loginUser);
|
tokenService.setLoginUser(loginUser);
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
@@ -92,11 +90,14 @@ public class SysProfileController extends BaseController
|
|||||||
*/
|
*/
|
||||||
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
|
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping("/updatePwd")
|
@PutMapping("/updatePwd")
|
||||||
public AjaxResult updatePwd(String oldPassword, String newPassword)
|
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
|
||||||
{
|
{
|
||||||
|
String oldPassword = params.get("oldPassword");
|
||||||
|
String newPassword = params.get("newPassword");
|
||||||
LoginUser loginUser = getLoginUser();
|
LoginUser loginUser = getLoginUser();
|
||||||
String userName = loginUser.getUsername();
|
Long userId = loginUser.getUserId();
|
||||||
String password = loginUser.getPassword();
|
SysUser user = userService.selectUserById(userId);
|
||||||
|
String password = user.getPassword();
|
||||||
if (!SecurityUtils.matchesPassword(oldPassword, password))
|
if (!SecurityUtils.matchesPassword(oldPassword, password))
|
||||||
{
|
{
|
||||||
return error("修改密码失败,旧密码错误");
|
return error("修改密码失败,旧密码错误");
|
||||||
@@ -105,10 +106,12 @@ public class SysProfileController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("新密码不能与旧密码相同");
|
return error("新密码不能与旧密码相同");
|
||||||
}
|
}
|
||||||
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
|
newPassword = SecurityUtils.encryptPassword(newPassword);
|
||||||
|
if (userService.resetUserPwd(userId, newPassword) > 0)
|
||||||
{
|
{
|
||||||
// 更新缓存用户密码
|
// 更新缓存用户密码&密码最后更新时间
|
||||||
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
|
loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
|
||||||
|
loginUser.getUser().setPassword(newPassword);
|
||||||
tokenService.setLoginUser(loginUser);
|
tokenService.setLoginUser(loginUser);
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
@@ -125,9 +128,14 @@ public class SysProfileController extends BaseController
|
|||||||
if (!file.isEmpty())
|
if (!file.isEmpty())
|
||||||
{
|
{
|
||||||
LoginUser loginUser = getLoginUser();
|
LoginUser loginUser = getLoginUser();
|
||||||
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
|
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
|
||||||
if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
|
if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
|
||||||
{
|
{
|
||||||
|
String oldAvatar = loginUser.getUser().getAvatar();
|
||||||
|
if (StringUtils.isNotEmpty(oldAvatar))
|
||||||
|
{
|
||||||
|
FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar));
|
||||||
|
}
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
ajax.put("imgUrl", avatar);
|
ajax.put("imgUrl", avatar);
|
||||||
// 更新缓存用户头像
|
// 更新缓存用户头像
|
||||||
|
|||||||
@@ -19,10 +19,8 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
import com.ruoyi.framework.web.service.SysPermissionService;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
@@ -128,14 +126,8 @@ public class SysRoleController extends BaseController
|
|||||||
|
|
||||||
if (roleService.updateRole(role) > 0)
|
if (roleService.updateRole(role) > 0)
|
||||||
{
|
{
|
||||||
// 更新缓存用户权限
|
// 刷新所有持有该角色的在线用户权限
|
||||||
LoginUser loginUser = getLoginUser();
|
tokenService.refreshPermissionByRoleId(role.getRoleId(), permissionService);
|
||||||
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 success();
|
return success();
|
||||||
}
|
}
|
||||||
return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
|
return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
|
||||||
|
|||||||
@@ -101,18 +101,18 @@ public class SysUserController extends BaseController
|
|||||||
@GetMapping(value = { "/", "/{userId}" })
|
@GetMapping(value = { "/", "/{userId}" })
|
||||||
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
|
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
|
||||||
{
|
{
|
||||||
userService.checkUserDataScope(userId);
|
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
List<SysRole> roles = roleService.selectRoleAll();
|
|
||||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
|
||||||
ajax.put("posts", postService.selectPostAll());
|
|
||||||
if (StringUtils.isNotNull(userId))
|
if (StringUtils.isNotNull(userId))
|
||||||
{
|
{
|
||||||
|
userService.checkUserDataScope(userId);
|
||||||
SysUser sysUser = userService.selectUserById(userId);
|
SysUser sysUser = userService.selectUserById(userId);
|
||||||
ajax.put(AjaxResult.DATA_TAG, sysUser);
|
ajax.put(AjaxResult.DATA_TAG, sysUser);
|
||||||
ajax.put("postIds", postService.selectPostListByUserId(userId));
|
ajax.put("postIds", postService.selectPostListByUserId(userId));
|
||||||
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
|
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
List<SysRole> roles = roleService.selectRoleAll();
|
||||||
|
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
|
ajax.put("posts", postService.selectPostAll());
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +124,8 @@ public class SysUserController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysUser user)
|
public AjaxResult add(@Validated @RequestBody SysUser user)
|
||||||
{
|
{
|
||||||
|
deptService.checkDeptDataScope(user.getDeptId());
|
||||||
|
roleService.checkRoleDataScope(user.getRoleIds());
|
||||||
if (!userService.checkUserNameUnique(user))
|
if (!userService.checkUserNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||||
@@ -151,6 +153,8 @@ public class SysUserController extends BaseController
|
|||||||
{
|
{
|
||||||
userService.checkUserAllowed(user);
|
userService.checkUserAllowed(user);
|
||||||
userService.checkUserDataScope(user.getUserId());
|
userService.checkUserDataScope(user.getUserId());
|
||||||
|
deptService.checkDeptDataScope(user.getDeptId());
|
||||||
|
roleService.checkRoleDataScope(user.getRoleIds());
|
||||||
if (!userService.checkUserNameUnique(user))
|
if (!userService.checkUserNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||||
@@ -222,7 +226,7 @@ public class SysUserController extends BaseController
|
|||||||
SysUser user = userService.selectUserById(userId);
|
SysUser user = userService.selectUserById(userId);
|
||||||
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||||
ajax.put("user", user);
|
ajax.put("user", user);
|
||||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +239,7 @@ public class SysUserController extends BaseController
|
|||||||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||||
{
|
{
|
||||||
userService.checkUserDataScope(userId);
|
userService.checkUserDataScope(userId);
|
||||||
|
roleService.checkRoleDataScope(roleIds);
|
||||||
userService.insertUserAuth(userId, roleIds);
|
userService.insertUserAuth(userId, roleIds);
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
restart.include.json=/com.alibaba.fastjson.*.jar
|
restart.include.json=/com.alibaba.fastjson2.*.jar
|
||||||
@@ -3,11 +3,9 @@ ruoyi:
|
|||||||
# 名称
|
# 名称
|
||||||
name: RuoYi
|
name: RuoYi
|
||||||
# 版本
|
# 版本
|
||||||
version: 3.8.6
|
version: 3.9.2
|
||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2023
|
copyrightYear: 2026
|
||||||
# 实例演示开关
|
|
||||||
demoEnabled: true
|
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
profile: D:/ruoyi/uploadPath
|
profile: D:/ruoyi/uploadPath
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
@@ -121,6 +119,13 @@ swagger:
|
|||||||
# 请求前缀
|
# 请求前缀
|
||||||
pathMapping: /dev-api
|
pathMapping: /dev-api
|
||||||
|
|
||||||
|
# 防盗链配置
|
||||||
|
referer:
|
||||||
|
# 防盗链开关
|
||||||
|
enabled: false
|
||||||
|
# 允许的域名列表
|
||||||
|
allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
|
|||||||
+3
-16
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -59,13 +59,6 @@
|
|||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 动态数据源 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
|
||||||
<version>3.5.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 阿里JSON解析器 -->
|
<!-- 阿里JSON解析器 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.fastjson2</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
@@ -84,12 +77,6 @@
|
|||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- yml解析器 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.yaml</groupId>
|
|
||||||
<artifactId>snakeyaml</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Token生成与解析-->
|
<!-- Token生成与解析-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
@@ -116,8 +103,8 @@
|
|||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>eu.bitwalker</groupId>
|
<groupId>nl.basjes.parse.useragent</groupId>
|
||||||
<artifactId>UserAgentUtils</artifactId>
|
<artifactId>yauaa</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- servlet包 -->
|
<!-- servlet包 -->
|
||||||
|
|||||||
@@ -16,15 +16,25 @@ import java.lang.annotation.Target;
|
|||||||
@Documented
|
@Documented
|
||||||
public @interface DataScope
|
public @interface DataScope
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 用户表的别名
|
||||||
|
*/
|
||||||
|
public String userAlias() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门表的别名
|
* 部门表的别名
|
||||||
*/
|
*/
|
||||||
public String deptAlias() default "";
|
public String deptAlias() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户表的别名
|
* 用户字段名
|
||||||
*/
|
*/
|
||||||
public String userAlias() default "";
|
public String userField() default "user_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门字段名
|
||||||
|
*/
|
||||||
|
public String deptField() default "dept_id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
|
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
|
||||||
|
|||||||
@@ -83,11 +83,21 @@ public @interface Excel
|
|||||||
*/
|
*/
|
||||||
public String prompt() default "";
|
public String prompt() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许内容换行
|
||||||
|
*/
|
||||||
|
public boolean wrapText() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置只能选择不能输入的列内容.
|
* 设置只能选择不能输入的列内容.
|
||||||
*/
|
*/
|
||||||
public String[] combo() default {};
|
public String[] combo() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
|
||||||
|
*/
|
||||||
|
public boolean comboReadDict() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
|
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
|
||||||
*/
|
*/
|
||||||
@@ -171,7 +181,7 @@ public @interface Excel
|
|||||||
|
|
||||||
public enum ColumnType
|
public enum ColumnType
|
||||||
{
|
{
|
||||||
NUMERIC(0), STRING(1), IMAGE(2);
|
NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
ColumnType(int value)
|
ColumnType(int value)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.ruoyi.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
|
||||||
|
import com.ruoyi.common.enums.DesensitizedType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据脱敏注解
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@JacksonAnnotationsInside
|
||||||
|
@JsonSerialize(using = SensitiveJsonSerializer.class)
|
||||||
|
public @interface Sensitive
|
||||||
|
{
|
||||||
|
DesensitizedType desensitizedType();
|
||||||
|
}
|
||||||
@@ -21,9 +21,6 @@ public class RuoYiConfig
|
|||||||
/** 版权年份 */
|
/** 版权年份 */
|
||||||
private String copyrightYear;
|
private String copyrightYear;
|
||||||
|
|
||||||
/** 实例演示开关 */
|
|
||||||
private boolean demoEnabled;
|
|
||||||
|
|
||||||
/** 上传路径 */
|
/** 上传路径 */
|
||||||
private static String profile;
|
private static String profile;
|
||||||
|
|
||||||
@@ -63,16 +60,6 @@ public class RuoYiConfig
|
|||||||
this.copyrightYear = copyrightYear;
|
this.copyrightYear = copyrightYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDemoEnabled()
|
|
||||||
{
|
|
||||||
return demoEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDemoEnabled(boolean demoEnabled)
|
|
||||||
{
|
|
||||||
this.demoEnabled = demoEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getProfile()
|
public static String getProfile()
|
||||||
{
|
{
|
||||||
return profile;
|
return profile;
|
||||||
|
|||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package com.ruoyi.common.config.serializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.BeanProperty;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||||
|
import com.ruoyi.common.annotation.Sensitive;
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.enums.DesensitizedType;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据脱敏序列化过滤
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
|
||||||
|
{
|
||||||
|
private DesensitizedType desensitizedType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
|
||||||
|
{
|
||||||
|
if (desensitization())
|
||||||
|
{
|
||||||
|
gen.writeString(desensitizedType.desensitizer().apply(value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gen.writeString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
|
||||||
|
throws JsonMappingException
|
||||||
|
{
|
||||||
|
Sensitive annotation = property.getAnnotation(Sensitive.class);
|
||||||
|
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
|
||||||
|
{
|
||||||
|
this.desensitizedType = annotation.desensitizedType();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return prov.findValueSerializer(property.getType(), property);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要脱敏处理
|
||||||
|
*/
|
||||||
|
private boolean desensitization()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LoginUser securityUser = SecurityUtils.getLoginUser();
|
||||||
|
// 管理员不脱敏
|
||||||
|
return !securityUser.getUser().isAdmin();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.common.constant;
|
package com.ruoyi.common.constant;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,6 +20,11 @@ public class Constants
|
|||||||
*/
|
*/
|
||||||
public static final String GBK = "GBK";
|
public static final String GBK = "GBK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统语言
|
||||||
|
*/
|
||||||
|
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www主域
|
* www主域
|
||||||
*/
|
*/
|
||||||
@@ -64,6 +70,26 @@ public class Constants
|
|||||||
*/
|
*/
|
||||||
public static final String LOGIN_FAIL = "Error";
|
public static final String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有权限标识
|
||||||
|
*/
|
||||||
|
public static final String ALL_PERMISSION = "*:*:*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员角色权限标识
|
||||||
|
*/
|
||||||
|
public static final String SUPER_ADMIN = "admin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色权限分隔符
|
||||||
|
*/
|
||||||
|
public static final String ROLE_DELIMITER = ",";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限标识分隔符
|
||||||
|
*/
|
||||||
|
public static final String PERMISSION_DELIMITER = ",";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码有效期(分钟)
|
* 验证码有效期(分钟)
|
||||||
*/
|
*/
|
||||||
@@ -129,14 +155,50 @@ public class Constants
|
|||||||
*/
|
*/
|
||||||
public static final String LOOKUP_LDAPS = "ldaps:";
|
public static final String LOOKUP_LDAPS = "ldaps:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||||
|
*/
|
||||||
|
public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||||
*/
|
*/
|
||||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
|
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务违规的字符
|
* 定时任务违规的字符
|
||||||
*/
|
*/
|
||||||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||||
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
|
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门相关常量
|
||||||
|
*/
|
||||||
|
public static class Dept
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 全部数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_ALL = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_CUSTOM = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_DEPT = "3";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门及以下数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅本人数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_SELF = "5";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ public class GenConstants
|
|||||||
/** 上级菜单名称字段 */
|
/** 上级菜单名称字段 */
|
||||||
public static final String PARENT_MENU_NAME = "parentMenuName";
|
public static final String PARENT_MENU_NAME = "parentMenuName";
|
||||||
|
|
||||||
|
/** 生成详情页开关 */
|
||||||
|
public static final String GEN_VIEW = "genView";
|
||||||
|
|
||||||
/** 数据库字符串类型 */
|
/** 数据库字符串类型 */
|
||||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ public class UserConstants
|
|||||||
/** 用户封禁状态 */
|
/** 用户封禁状态 */
|
||||||
public static final String USER_DISABLE = "1";
|
public static final String USER_DISABLE = "1";
|
||||||
|
|
||||||
|
/** 角色正常状态 */
|
||||||
|
public static final String ROLE_NORMAL = "0";
|
||||||
|
|
||||||
/** 角色封禁状态 */
|
/** 角色封禁状态 */
|
||||||
public static final String ROLE_DISABLE = "1";
|
public static final String ROLE_DISABLE = "1";
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import java.io.Serializable;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Treeselect树结构实体类
|
* Treeselect树结构实体类
|
||||||
@@ -22,6 +24,9 @@ public class TreeSelect implements Serializable
|
|||||||
/** 节点名称 */
|
/** 节点名称 */
|
||||||
private String label;
|
private String label;
|
||||||
|
|
||||||
|
/** 节点禁用 */
|
||||||
|
private boolean disabled = false;
|
||||||
|
|
||||||
/** 子节点 */
|
/** 子节点 */
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
private List<TreeSelect> children;
|
private List<TreeSelect> children;
|
||||||
@@ -35,6 +40,7 @@ public class TreeSelect implements Serializable
|
|||||||
{
|
{
|
||||||
this.id = dept.getDeptId();
|
this.id = dept.getDeptId();
|
||||||
this.label = dept.getDeptName();
|
this.label = dept.getDeptName();
|
||||||
|
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
|
||||||
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +71,16 @@ public class TreeSelect implements Serializable
|
|||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDisabled()
|
||||||
|
{
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisabled(boolean disabled)
|
||||||
|
{
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
public List<TreeSelect> getChildren()
|
public List<TreeSelect> getChildren()
|
||||||
{
|
{
|
||||||
return children;
|
return children;
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public class SysMenu extends BaseEntity
|
|||||||
/** 路由参数 */
|
/** 路由参数 */
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
|
/** 路由名称,默认和路由地址相同的驼峰格式(注意:因为vue3版本的router会删除名称相同路由,为避免名字的冲突,特殊情况可以自定义) */
|
||||||
|
private String routeName;
|
||||||
|
|
||||||
/** 是否为外链(0是 1否) */
|
/** 是否为外链(0是 1否) */
|
||||||
private String isFrame;
|
private String isFrame;
|
||||||
|
|
||||||
@@ -151,6 +154,16 @@ public class SysMenu extends BaseEntity
|
|||||||
this.query = query;
|
this.query = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRouteName()
|
||||||
|
{
|
||||||
|
return routeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRouteName(String routeName)
|
||||||
|
{
|
||||||
|
this.routeName = routeName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getIsFrame()
|
public String getIsFrame()
|
||||||
{
|
{
|
||||||
return isFrame;
|
return isFrame;
|
||||||
@@ -242,6 +255,8 @@ public class SysMenu extends BaseEntity
|
|||||||
.append("orderNum", getOrderNum())
|
.append("orderNum", getOrderNum())
|
||||||
.append("path", getPath())
|
.append("path", getPath())
|
||||||
.append("component", getComponent())
|
.append("component", getComponent())
|
||||||
|
.append("query", getQuery())
|
||||||
|
.append("routeName", getRouteName())
|
||||||
.append("isFrame", getIsFrame())
|
.append("isFrame", getIsFrame())
|
||||||
.append("IsCache", getIsCache())
|
.append("IsCache", getIsCache())
|
||||||
.append("menuType", getMenuType())
|
.append("menuType", getMenuType())
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import java.util.List;
|
|||||||
import javax.validation.constraints.*;
|
import javax.validation.constraints.*;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import com.ruoyi.common.annotation.Excel.ColumnType;
|
import com.ruoyi.common.annotation.Excel.ColumnType;
|
||||||
import com.ruoyi.common.annotation.Excel.Type;
|
import com.ruoyi.common.annotation.Excel.Type;
|
||||||
import com.ruoyi.common.annotation.Excels;
|
import com.ruoyi.common.annotation.Excels;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.xss.Xss;
|
import com.ruoyi.common.xss.Xss;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +25,7 @@ public class SysUser extends BaseEntity
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 用户ID */
|
/** 用户ID */
|
||||||
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
/** 部门ID */
|
/** 部门ID */
|
||||||
@@ -42,7 +45,7 @@ public class SysUser extends BaseEntity
|
|||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
/** 手机号码 */
|
/** 手机号码 */
|
||||||
@Excel(name = "手机号码")
|
@Excel(name = "手机号码", cellType = ColumnType.TEXT)
|
||||||
private String phonenumber;
|
private String phonenumber;
|
||||||
|
|
||||||
/** 用户性别 */
|
/** 用户性别 */
|
||||||
@@ -55,8 +58,8 @@ public class SysUser extends BaseEntity
|
|||||||
/** 密码 */
|
/** 密码 */
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
/** 帐号状态(0正常 1停用) */
|
/** 账号状态(0正常 1停用) */
|
||||||
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
|
@Excel(name = "账号状态", readConverterExp = "0=正常,1=停用")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
/** 删除标志(0代表存在 2代表删除) */
|
/** 删除标志(0代表存在 2代表删除) */
|
||||||
@@ -67,9 +70,13 @@ public class SysUser extends BaseEntity
|
|||||||
private String loginIp;
|
private String loginIp;
|
||||||
|
|
||||||
/** 最后登录时间 */
|
/** 最后登录时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@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;
|
private Date loginDate;
|
||||||
|
|
||||||
|
/** 密码最后更新时间 */
|
||||||
|
private Date pwdUpdateDate;
|
||||||
|
|
||||||
/** 部门对象 */
|
/** 部门对象 */
|
||||||
@Excels({
|
@Excels({
|
||||||
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
|
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
|
||||||
@@ -111,12 +118,7 @@ public class SysUser extends BaseEntity
|
|||||||
|
|
||||||
public boolean isAdmin()
|
public boolean isAdmin()
|
||||||
{
|
{
|
||||||
return isAdmin(this.userId);
|
return SecurityUtils.isAdmin(this.userId);
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAdmin(Long userId)
|
|
||||||
{
|
|
||||||
return userId != null && 1L == userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getDeptId()
|
public Long getDeptId()
|
||||||
@@ -197,6 +199,7 @@ public class SysUser extends BaseEntity
|
|||||||
this.avatar = avatar;
|
this.avatar = avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
||||||
public String getPassword()
|
public String getPassword()
|
||||||
{
|
{
|
||||||
return password;
|
return password;
|
||||||
@@ -247,6 +250,16 @@ public class SysUser extends BaseEntity
|
|||||||
this.loginDate = loginDate;
|
this.loginDate = loginDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getPwdUpdateDate()
|
||||||
|
{
|
||||||
|
return pwdUpdateDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPwdUpdateDate(Date pwdUpdateDate)
|
||||||
|
{
|
||||||
|
this.pwdUpdateDate = pwdUpdateDate;
|
||||||
|
}
|
||||||
|
|
||||||
public SysDept getDept()
|
public SysDept getDept()
|
||||||
{
|
{
|
||||||
return dept;
|
return dept;
|
||||||
@@ -313,6 +326,7 @@ public class SysUser extends BaseEntity
|
|||||||
.append("delFlag", getDelFlag())
|
.append("delFlag", getDelFlag())
|
||||||
.append("loginIp", getLoginIp())
|
.append("loginIp", getLoginIp())
|
||||||
.append("loginDate", getLoginDate())
|
.append("loginDate", getLoginDate())
|
||||||
|
.append("pwdUpdateDate", getPwdUpdateDate())
|
||||||
.append("createBy", getCreateBy())
|
.append("createBy", getCreateBy())
|
||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
.append("updateBy", getUpdateBy())
|
.append("updateBy", getUpdateBy())
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class TableDataInfo implements Serializable
|
|||||||
* @param list 列表数据
|
* @param list 列表数据
|
||||||
* @param total 总记录数
|
* @param total 总记录数
|
||||||
*/
|
*/
|
||||||
public TableDataInfo(List<?> list, int total)
|
public TableDataInfo(List<?> list, long total)
|
||||||
{
|
{
|
||||||
this.rows = list;
|
this.rows = list;
|
||||||
this.total = total;
|
this.total = total;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package com.ruoyi.common.core.text;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型转换器
|
* 类型转换器
|
||||||
@@ -364,6 +364,10 @@ public class Convert
|
|||||||
*/
|
*/
|
||||||
public static String[] toStrArray(String str)
|
public static String[] toStrArray(String str)
|
||||||
{
|
{
|
||||||
|
if (StringUtils.isEmpty(str))
|
||||||
|
{
|
||||||
|
return new String[] {};
|
||||||
|
}
|
||||||
return toStrArray(",", str);
|
return toStrArray(",", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +540,7 @@ public class Convert
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为boolean<br>
|
* 转换为boolean<br>
|
||||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
* String支持的值为:true、false、yes、ok、no、1、0、是、否, 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||||
* 转换失败不会报错
|
* 转换失败不会报错
|
||||||
*
|
*
|
||||||
* @param value 被转换的值
|
* @param value 被转换的值
|
||||||
@@ -565,10 +569,12 @@ public class Convert
|
|||||||
case "yes":
|
case "yes":
|
||||||
case "ok":
|
case "ok":
|
||||||
case "1":
|
case "1":
|
||||||
|
case "是":
|
||||||
return true;
|
return true;
|
||||||
case "false":
|
case "false":
|
||||||
case "no":
|
case "no":
|
||||||
case "0":
|
case "0":
|
||||||
|
case "否":
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
@@ -791,14 +797,23 @@ public class Convert
|
|||||||
{
|
{
|
||||||
return (String) obj;
|
return (String) obj;
|
||||||
}
|
}
|
||||||
else if (obj instanceof byte[])
|
else if (obj instanceof byte[] || obj instanceof Byte[])
|
||||||
|
{
|
||||||
|
if (obj instanceof byte[])
|
||||||
{
|
{
|
||||||
return str((byte[]) obj, charset);
|
return str((byte[]) obj, charset);
|
||||||
}
|
}
|
||||||
else if (obj instanceof Byte[])
|
else
|
||||||
{
|
{
|
||||||
byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
|
Byte[] bytes = (Byte[]) obj;
|
||||||
return str(bytes, charset);
|
int length = bytes.length;
|
||||||
|
byte[] dest = new byte[length];
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
dest[i] = bytes[i];
|
||||||
|
}
|
||||||
|
return str(dest, charset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (obj instanceof ByteBuffer)
|
else if (obj instanceof ByteBuffer)
|
||||||
{
|
{
|
||||||
@@ -954,9 +969,7 @@ public class Convert
|
|||||||
c[i] = (char) (c[i] - 65248);
|
c[i] = (char) (c[i] - 65248);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String returnString = new String(c);
|
return new String(c);
|
||||||
|
|
||||||
return returnString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -977,7 +990,12 @@ public class Convert
|
|||||||
String s = "";
|
String s = "";
|
||||||
for (int i = 0; i < fraction.length; i++)
|
for (int i = 0; i < fraction.length; i++)
|
||||||
{
|
{
|
||||||
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
|
// 优化double计算精度丢失问题
|
||||||
|
BigDecimal nNum = new BigDecimal(n);
|
||||||
|
BigDecimal decimal = new BigDecimal(10);
|
||||||
|
BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
|
||||||
|
double d = scale.doubleValue();
|
||||||
|
s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
|
||||||
}
|
}
|
||||||
if (s.length() < 1)
|
if (s.length() < 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.ruoyi.common.enums;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import com.ruoyi.common.utils.DesensitizedUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脱敏类型
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public enum DesensitizedType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 姓名,第2位星号替换
|
||||||
|
*/
|
||||||
|
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码,全部字符都用*代替
|
||||||
|
*/
|
||||||
|
PASSWORD(DesensitizedUtil::password),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证,中间10位星号替换
|
||||||
|
*/
|
||||||
|
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号,中间4位星号替换
|
||||||
|
*/
|
||||||
|
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
|
||||||
|
*/
|
||||||
|
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 银行卡号,保留最后4位,其他星号替换
|
||||||
|
*/
|
||||||
|
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌号码,包含普通车辆、新能源车辆
|
||||||
|
*/
|
||||||
|
CAR_LICENSE(DesensitizedUtil::carLicense);
|
||||||
|
|
||||||
|
private final Function<String, String> desensitizer;
|
||||||
|
|
||||||
|
DesensitizedType(Function<String, String> desensitizer)
|
||||||
|
{
|
||||||
|
this.desensitizer = desensitizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<String, String> desensitizer()
|
||||||
|
{
|
||||||
|
return desensitizer;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ package com.ruoyi.common.exception.file;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件上传 误异常类
|
* 文件上传无效扩展名异常类
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防盗链过滤器
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class RefererFilter implements Filter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 允许的域名列表
|
||||||
|
*/
|
||||||
|
public List<String> allowedDomains;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException
|
||||||
|
{
|
||||||
|
String domains = filterConfig.getInitParameter("allowedDomains");
|
||||||
|
this.allowedDomains = Arrays.asList(domains.split(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException
|
||||||
|
{
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse resp = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
String referer = req.getHeader("Referer");
|
||||||
|
|
||||||
|
// 如果Referer为空,拒绝访问
|
||||||
|
if (referer == null || referer.isEmpty())
|
||||||
|
{
|
||||||
|
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Referer是否在允许的域名列表中
|
||||||
|
boolean allowed = false;
|
||||||
|
for (String domain : allowedDomains)
|
||||||
|
{
|
||||||
|
if (referer.contains(domain))
|
||||||
|
{
|
||||||
|
allowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据检查结果决定是否放行
|
||||||
|
if (allowed)
|
||||||
|
{
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,10 +32,10 @@ public class XssFilter implements Filter
|
|||||||
String tempExcludes = filterConfig.getInitParameter("excludes");
|
String tempExcludes = filterConfig.getInitParameter("excludes");
|
||||||
if (StringUtils.isNotEmpty(tempExcludes))
|
if (StringUtils.isNotEmpty(tempExcludes))
|
||||||
{
|
{
|
||||||
String[] url = tempExcludes.split(",");
|
String[] urls = tempExcludes.split(",");
|
||||||
for (int i = 0; url != null && i < url.length; i++)
|
for (String url : urls)
|
||||||
{
|
{
|
||||||
excludes.add(url[i]);
|
excludes.add(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ public class Arith
|
|||||||
"The scale must be a positive integer or zero");
|
"The scale must be a positive integer or zero");
|
||||||
}
|
}
|
||||||
BigDecimal b = new BigDecimal(Double.toString(v));
|
BigDecimal b = new BigDecimal(Double.toString(v));
|
||||||
BigDecimal one = BigDecimal.ONE;
|
return b.divide(BigDecimal.ONE, scale, RoundingMode.HALF_UP).doubleValue();
|
||||||
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
|||||||
/**
|
/**
|
||||||
* 计算时间差
|
* 计算时间差
|
||||||
*
|
*
|
||||||
* @param endTime 最后时间
|
* @param endDate 最后时间
|
||||||
* @param startTime 开始时间
|
* @param startTime 开始时间
|
||||||
* @return 时间差(天/小时/分钟)
|
* @return 时间差(天/小时/分钟)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脱敏工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class DesensitizedUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 密码的全部字符都用*代替,比如:******
|
||||||
|
*
|
||||||
|
* @param password 密码
|
||||||
|
* @return 脱敏后的密码
|
||||||
|
*/
|
||||||
|
public static String password(String password)
|
||||||
|
{
|
||||||
|
if (StringUtils.isBlank(password))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return StringUtils.repeat('*', password.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌中间用*代替,如果是错误的车牌,不处理
|
||||||
|
*
|
||||||
|
* @param carLicense 完整的车牌号
|
||||||
|
* @return 脱敏后的车牌
|
||||||
|
*/
|
||||||
|
public static String carLicense(String carLicense)
|
||||||
|
{
|
||||||
|
if (StringUtils.isBlank(carLicense))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
// 普通车牌
|
||||||
|
if (carLicense.length() == 7)
|
||||||
|
{
|
||||||
|
carLicense = StringUtils.hide(carLicense, 3, 6);
|
||||||
|
}
|
||||||
|
else if (carLicense.length() == 8)
|
||||||
|
{
|
||||||
|
// 新能源车牌
|
||||||
|
carLicense = StringUtils.hide(carLicense, 3, 7);
|
||||||
|
}
|
||||||
|
return carLicense;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.ruoyi.common.utils;
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||||
@@ -56,6 +58,10 @@ public class DictUtils
|
|||||||
*/
|
*/
|
||||||
public static String getDictLabel(String dictType, String dictValue)
|
public static String getDictLabel(String dictType, String dictValue)
|
||||||
{
|
{
|
||||||
|
if (StringUtils.isEmpty(dictValue))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +74,10 @@ public class DictUtils
|
|||||||
*/
|
*/
|
||||||
public static String getDictValue(String dictType, String dictLabel)
|
public static String getDictValue(String dictType, String dictLabel)
|
||||||
{
|
{
|
||||||
|
if (StringUtils.isEmpty(dictLabel))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,37 +91,25 @@ public class DictUtils
|
|||||||
*/
|
*/
|
||||||
public static String getDictLabel(String dictType, String dictValue, String separator)
|
public static String getDictLabel(String dictType, String dictValue, String separator)
|
||||||
{
|
{
|
||||||
StringBuilder propertyString = new StringBuilder();
|
|
||||||
List<SysDictData> datas = getDictCache(dictType);
|
List<SysDictData> datas = getDictCache(dictType);
|
||||||
|
if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictValue))
|
||||||
if (StringUtils.isNotNull(datas))
|
|
||||||
{
|
{
|
||||||
if (StringUtils.containsAny(separator, dictValue))
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictValue(), dict.getDictLabel()), Map::putAll);
|
||||||
|
if (!StringUtils.contains(dictValue, separator))
|
||||||
{
|
{
|
||||||
for (SysDictData dict : datas)
|
return dictMap.getOrDefault(dictValue, StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
StringBuilder labelBuilder = new StringBuilder();
|
||||||
|
for (String seperatedValue : dictValue.split(separator))
|
||||||
{
|
{
|
||||||
for (String value : dictValue.split(separator))
|
if (dictMap.containsKey(seperatedValue))
|
||||||
{
|
{
|
||||||
if (value.equals(dict.getDictValue()))
|
labelBuilder.append(dictMap.get(seperatedValue)).append(separator);
|
||||||
{
|
|
||||||
propertyString.append(dict.getDictLabel()).append(separator);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return StringUtils.removeEnd(labelBuilder.toString(), separator);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (SysDictData dict : datas)
|
|
||||||
{
|
|
||||||
if (dictValue.equals(dict.getDictValue()))
|
|
||||||
{
|
|
||||||
return dict.getDictLabel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,35 +121,68 @@ public class DictUtils
|
|||||||
* @return 字典值
|
* @return 字典值
|
||||||
*/
|
*/
|
||||||
public static String getDictValue(String dictType, String dictLabel, String separator)
|
public static String getDictValue(String dictType, String dictLabel, String separator)
|
||||||
|
{
|
||||||
|
List<SysDictData> datas = getDictCache(dictType);
|
||||||
|
if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictLabel))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictLabel(), dict.getDictValue()), Map::putAll);
|
||||||
|
if (!StringUtils.contains(dictLabel, separator))
|
||||||
|
{
|
||||||
|
return dictMap.getOrDefault(dictLabel, StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
StringBuilder valueBuilder = new StringBuilder();
|
||||||
|
for (String seperatedValue : dictLabel.split(separator))
|
||||||
|
{
|
||||||
|
if (dictMap.containsKey(seperatedValue))
|
||||||
|
{
|
||||||
|
valueBuilder.append(dictMap.get(seperatedValue)).append(separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StringUtils.removeEnd(valueBuilder.toString(), separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据字典类型获取字典所有值
|
||||||
|
*
|
||||||
|
* @param dictType 字典类型
|
||||||
|
* @return 字典值
|
||||||
|
*/
|
||||||
|
public static String getDictValues(String dictType)
|
||||||
{
|
{
|
||||||
StringBuilder propertyString = new StringBuilder();
|
StringBuilder propertyString = new StringBuilder();
|
||||||
List<SysDictData> datas = getDictCache(dictType);
|
List<SysDictData> datas = getDictCache(dictType);
|
||||||
|
if (StringUtils.isNull(datas))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
for (SysDictData dict : datas)
|
||||||
|
{
|
||||||
|
propertyString.append(dict.getDictValue()).append(SEPARATOR);
|
||||||
|
}
|
||||||
|
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
|
/**
|
||||||
|
* 根据字典类型获取字典所有标签
|
||||||
|
*
|
||||||
|
* @param dictType 字典类型
|
||||||
|
* @return 字典值
|
||||||
|
*/
|
||||||
|
public static String getDictLabels(String dictType)
|
||||||
{
|
{
|
||||||
|
StringBuilder propertyString = new StringBuilder();
|
||||||
|
List<SysDictData> datas = getDictCache(dictType);
|
||||||
|
if (StringUtils.isNull(datas))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
for (SysDictData dict : datas)
|
for (SysDictData dict : datas)
|
||||||
{
|
{
|
||||||
for (String label : dictLabel.split(separator))
|
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
|
||||||
{
|
|
||||||
if (label.equals(dict.getDictLabel()))
|
|
||||||
{
|
|
||||||
propertyString.append(dict.getDictValue()).append(separator);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (SysDictData dict : datas)
|
|
||||||
{
|
|
||||||
if (dictLabel.equals(dict.getDictLabel()))
|
|
||||||
{
|
|
||||||
return dict.getDictValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
package com.ruoyi.common.utils;
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.util.PatternMatchUtils;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.HttpStatus;
|
import com.ruoyi.common.constant.HttpStatus;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
|
||||||
@@ -14,6 +20,7 @@ import com.ruoyi.common.exception.ServiceException;
|
|||||||
*/
|
*/
|
||||||
public class SecurityUtils
|
public class SecurityUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
**/
|
**/
|
||||||
@@ -107,6 +114,16 @@ public class SecurityUtils
|
|||||||
return passwordEncoder.matches(rawPassword, encodedPassword);
|
return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为管理员
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean isAdmin()
|
||||||
|
{
|
||||||
|
return isAdmin(getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为管理员
|
* 是否为管理员
|
||||||
*
|
*
|
||||||
@@ -117,4 +134,55 @@ public class SecurityUtils
|
|||||||
{
|
{
|
||||||
return userId != null && 1L == userId;
|
return userId != null && 1L == userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具备某权限
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
public static boolean hasPermi(String permission)
|
||||||
|
{
|
||||||
|
return hasPermi(getLoginUser().getPermissions(), permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否包含权限
|
||||||
|
*
|
||||||
|
* @param authorities 权限列表
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
public static boolean hasPermi(Collection<String> authorities, String permission)
|
||||||
|
{
|
||||||
|
return authorities.stream().filter(StringUtils::hasText)
|
||||||
|
.anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否拥有某个角色
|
||||||
|
*
|
||||||
|
* @param role 角色标识
|
||||||
|
* @return 用户是否具备某角色
|
||||||
|
*/
|
||||||
|
public static boolean hasRole(String role)
|
||||||
|
{
|
||||||
|
List<SysRole> roleList = getLoginUser().getUser().getRoles();
|
||||||
|
Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
|
||||||
|
return hasRole(roles, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否包含角色
|
||||||
|
*
|
||||||
|
* @param roles 角色列表
|
||||||
|
* @param role 角色
|
||||||
|
* @return 用户是否具备某角色权限
|
||||||
|
*/
|
||||||
|
public static boolean hasRole(Collection<String> roles, String role)
|
||||||
|
{
|
||||||
|
return roles.stream().filter(StringUtils::hasText)
|
||||||
|
.anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
/** 下划线 */
|
/** 下划线 */
|
||||||
private static final char SEPARATOR = '_';
|
private static final char SEPARATOR = '_';
|
||||||
|
|
||||||
|
/** 星号 */
|
||||||
|
private static final char ASTERISK = '*';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取参数不为空值
|
* 获取参数不为空值
|
||||||
*
|
*
|
||||||
@@ -163,6 +166,49 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
return (str == null ? "" : str.trim());
|
return (str == null ? "" : str.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换指定字符串的指定区间内字符为"*"
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param startInclude 开始位置(包含)
|
||||||
|
* @param endExclude 结束位置(不包含)
|
||||||
|
* @return 替换后的字符串
|
||||||
|
*/
|
||||||
|
public static String hide(CharSequence str, int startInclude, int endExclude)
|
||||||
|
{
|
||||||
|
if (isEmpty(str))
|
||||||
|
{
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
final int strLength = str.length();
|
||||||
|
if (startInclude > strLength)
|
||||||
|
{
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
if (endExclude > strLength)
|
||||||
|
{
|
||||||
|
endExclude = strLength;
|
||||||
|
}
|
||||||
|
if (startInclude > endExclude)
|
||||||
|
{
|
||||||
|
// 如果起始位置大于结束位置,不替换
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
final char[] chars = new char[strLength];
|
||||||
|
for (int i = 0; i < strLength; i++)
|
||||||
|
{
|
||||||
|
if (i >= startInclude && i < endExclude)
|
||||||
|
{
|
||||||
|
chars[i] = ASTERISK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chars[i] = str.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 截取字符串
|
* 截取字符串
|
||||||
*
|
*
|
||||||
@@ -240,6 +286,56 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
return str.substring(start, end);
|
return str.substring(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
|
||||||
|
*
|
||||||
|
* @param str 要截取的字符串
|
||||||
|
* @param open 起始字符串
|
||||||
|
* @param close 结束字符串
|
||||||
|
* @return 截取结果
|
||||||
|
*/
|
||||||
|
public static String substringBetweenLast(final String str, final String open, final String close)
|
||||||
|
{
|
||||||
|
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
|
||||||
|
{
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
final int start = str.indexOf(open);
|
||||||
|
if (start != INDEX_NOT_FOUND)
|
||||||
|
{
|
||||||
|
final int end = str.lastIndexOf(close);
|
||||||
|
if (end != INDEX_NOT_FOUND)
|
||||||
|
{
|
||||||
|
return str.substring(start + open.length(), end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULLSTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为空,并且不是空白字符
|
||||||
|
*
|
||||||
|
* @param str 要判断的value
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean hasText(String str)
|
||||||
|
{
|
||||||
|
return (str != null && !str.isEmpty() && containsText(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean containsText(CharSequence str)
|
||||||
|
{
|
||||||
|
int strLen = str.length();
|
||||||
|
for (int i = 0; i < strLen; i++)
|
||||||
|
{
|
||||||
|
if (!Character.isWhitespace(str.charAt(i)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化文本, {} 表示占位符<br>
|
* 格式化文本, {} 表示占位符<br>
|
||||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||||
@@ -285,6 +381,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
return new HashSet<String>(str2List(str, sep, true, false));
|
return new HashSet<String>(str2List(str, sep, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转list
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param sep 分隔符
|
||||||
|
* @return list集合
|
||||||
|
*/
|
||||||
|
public static final List<String> str2List(String str, String sep)
|
||||||
|
{
|
||||||
|
return str2List(str, sep, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字符串转list
|
* 字符串转list
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
|
|||||||
import com.ruoyi.common.exception.file.InvalidExtensionException;
|
import com.ruoyi.common.exception.file.InvalidExtensionException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||||
import com.ruoyi.common.utils.uuid.Seq;
|
import com.ruoyi.common.utils.uuid.Seq;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,7 +26,7 @@ public class FileUploadUtils
|
|||||||
/**
|
/**
|
||||||
* 默认大小 50M
|
* 默认大小 50M
|
||||||
*/
|
*/
|
||||||
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
|
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认的文件名最大长度 100
|
* 默认的文件名最大长度 100
|
||||||
@@ -102,15 +103,35 @@ public class FileUploadUtils
|
|||||||
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
|
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
|
||||||
InvalidExtensionException
|
InvalidExtensionException
|
||||||
{
|
{
|
||||||
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
|
return upload(baseDir, file, allowedExtension, false);
|
||||||
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
*
|
||||||
|
* @param baseDir 相对应用的基目录
|
||||||
|
* @param file 上传的文件
|
||||||
|
* @param useCustomNaming 系统自定义文件名
|
||||||
|
* @param allowedExtension 上传文件类型
|
||||||
|
* @return 返回上传成功的文件名
|
||||||
|
* @throws FileSizeLimitExceededException 如果超出最大大小
|
||||||
|
* @throws FileNameLengthLimitExceededException 文件名太长
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
* @throws InvalidExtensionException 文件校验异常
|
||||||
|
*/
|
||||||
|
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, boolean useCustomNaming)
|
||||||
|
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
|
||||||
|
InvalidExtensionException
|
||||||
|
{
|
||||||
|
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
|
||||||
|
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
|
||||||
{
|
{
|
||||||
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
|
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertAllowed(file, allowedExtension);
|
assertAllowed(file, allowedExtension);
|
||||||
|
|
||||||
String fileName = extractFilename(file);
|
String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file);
|
||||||
|
|
||||||
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
||||||
file.transferTo(Paths.get(absPath));
|
file.transferTo(Paths.get(absPath));
|
||||||
@@ -118,12 +139,19 @@ public class FileUploadUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编码文件名
|
* 编码文件名(日期格式目录 + 原文件名 + 序列值 + 后缀)
|
||||||
*/
|
*/
|
||||||
public static final String extractFilename(MultipartFile file)
|
public static final String extractFilename(MultipartFile file)
|
||||||
{
|
{
|
||||||
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
|
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
|
||||||
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编编码文件名(日期格式目录 + UUID + 后缀)
|
||||||
|
*/
|
||||||
|
public static final String uuidFilename(MultipartFile file)
|
||||||
|
{
|
||||||
|
return StringUtils.format("{}/{}.{}", DateUtils.datePath(), IdUtils.fastSimpleUUID(), getExtension(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
|
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ import java.net.URLEncoder;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件处理工具类
|
* 文件处理工具类
|
||||||
@@ -103,6 +104,17 @@ public class FileUtils
|
|||||||
return FileUploadUtils.getPathFileName(uploadDir, pathName);
|
return FileUploadUtils.getPathFileName(uploadDir, pathName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除路径中的请求前缀片段
|
||||||
|
*
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @return 移除后的文件路径
|
||||||
|
*/
|
||||||
|
public static String stripPrefix(String filePath)
|
||||||
|
{
|
||||||
|
return StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除文件
|
* 删除文件
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用http发送方法
|
* 通用http发送方法
|
||||||
@@ -74,7 +75,7 @@ public class HttpUtils
|
|||||||
URLConnection connection = realUrl.openConnection();
|
URLConnection connection = realUrl.openConnection();
|
||||||
connection.setRequestProperty("accept", "*/*");
|
connection.setRequestProperty("accept", "*/*");
|
||||||
connection.setRequestProperty("connection", "Keep-Alive");
|
connection.setRequestProperty("connection", "Keep-Alive");
|
||||||
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
connection.connect();
|
connection.connect();
|
||||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
||||||
String line;
|
String line;
|
||||||
@@ -125,6 +126,19 @@ public class HttpUtils
|
|||||||
* @return 所代表远程资源的响应结果
|
* @return 所代表远程资源的响应结果
|
||||||
*/
|
*/
|
||||||
public static String sendPost(String url, String param)
|
public static String sendPost(String url, String param)
|
||||||
|
{
|
||||||
|
return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 URL 发送POST方法的请求
|
||||||
|
*
|
||||||
|
* @param url 发送请求的 URL
|
||||||
|
* @param param 请求参数
|
||||||
|
* @param contentType 内容类型
|
||||||
|
* @return 所代表远程资源的响应结果
|
||||||
|
*/
|
||||||
|
public static String sendPost(String url, String param, String contentType)
|
||||||
{
|
{
|
||||||
PrintWriter out = null;
|
PrintWriter out = null;
|
||||||
BufferedReader in = null;
|
BufferedReader in = null;
|
||||||
@@ -136,9 +150,9 @@ public class HttpUtils
|
|||||||
URLConnection conn = realUrl.openConnection();
|
URLConnection conn = realUrl.openConnection();
|
||||||
conn.setRequestProperty("accept", "*/*");
|
conn.setRequestProperty("accept", "*/*");
|
||||||
conn.setRequestProperty("connection", "Keep-Alive");
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||||
conn.setRequestProperty("contentType", "utf-8");
|
conn.setRequestProperty("Content-Type", contentType);
|
||||||
conn.setDoOutput(true);
|
conn.setDoOutput(true);
|
||||||
conn.setDoInput(true);
|
conn.setDoInput(true);
|
||||||
out = new PrintWriter(conn.getOutputStream());
|
out = new PrintWriter(conn.getOutputStream());
|
||||||
@@ -190,6 +204,11 @@ public class HttpUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String sendSSLPost(String url, String param)
|
public static String sendSSLPost(String url, String param)
|
||||||
|
{
|
||||||
|
return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendSSLPost(String url, String param, String contentType)
|
||||||
{
|
{
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
String urlNameString = url + "?" + param;
|
String urlNameString = url + "?" + param;
|
||||||
@@ -202,9 +221,9 @@ public class HttpUtils
|
|||||||
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
|
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
|
||||||
conn.setRequestProperty("accept", "*/*");
|
conn.setRequestProperty("accept", "*/*");
|
||||||
conn.setRequestProperty("connection", "Keep-Alive");
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||||
conn.setRequestProperty("contentType", "utf-8");
|
conn.setRequestProperty("Content-Type", contentType);
|
||||||
conn.setDoOutput(true);
|
conn.setDoOutput(true);
|
||||||
conn.setDoInput(true);
|
conn.setDoInput(true);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
package com.ruoyi.common.utils.http;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import nl.basjes.parse.useragent.UserAgent;
|
||||||
|
import nl.basjes.parse.useragent.UserAgentAnalyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserAgent解析工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class UserAgentUtils
|
||||||
|
{
|
||||||
|
public static final String UNKNOWN = "";
|
||||||
|
|
||||||
|
// 浏览器正则表达式模式
|
||||||
|
private static final Pattern CHROME_PATTERN = Pattern.compile("Chrome/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern FIREFOX_PATTERN = Pattern.compile("Firefox/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern EDGE_PATTERN = Pattern.compile("Edg(?:e)?/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern SAFARI_PATTERN = Pattern.compile("Version/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern OPERA_PATTERN = Pattern.compile("Opera/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern IE_PATTERN = Pattern.compile("(?:MSIE |Trident/.*rv:)(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern SAMSUNG_PATTERN = Pattern.compile("SamsungBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern UC_PATTERN = Pattern.compile("UCBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern QQ_PATTERN = Pattern.compile("QQBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern WECHAT_PATTERN = Pattern.compile("MicroMessenger/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern BAIDU_PATTERN = Pattern.compile("baidubrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
|
||||||
|
// 操作系统正则表达式模式
|
||||||
|
private static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows NT (\\d+\\.\\d+)");
|
||||||
|
private static final Pattern MACOS_PATTERN = Pattern.compile("Mac OS X (\\d+[_\\d]*)");
|
||||||
|
private static final Pattern ANDROID_PATTERN = Pattern.compile("Android (\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern IOS_PATTERN = Pattern.compile("OS[\\s_](\\d+)(?:_\\d+)*");
|
||||||
|
private static final Pattern LINUX_PATTERN = Pattern.compile("Linux");
|
||||||
|
private static final Pattern CHROMEOS_PATTERN = Pattern.compile("CrOS");
|
||||||
|
|
||||||
|
private static final UserAgentAnalyzer userAgentAnalyzer = UserAgentAnalyzer
|
||||||
|
.newBuilder().hideMatcherLoadStats()
|
||||||
|
.withCache(5000)
|
||||||
|
.showMinimalVersion()
|
||||||
|
.withField(UserAgent.AGENT_NAME_VERSION)
|
||||||
|
.withField(UserAgent.OPERATING_SYSTEM_NAME_VERSION)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端浏览器
|
||||||
|
*/
|
||||||
|
public static String getBrowser(String userAgent)
|
||||||
|
{
|
||||||
|
UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
|
||||||
|
String agentNameVersion = iua.get(UserAgent.AGENT_NAME_VERSION).getValue();
|
||||||
|
if (StringUtils.isBlank(agentNameVersion) || agentNameVersion.contains("??"))
|
||||||
|
{
|
||||||
|
return formatBrowser(userAgent);
|
||||||
|
}
|
||||||
|
return agentNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端操作系统
|
||||||
|
*/
|
||||||
|
public static String getOperatingSystem(String userAgent)
|
||||||
|
{
|
||||||
|
UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
|
||||||
|
String operatingSystemNameVersion = iua.get(UserAgent.OPERATING_SYSTEM_NAME_VERSION).getValue();
|
||||||
|
if (StringUtils.isBlank(operatingSystemNameVersion) || operatingSystemNameVersion.contains("??"))
|
||||||
|
{
|
||||||
|
return formatOperatingSystem(userAgent);
|
||||||
|
}
|
||||||
|
return operatingSystemNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全面浏览器检测
|
||||||
|
*/
|
||||||
|
private static String formatBrowser(String browser)
|
||||||
|
{
|
||||||
|
// Chrome系列浏览器
|
||||||
|
Matcher chromeMatcher = CHROME_PATTERN.matcher(browser);
|
||||||
|
if (chromeMatcher.find() && (browser.contains("Chrome") || browser.contains("CriOS")))
|
||||||
|
{
|
||||||
|
return "Chrome" + chromeMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Firefox
|
||||||
|
Matcher firefoxMatcher = FIREFOX_PATTERN.matcher(browser);
|
||||||
|
if (firefoxMatcher.find())
|
||||||
|
{
|
||||||
|
return "Firefox" + firefoxMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Edge浏览器
|
||||||
|
Matcher edgeMatcher = EDGE_PATTERN.matcher(browser);
|
||||||
|
if (edgeMatcher.find())
|
||||||
|
{
|
||||||
|
return "Edge" + edgeMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Safari浏览器(需排除Chrome)
|
||||||
|
Matcher safariMatcher = SAFARI_PATTERN.matcher(browser);
|
||||||
|
if (safariMatcher.find() && !browser.contains("Chrome"))
|
||||||
|
{
|
||||||
|
return "Safari" + safariMatcher.group(1);
|
||||||
|
}
|
||||||
|
// 微信内置浏览器
|
||||||
|
Matcher wechatMatcher = WECHAT_PATTERN.matcher(browser);
|
||||||
|
if (wechatMatcher.find())
|
||||||
|
{
|
||||||
|
return "WeChat" + wechatMatcher.group(1);
|
||||||
|
}
|
||||||
|
// UC浏览器
|
||||||
|
Matcher ucMatcher = UC_PATTERN.matcher(browser);
|
||||||
|
if (ucMatcher.find())
|
||||||
|
{
|
||||||
|
return "UC Browser" + ucMatcher.group(1);
|
||||||
|
}
|
||||||
|
// QQ浏览器
|
||||||
|
Matcher qqMatcher = QQ_PATTERN.matcher(browser);
|
||||||
|
if (qqMatcher.find())
|
||||||
|
{
|
||||||
|
return "QQ Browser" + qqMatcher.group(1);
|
||||||
|
}
|
||||||
|
// 百度浏览器
|
||||||
|
Matcher baiduMatcher = BAIDU_PATTERN.matcher(browser);
|
||||||
|
if (baiduMatcher.find())
|
||||||
|
{
|
||||||
|
return "Baidu Browser" + baiduMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Samsung浏览器
|
||||||
|
Matcher samsungMatcher = SAMSUNG_PATTERN.matcher(browser);
|
||||||
|
if (samsungMatcher.find())
|
||||||
|
{
|
||||||
|
return "Samsung Browser" + samsungMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Opera浏览器
|
||||||
|
Matcher operaMatcher = OPERA_PATTERN.matcher(browser);
|
||||||
|
if (operaMatcher.find())
|
||||||
|
{
|
||||||
|
return "Opera" + operaMatcher.group(1);
|
||||||
|
}
|
||||||
|
// IE浏览器
|
||||||
|
Matcher ieMatcher = IE_PATTERN.matcher(browser);
|
||||||
|
if (ieMatcher.find())
|
||||||
|
{
|
||||||
|
return "Internet Explorer" + ieMatcher.group(1);
|
||||||
|
}
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测操作系统
|
||||||
|
*/
|
||||||
|
private static String formatOperatingSystem(String operatingSystem)
|
||||||
|
{
|
||||||
|
// Windows系统
|
||||||
|
Matcher windowsMatcher = WINDOWS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (windowsMatcher.find())
|
||||||
|
{
|
||||||
|
return "Windows" + getWindowsVersionDisplay(windowsMatcher.group(1));
|
||||||
|
}
|
||||||
|
// macOS系统
|
||||||
|
Matcher macMatcher = MACOS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (macMatcher.find())
|
||||||
|
{
|
||||||
|
String version = macMatcher.group(1).replace("_", ".");
|
||||||
|
return "macOS" + extractMajorVersion(version);
|
||||||
|
}
|
||||||
|
// Android系统
|
||||||
|
Matcher androidMatcher = ANDROID_PATTERN.matcher(operatingSystem);
|
||||||
|
if (androidMatcher.find())
|
||||||
|
{
|
||||||
|
return "Android" + extractMajorVersion(androidMatcher.group(1));
|
||||||
|
}
|
||||||
|
// iOS系统
|
||||||
|
Matcher iosMatcher = IOS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (iosMatcher.find() && (operatingSystem.contains("iPhone") || operatingSystem.contains("iPad")))
|
||||||
|
{
|
||||||
|
return "iOS" + extractMajorVersion(iosMatcher.group(1));
|
||||||
|
}
|
||||||
|
// Linux系统
|
||||||
|
if (LINUX_PATTERN.matcher(operatingSystem).find() && !operatingSystem.contains("Android"))
|
||||||
|
{
|
||||||
|
return "Linux";
|
||||||
|
}
|
||||||
|
// Chrome OS
|
||||||
|
if (CHROMEOS_PATTERN.matcher(operatingSystem).find())
|
||||||
|
{
|
||||||
|
return "Chrome OS";
|
||||||
|
}
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取优化的主版本号
|
||||||
|
*/
|
||||||
|
private static String extractMajorVersion(String fullVersion)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(fullVersion))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 清理版本号中的非数字字符
|
||||||
|
String cleanVersion = fullVersion.replaceAll("[^0-9.]", "");
|
||||||
|
String[] parts = cleanVersion.split("\\.");
|
||||||
|
if (parts.length > 0)
|
||||||
|
{
|
||||||
|
String firstPart = parts[0];
|
||||||
|
if (firstPart.matches("\\d+"))
|
||||||
|
{
|
||||||
|
int version = Integer.parseInt(firstPart);
|
||||||
|
|
||||||
|
// 处理三位数版本号(如142 -> 14)
|
||||||
|
if (version >= 100)
|
||||||
|
{
|
||||||
|
return String.valueOf(version / 10);
|
||||||
|
}
|
||||||
|
return firstPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
// 版本号解析失败,返回原始值
|
||||||
|
}
|
||||||
|
return fullVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows版本号显示优化
|
||||||
|
*/
|
||||||
|
private static String getWindowsVersionDisplay(String version)
|
||||||
|
{
|
||||||
|
switch (version)
|
||||||
|
{
|
||||||
|
case "10.0":
|
||||||
|
return "10";
|
||||||
|
case "6.3":
|
||||||
|
return "8.1";
|
||||||
|
case "6.2":
|
||||||
|
return "8";
|
||||||
|
case "6.1":
|
||||||
|
return "7";
|
||||||
|
case "6.0":
|
||||||
|
return "Vista";
|
||||||
|
case "5.1":
|
||||||
|
return "XP";
|
||||||
|
case "5.0":
|
||||||
|
return "2000";
|
||||||
|
default:
|
||||||
|
return extractMajorVersion(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ public class AddressUtils
|
|||||||
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
|
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
|
||||||
|
|
||||||
// IP地址查询
|
// IP地址查询
|
||||||
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
public static final String IP_URL = "https://whois.pconline.com.cn/ipJson.jsp";
|
||||||
|
|
||||||
// 未知地址
|
// 未知地址
|
||||||
public static final String UNKNOWN = "XX XX";
|
public static final String UNKNOWN = "XX XX";
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.ruoyi.common.utils.poi;
|
package com.ruoyi.common.utils.poi;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel数据格式处理适配器
|
* Excel数据格式处理适配器
|
||||||
*
|
*
|
||||||
@@ -12,8 +15,10 @@ public interface ExcelHandlerAdapter
|
|||||||
*
|
*
|
||||||
* @param value 单元格数据值
|
* @param value 单元格数据值
|
||||||
* @param args excel注解args参数组
|
* @param args excel注解args参数组
|
||||||
|
* @param cell 单元格对象
|
||||||
|
* @param wb 工作簿对象
|
||||||
*
|
*
|
||||||
* @return 处理后的值
|
* @return 处理后的值
|
||||||
*/
|
*/
|
||||||
Object format(Object value, String[] args);
|
Object format(Object value, String[] args, Cell cell, Workbook wb);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.ruoyi.common.utils.poi;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多 Sheet 导出时的数据信息
|
||||||
|
*
|
||||||
|
* 使用示例:
|
||||||
|
* <pre>
|
||||||
|
* List<ExcelSheet<?>> sheets = new ArrayList<>();
|
||||||
|
* sheets.add(new ExcelSheet<>("参数数据", configList, Config.class, "参数信息"));
|
||||||
|
* sheets.add(new ExcelSheet<>("岗位数据", postList, Post.class, "岗位信息"));
|
||||||
|
* return ExcelUtil.exportMultiSheet(sheets);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class ExcelSheet<T>
|
||||||
|
{
|
||||||
|
/** Sheet 名称 */
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
/** 导出数据集合 */
|
||||||
|
private List<T> list;
|
||||||
|
|
||||||
|
/** 数据对应的实体 Class */
|
||||||
|
private Class<T> clazz;
|
||||||
|
|
||||||
|
/** Sheet 顶部大标题(可为空) */
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public ExcelSheet(String sheetName, List<T> list, Class<T> clazz)
|
||||||
|
{
|
||||||
|
this(sheetName, list, clazz, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExcelSheet(String sheetName, List<T> list, Class<T> clazz, String title)
|
||||||
|
{
|
||||||
|
this.sheetName = sheetName;
|
||||||
|
this.list = list != null ? list : new ArrayList<>();
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.title = title != null ? title : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetName()
|
||||||
|
{
|
||||||
|
return sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getList()
|
||||||
|
{
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<T> getClazz()
|
||||||
|
{
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSheetName(String sheetName)
|
||||||
|
{
|
||||||
|
this.sheetName = sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<T> list)
|
||||||
|
{
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClazz(Class<T> clazz)
|
||||||
|
{
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title)
|
||||||
|
{
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.common.utils.spring;
|
package com.ruoyi.common.utils.spring;
|
||||||
|
|
||||||
|
import org.springframework.aop.framework.Advised;
|
||||||
import org.springframework.aop.framework.AopContext;
|
import org.springframework.aop.framework.AopContext;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
@@ -120,7 +121,12 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T getAopProxy(T invoker)
|
public static <T> T getAopProxy(T invoker)
|
||||||
{
|
{
|
||||||
return (T) AopContext.currentProxy();
|
Object proxy = AopContext.currentProxy();
|
||||||
|
if (((Advised) proxy).getTargetSource().getTargetClass() == invoker.getClass())
|
||||||
|
{
|
||||||
|
return (T) proxy;
|
||||||
|
}
|
||||||
|
return invoker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,13 +13,18 @@ public class SqlUtil
|
|||||||
/**
|
/**
|
||||||
* 定义常用的 sql关键字
|
* 定义常用的 sql关键字
|
||||||
*/
|
*/
|
||||||
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
|
public static String SQL_REGEX = "\u000B|%0A|and |extractvalue|updatexml|sleep|information_schema|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||||
*/
|
*/
|
||||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制orderBy最大长度
|
||||||
|
*/
|
||||||
|
private static final int ORDER_BY_MAX_LENGTH = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查字符,防止注入绕过
|
* 检查字符,防止注入绕过
|
||||||
*/
|
*/
|
||||||
@@ -29,6 +34,10 @@ public class SqlUtil
|
|||||||
{
|
{
|
||||||
throw new UtilException("参数不符合规范,不能进行查询");
|
throw new UtilException("参数不符合规范,不能进行查询");
|
||||||
}
|
}
|
||||||
|
if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
throw new UtilException("参数已超过最大限制,不能进行查询");
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +58,13 @@ public class SqlUtil
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String normalizedValue = value.replaceAll("\\p{Z}|\\s", "");
|
||||||
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
|
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
|
||||||
for (String sqlKeyword : sqlKeywords)
|
for (String sqlKeyword : sqlKeywords)
|
||||||
{
|
{
|
||||||
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
|
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
|
||||||
{
|
{
|
||||||
throw new UtilException("参数存在SQL注入风险");
|
throw new UtilException("请求参数包含敏感关键词'" + sqlKeyword + "',可能存在安全风险");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
|
|||||||
|
|
||||||
public static boolean containsHtml(String value)
|
public static boolean containsHtml(String value)
|
||||||
{
|
{
|
||||||
|
StringBuilder sHtml = new StringBuilder();
|
||||||
Pattern pattern = Pattern.compile(HTML_PATTERN);
|
Pattern pattern = Pattern.compile(HTML_PATTERN);
|
||||||
Matcher matcher = pattern.matcher(value);
|
Matcher matcher = pattern.matcher(value);
|
||||||
return matcher.matches();
|
while (matcher.find())
|
||||||
|
{
|
||||||
|
sHtml.append(matcher.group());
|
||||||
|
}
|
||||||
|
return pattern.matcher(sHtml).matches();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import org.aspectj.lang.annotation.Aspect;
|
|||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.annotation.DataScope;
|
import com.ruoyi.common.annotation.DataScope;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
@@ -25,31 +27,6 @@ import com.ruoyi.framework.security.context.PermissionContextHolder;
|
|||||||
@Component
|
@Component
|
||||||
public class DataScopeAspect
|
public class DataScopeAspect
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* 全部数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_ALL = "1";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_CUSTOM = "2";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_DEPT = "3";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门及以下数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仅本人数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_SELF = "5";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据权限过滤关键字
|
* 数据权限过滤关键字
|
||||||
*/
|
*/
|
||||||
@@ -73,8 +50,7 @@ public class DataScopeAspect
|
|||||||
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
|
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
|
||||||
{
|
{
|
||||||
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
|
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
|
||||||
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
|
dataScopeFilter(joinPoint, currentUser, controllerDataScope.userAlias(), controllerDataScope.deptAlias(), controllerDataScope.userField(), controllerDataScope.deptField(), permission);
|
||||||
controllerDataScope.userAlias(), permission);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,64 +64,74 @@ public class DataScopeAspect
|
|||||||
* @param userAlias 用户别名
|
* @param userAlias 用户别名
|
||||||
* @param permission 权限字符
|
* @param permission 权限字符
|
||||||
*/
|
*/
|
||||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
|
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String userAlias, String deptAlias, String userField, String deptField, String permission)
|
||||||
{
|
{
|
||||||
StringBuilder sqlString = new StringBuilder();
|
StringBuilder sqlString = new StringBuilder();
|
||||||
List<String> conditions = new ArrayList<String>();
|
List<String> conditions = new ArrayList<String>();
|
||||||
|
List<String> scopeCustomIds = new ArrayList<String>();
|
||||||
|
user.getRoles().forEach(role -> {
|
||||||
|
if (Constants.Dept.DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))))
|
||||||
|
{
|
||||||
|
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (SysRole role : user.getRoles())
|
for (SysRole role : user.getRoles())
|
||||||
{
|
{
|
||||||
String dataScope = role.getDataScope();
|
String dataScope = role.getDataScope();
|
||||||
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
|
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
|
if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||||
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (DATA_SCOPE_ALL.equals(dataScope))
|
if (Constants.Dept.DATA_SCOPE_ALL.equals(dataScope))
|
||||||
{
|
{
|
||||||
sqlString = new StringBuilder();
|
sqlString = new StringBuilder();
|
||||||
conditions.add(dataScope);
|
conditions.add(dataScope);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
else if (Constants.Dept.DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||||
{
|
{
|
||||||
sqlString.append(StringUtils.format(
|
if (scopeCustomIds.size() > 1)
|
||||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
|
||||||
role.getRoleId()));
|
|
||||||
}
|
|
||||||
else if (DATA_SCOPE_DEPT.equals(dataScope))
|
|
||||||
{
|
{
|
||||||
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
|
// 多个自定数据权限使用in查询,避免多次拼接。
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.{} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, deptField, String.join(",", scopeCustomIds)));
|
||||||
}
|
}
|
||||||
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
else
|
||||||
{
|
{
|
||||||
sqlString.append(StringUtils.format(
|
sqlString.append(StringUtils.format(" OR {}.{} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, deptField, role.getRoleId()));
|
||||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
|
||||||
deptAlias, user.getDeptId(), user.getDeptId()));
|
|
||||||
}
|
}
|
||||||
else if (DATA_SCOPE_SELF.equals(dataScope))
|
}
|
||||||
|
else if (Constants.Dept.DATA_SCOPE_DEPT.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.{} = {} ", deptAlias, deptField, user.getDeptId()));
|
||||||
|
}
|
||||||
|
else if (Constants.Dept.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.{} IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, deptField, user.getDeptId(), user.getDeptId()));
|
||||||
|
}
|
||||||
|
else if (Constants.Dept.DATA_SCOPE_SELF.equals(dataScope))
|
||||||
{
|
{
|
||||||
if (StringUtils.isNotBlank(userAlias))
|
if (StringUtils.isNotBlank(userAlias))
|
||||||
{
|
{
|
||||||
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
|
sqlString.append(StringUtils.format(" OR {}.{} = {} ", userAlias, userField, user.getUserId()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
||||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
sqlString.append(StringUtils.format(" OR {}.{} = 0 ", deptAlias, deptField));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conditions.add(dataScope);
|
conditions.add(dataScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多角色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
// 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
||||||
if (StringUtils.isEmpty(conditions))
|
if (StringUtils.isEmpty(conditions))
|
||||||
{
|
{
|
||||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
sqlString.append(StringUtils.format(" OR {}.{} = 0 ", deptAlias, deptField));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(sqlString.toString()))
|
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ import org.springframework.validation.BindingResult;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.enums.BusinessStatus;
|
import com.ruoyi.common.enums.BusinessStatus;
|
||||||
import com.ruoyi.common.enums.HttpMethod;
|
import com.ruoyi.common.enums.HttpMethod;
|
||||||
import com.ruoyi.common.filter.PropertyPreExcludeFilter;
|
import com.ruoyi.common.filter.PropertyPreExcludeFilter;
|
||||||
|
import com.ruoyi.common.utils.ExceptionUtil;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@@ -47,11 +50,14 @@ public class LogAspect
|
|||||||
/** 计算操作消耗时间 */
|
/** 计算操作消耗时间 */
|
||||||
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
||||||
|
|
||||||
|
/** 参数最大长度限制 */
|
||||||
|
private static final int PARAM_MAX_LENGTH = 2000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理请求前执行
|
* 处理请求前执行
|
||||||
*/
|
*/
|
||||||
@Before(value = "@annotation(controllerLog)")
|
@Before(value = "@annotation(controllerLog)")
|
||||||
public void boBefore(JoinPoint joinPoint, Log controllerLog)
|
public void doBefore(JoinPoint joinPoint, Log controllerLog)
|
||||||
{
|
{
|
||||||
TIME_THREADLOCAL.set(System.currentTimeMillis());
|
TIME_THREADLOCAL.set(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
@@ -96,12 +102,17 @@ public class LogAspect
|
|||||||
if (loginUser != null)
|
if (loginUser != null)
|
||||||
{
|
{
|
||||||
operLog.setOperName(loginUser.getUsername());
|
operLog.setOperName(loginUser.getUsername());
|
||||||
|
SysUser currentUser = loginUser.getUser();
|
||||||
|
if (StringUtils.isNotNull(currentUser) && StringUtils.isNotNull(currentUser.getDept()))
|
||||||
|
{
|
||||||
|
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e != null)
|
if (e != null)
|
||||||
{
|
{
|
||||||
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000));
|
||||||
}
|
}
|
||||||
// 设置方法名称
|
// 设置方法名称
|
||||||
String className = joinPoint.getTarget().getClass().getName();
|
String className = joinPoint.getTarget().getClass().getName();
|
||||||
@@ -164,17 +175,16 @@ public class LogAspect
|
|||||||
*/
|
*/
|
||||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
||||||
{
|
{
|
||||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
|
||||||
String requestMethod = operLog.getRequestMethod();
|
String requestMethod = operLog.getRequestMethod();
|
||||||
if (StringUtils.isEmpty(paramsMap)
|
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||||
&& (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
|
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
|
||||||
{
|
{
|
||||||
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
||||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
operLog.setOperParam(params);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
|
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +193,7 @@ public class LogAspect
|
|||||||
*/
|
*/
|
||||||
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
||||||
{
|
{
|
||||||
String params = "";
|
StringBuilder params = new StringBuilder();
|
||||||
if (paramsArray != null && paramsArray.length > 0)
|
if (paramsArray != null && paramsArray.length > 0)
|
||||||
{
|
{
|
||||||
for (Object o : paramsArray)
|
for (Object o : paramsArray)
|
||||||
@@ -193,15 +203,20 @@ public class LogAspect
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
||||||
params += jsonObj.toString() + " ";
|
params.append(jsonObj).append(" ");
|
||||||
|
if (params.length() >= PARAM_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return params.trim();
|
return params.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+5
-1
@@ -6,6 +6,8 @@ import org.springframework.data.redis.serializer.SerializationException;
|
|||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONReader;
|
import com.alibaba.fastjson2.JSONReader;
|
||||||
import com.alibaba.fastjson2.JSONWriter;
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
|
import com.alibaba.fastjson2.filter.Filter;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis使用FastJson序列化
|
* Redis使用FastJson序列化
|
||||||
@@ -16,6 +18,8 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
|||||||
{
|
{
|
||||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
|
||||||
|
|
||||||
private Class<T> clazz;
|
private Class<T> clazz;
|
||||||
|
|
||||||
public FastJson2JsonRedisSerializer(Class<T> clazz)
|
public FastJson2JsonRedisSerializer(Class<T> clazz)
|
||||||
@@ -43,6 +47,6 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
|||||||
}
|
}
|
||||||
String str = new String(bytes, DEFAULT_CHARSET);
|
String str = new String(bytes, DEFAULT_CHARSET);
|
||||||
|
|
||||||
return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
|
return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.filter.RefererFilter;
|
||||||
import com.ruoyi.common.filter.RepeatableFilter;
|
import com.ruoyi.common.filter.RepeatableFilter;
|
||||||
import com.ruoyi.common.filter.XssFilter;
|
import com.ruoyi.common.filter.XssFilter;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@@ -26,6 +28,9 @@ public class FilterConfig
|
|||||||
@Value("${xss.urlPatterns}")
|
@Value("${xss.urlPatterns}")
|
||||||
private String urlPatterns;
|
private String urlPatterns;
|
||||||
|
|
||||||
|
@Value("${referer.allowed-domains}")
|
||||||
|
private String allowedDomains;
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
||||||
@@ -43,6 +48,23 @@ public class FilterConfig
|
|||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
|
||||||
|
public FilterRegistrationBean refererFilterRegistration()
|
||||||
|
{
|
||||||
|
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||||
|
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||||
|
registration.setFilter(new RefererFilter());
|
||||||
|
registration.addUrlPatterns(Constants.RESOURCE_PREFIX + "/*");
|
||||||
|
registration.setName("refererFilter");
|
||||||
|
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
|
||||||
|
Map<String, String> initParameters = new HashMap<String, String>();
|
||||||
|
initParameters.put("allowedDomains", allowedDomains);
|
||||||
|
registration.setInitParameters(initParameters);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Bean
|
@Bean
|
||||||
public FilterRegistrationBean someFilterRegistration()
|
public FilterRegistrationBean someFilterRegistration()
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||||
|
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源文件配置加载
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class I18nConfig implements WebMvcConfigurer
|
||||||
|
{
|
||||||
|
@Bean
|
||||||
|
public LocaleResolver localeResolver()
|
||||||
|
{
|
||||||
|
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||||
|
// 默认语言
|
||||||
|
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
|
||||||
|
return slr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||||
|
{
|
||||||
|
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||||
|
// 参数名
|
||||||
|
lci.setParamName("lang");
|
||||||
|
return lci;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry)
|
||||||
|
{
|
||||||
|
registry.addInterceptor(localeChangeInterceptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
|||||||
/** swagger配置 */
|
/** swagger配置 */
|
||||||
registry.addResourceHandler("/swagger-ui/**")
|
registry.addResourceHandler("/swagger-ui/**")
|
||||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
|
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +55,6 @@ public class ResourcesConfig implements WebMvcConfigurer
|
|||||||
public CorsFilter corsFilter()
|
public CorsFilter corsFilter()
|
||||||
{
|
{
|
||||||
CorsConfiguration config = new CorsConfiguration();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
config.setAllowCredentials(true);
|
|
||||||
// 设置访问源地址
|
// 设置访问源地址
|
||||||
config.addAllowedOriginPattern("*");
|
config.addAllowedOriginPattern("*");
|
||||||
// 设置访问源请求头
|
// 设置访问源请求头
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package com.ruoyi.framework.config;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
@@ -25,8 +26,9 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
|||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter
|
@Configuration
|
||||||
|
public class SecurityConfig
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 自定义用户认证逻辑
|
* 自定义用户认证逻辑
|
||||||
@@ -65,16 +67,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
private PermitAllUrlProperties permitAllUrl;
|
private PermitAllUrlProperties permitAllUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解决 无法直接注入 AuthenticationManager
|
* 身份验证实现
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
public AuthenticationManager authenticationManager()
|
||||||
public AuthenticationManager authenticationManagerBean() throws Exception
|
|
||||||
{
|
{
|
||||||
return super.authenticationManagerBean();
|
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
|
||||||
|
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
|
||||||
|
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
|
||||||
|
return new ProviderManager(daoAuthenticationProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,40 +93,39 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
* rememberMe | 允许通过remember-me登录的用户访问
|
* rememberMe | 允许通过remember-me登录的用户访问
|
||||||
* authenticated | 用户登录后可访问
|
* authenticated | 用户登录后可访问
|
||||||
*/
|
*/
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(HttpSecurity httpSecurity) throws Exception
|
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
|
||||||
{
|
{
|
||||||
// 注解标记允许匿名访问的url
|
return httpSecurity
|
||||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
|
|
||||||
permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
|
|
||||||
|
|
||||||
httpSecurity
|
|
||||||
// CSRF禁用,因为不使用session
|
// CSRF禁用,因为不使用session
|
||||||
.csrf().disable()
|
.csrf(csrf -> csrf.disable())
|
||||||
// 禁用HTTP响应标头
|
// 禁用HTTP响应标头
|
||||||
.headers().cacheControl().disable().and()
|
.headers((headersCustomizer) -> {
|
||||||
|
headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
|
||||||
|
})
|
||||||
// 认证失败处理类
|
// 认证失败处理类
|
||||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
|
||||||
// 基于token,所以不需要session
|
// 基于token,所以不需要session
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
// 过滤请求
|
// 注解标记允许匿名访问的url
|
||||||
.authorizeRequests()
|
.authorizeHttpRequests((requests) -> {
|
||||||
|
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
|
||||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
||||||
.antMatchers("/login", "/register", "/captchaImage").permitAll()
|
requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
|
||||||
// 静态资源,可匿名访问
|
// 静态资源,可匿名访问
|
||||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
// 除上面外的所有请求全部需要鉴权认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated();
|
||||||
.and()
|
})
|
||||||
.headers().frameOptions().disable();
|
|
||||||
// 添加Logout filter
|
// 添加Logout filter
|
||||||
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
.logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
|
||||||
// 添加JWT filter
|
// 添加JWT filter
|
||||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
// 添加CORS filter
|
// 添加CORS filter
|
||||||
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
|
.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
|
||||||
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
|
.addFilterBefore(corsFilter, LogoutFilter.class)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,13 +136,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
{
|
{
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 身份认证接口
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception
|
|
||||||
{
|
|
||||||
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -47,8 +47,9 @@ public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
|
|||||||
/**
|
/**
|
||||||
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
||||||
*
|
*
|
||||||
* @param request
|
* @param request 请求信息
|
||||||
* @return
|
* @param annotation 防重复注解参数
|
||||||
|
* @return 结果
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
|
public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.ruoyi.common.constant.Constants;
|
|||||||
import com.ruoyi.common.utils.LogUtils;
|
import com.ruoyi.common.utils.LogUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.http.UserAgentUtils;
|
||||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
import com.ruoyi.common.utils.ip.IpUtils;
|
import com.ruoyi.common.utils.ip.IpUtils;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
@@ -14,7 +15,6 @@ import com.ruoyi.system.domain.SysLogininfor;
|
|||||||
import com.ruoyi.system.domain.SysOperLog;
|
import com.ruoyi.system.domain.SysOperLog;
|
||||||
import com.ruoyi.system.service.ISysLogininforService;
|
import com.ruoyi.system.service.ISysLogininforService;
|
||||||
import com.ruoyi.system.service.ISysOperLogService;
|
import com.ruoyi.system.service.ISysOperLogService;
|
||||||
import eu.bitwalker.useragentutils.UserAgent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步工厂(产生任务用)
|
* 异步工厂(产生任务用)
|
||||||
@@ -37,7 +37,7 @@ public class AsyncFactory
|
|||||||
public static TimerTask recordLogininfor(final String username, final String status, final String message,
|
public static TimerTask recordLogininfor(final String username, final String status, final String message,
|
||||||
final Object... args)
|
final Object... args)
|
||||||
{
|
{
|
||||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
final String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||||
final String ip = IpUtils.getIpAddr();
|
final String ip = IpUtils.getIpAddr();
|
||||||
return new TimerTask()
|
return new TimerTask()
|
||||||
{
|
{
|
||||||
@@ -54,9 +54,9 @@ public class AsyncFactory
|
|||||||
// 打印信息到日志
|
// 打印信息到日志
|
||||||
sys_user_logger.info(s.toString(), args);
|
sys_user_logger.info(s.toString(), args);
|
||||||
// 获取客户端操作系统
|
// 获取客户端操作系统
|
||||||
String os = userAgent.getOperatingSystem().getName();
|
String os = UserAgentUtils.getOperatingSystem(userAgent);
|
||||||
// 获取客户端浏览器
|
// 获取客户端浏览器
|
||||||
String browser = userAgent.getBrowser().getName();
|
String browser = UserAgentUtils.getBrowser(userAgent);
|
||||||
// 封装对象
|
// 封装对象
|
||||||
SysLogininfor logininfor = new SysLogininfor();
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
logininfor.setUserName(username);
|
logininfor.setUserName(username);
|
||||||
|
|||||||
+3
-2
@@ -12,6 +12,7 @@ import com.alibaba.fastjson2.JSON;
|
|||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.manager.AsyncManager;
|
import com.ruoyi.framework.manager.AsyncManager;
|
||||||
@@ -45,8 +46,8 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
|
|||||||
// 删除用户缓存记录
|
// 删除用户缓存记录
|
||||||
tokenService.delLoginUser(loginUser.getToken());
|
tokenService.delLoginUser(loginUser.getToken());
|
||||||
// 记录用户退出日志
|
// 记录用户退出日志
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
|
||||||
}
|
}
|
||||||
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功")));
|
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
@@ -7,13 +7,17 @@ import org.springframework.security.access.AccessDeniedException;
|
|||||||
import org.springframework.validation.BindException;
|
import org.springframework.validation.BindException;
|
||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.MissingPathVariableException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||||
import com.ruoyi.common.constant.HttpStatus;
|
import com.ruoyi.common.constant.HttpStatus;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.exception.DemoModeException;
|
import com.ruoyi.common.exception.DemoModeException;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.html.EscapeUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局异常处理器
|
* 全局异常处理器
|
||||||
@@ -59,6 +63,33 @@ public class GlobalExceptionHandler
|
|||||||
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
|
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求路径中缺少必需的路径变量
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MissingPathVariableException.class)
|
||||||
|
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
|
||||||
|
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数类型不匹配
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||||
|
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
String value = Convert.toStr(e.getValue());
|
||||||
|
if (StringUtils.isNotEmpty(value))
|
||||||
|
{
|
||||||
|
value = EscapeUtil.clean(value);
|
||||||
|
}
|
||||||
|
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
|
||||||
|
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拦截未知的运行时异常
|
* 拦截未知的运行时异常
|
||||||
*/
|
*/
|
||||||
|
|||||||
+7
-16
@@ -3,6 +3,7 @@ package com.ruoyi.framework.web.service;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
@@ -17,16 +18,6 @@ import com.ruoyi.framework.security.context.PermissionContextHolder;
|
|||||||
@Service("ss")
|
@Service("ss")
|
||||||
public class PermissionService
|
public class PermissionService
|
||||||
{
|
{
|
||||||
/** 所有权限标识 */
|
|
||||||
private static final String ALL_PERMISSION = "*:*:*";
|
|
||||||
|
|
||||||
/** 管理员角色权限标识 */
|
|
||||||
private static final String SUPER_ADMIN = "admin";
|
|
||||||
|
|
||||||
private static final String ROLE_DELIMETER = ",";
|
|
||||||
|
|
||||||
private static final String PERMISSION_DELIMETER = ",";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证用户是否具备某权限
|
* 验证用户是否具备某权限
|
||||||
*
|
*
|
||||||
@@ -62,7 +53,7 @@ public class PermissionService
|
|||||||
/**
|
/**
|
||||||
* 验证用户是否具有以下任意一个权限
|
* 验证用户是否具有以下任意一个权限
|
||||||
*
|
*
|
||||||
* @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
|
* @param permissions 以 PERMISSION_DELIMITER 为分隔符的权限列表
|
||||||
* @return 用户是否具有以下任意一个权限
|
* @return 用户是否具有以下任意一个权限
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyPermi(String permissions)
|
public boolean hasAnyPermi(String permissions)
|
||||||
@@ -78,7 +69,7 @@ public class PermissionService
|
|||||||
}
|
}
|
||||||
PermissionContextHolder.setContext(permissions);
|
PermissionContextHolder.setContext(permissions);
|
||||||
Set<String> authorities = loginUser.getPermissions();
|
Set<String> authorities = loginUser.getPermissions();
|
||||||
for (String permission : permissions.split(PERMISSION_DELIMETER))
|
for (String permission : permissions.split(Constants.PERMISSION_DELIMITER))
|
||||||
{
|
{
|
||||||
if (permission != null && hasPermissions(authorities, permission))
|
if (permission != null && hasPermissions(authorities, permission))
|
||||||
{
|
{
|
||||||
@@ -108,7 +99,7 @@ public class PermissionService
|
|||||||
for (SysRole sysRole : loginUser.getUser().getRoles())
|
for (SysRole sysRole : loginUser.getUser().getRoles())
|
||||||
{
|
{
|
||||||
String roleKey = sysRole.getRoleKey();
|
String roleKey = sysRole.getRoleKey();
|
||||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
if (Constants.SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -130,7 +121,7 @@ public class PermissionService
|
|||||||
/**
|
/**
|
||||||
* 验证用户是否具有以下任意一个角色
|
* 验证用户是否具有以下任意一个角色
|
||||||
*
|
*
|
||||||
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
* @param roles 以 ROLE_DELIMITER 为分隔符的角色列表
|
||||||
* @return 用户是否具有以下任意一个角色
|
* @return 用户是否具有以下任意一个角色
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyRoles(String roles)
|
public boolean hasAnyRoles(String roles)
|
||||||
@@ -144,7 +135,7 @@ public class PermissionService
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (String role : roles.split(ROLE_DELIMETER))
|
for (String role : roles.split(Constants.ROLE_DELIMITER))
|
||||||
{
|
{
|
||||||
if (hasRole(role))
|
if (hasRole(role))
|
||||||
{
|
{
|
||||||
@@ -163,6 +154,6 @@ public class PermissionService
|
|||||||
*/
|
*/
|
||||||
private boolean hasPermissions(Set<String> permissions, String permission)
|
private boolean hasPermissions(Set<String> permissions, String permission)
|
||||||
{
|
{
|
||||||
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
|
return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import org.springframework.stereotype.Component;
|
|||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
@@ -115,12 +114,12 @@ public class SysLoginService
|
|||||||
{
|
{
|
||||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
||||||
String captcha = redisCache.getCacheObject(verifyKey);
|
String captcha = redisCache.getCacheObject(verifyKey);
|
||||||
redisCache.deleteObject(verifyKey);
|
|
||||||
if (captcha == null)
|
if (captcha == null)
|
||||||
{
|
{
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
|
redisCache.deleteObject(verifyKey);
|
||||||
if (!code.equalsIgnoreCase(captcha))
|
if (!code.equalsIgnoreCase(captcha))
|
||||||
{
|
{
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||||
@@ -172,10 +171,6 @@ public class SysLoginService
|
|||||||
*/
|
*/
|
||||||
public void recordLoginInfo(Long userId)
|
public void recordLoginInfo(Long userId)
|
||||||
{
|
{
|
||||||
SysUser sysUser = new SysUser();
|
userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate());
|
||||||
sysUser.setUserId(userId);
|
|
||||||
sysUser.setLoginIp(IpUtils.getIpAddr());
|
|
||||||
sysUser.setLoginDate(DateUtils.getNowDate());
|
|
||||||
userService.updateUserProfile(sysUser);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,11 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||||
import com.ruoyi.common.utils.MessageUtils;
|
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.framework.manager.AsyncManager;
|
|
||||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
|
||||||
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
|
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,16 +56,12 @@ public class SysPasswordService
|
|||||||
|
|
||||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
||||||
{
|
{
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
|
||||||
MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
|
|
||||||
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
|
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matches(user, password))
|
if (!matches(user, password))
|
||||||
{
|
{
|
||||||
retryCount = retryCount + 1;
|
retryCount = retryCount + 1;
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
|
||||||
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
|
||||||
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
||||||
throw new UserPasswordNotMatchException();
|
throw new UserPasswordNotMatchException();
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -6,8 +6,11 @@ import java.util.Set;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
|
|
||||||
@@ -37,7 +40,7 @@ public class SysPermissionService
|
|||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin())
|
||||||
{
|
{
|
||||||
roles.add("admin");
|
roles.add(Constants.SUPER_ADMIN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -58,7 +61,7 @@ public class SysPermissionService
|
|||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin())
|
||||||
{
|
{
|
||||||
perms.add("*:*:*");
|
perms.add(Constants.ALL_PERMISSION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -67,12 +70,15 @@ public class SysPermissionService
|
|||||||
{
|
{
|
||||||
// 多角色设置permissions属性,以便数据权限匹配权限
|
// 多角色设置permissions属性,以便数据权限匹配权限
|
||||||
for (SysRole role : roles)
|
for (SysRole role : roles)
|
||||||
|
{
|
||||||
|
if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin())
|
||||||
{
|
{
|
||||||
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
|
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
|
||||||
role.setPermissions(rolePerms);
|
role.setPermissions(rolePerms);
|
||||||
perms.addAll(rolePerms);
|
perms.addAll(rolePerms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
|
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.ruoyi.common.core.domain.model.RegisterBody;
|
|||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.MessageUtils;
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@@ -76,6 +77,7 @@ public class SysRegisterService
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sysUser.setNickName(username);
|
sysUser.setNickName(username);
|
||||||
|
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
|
||||||
sysUser.setPassword(SecurityUtils.encryptPassword(password));
|
sysUser.setPassword(SecurityUtils.encryptPassword(password));
|
||||||
boolean regFlag = userService.registerUser(sysUser);
|
boolean regFlag = userService.registerUser(sysUser);
|
||||||
if (!regFlag)
|
if (!regFlag)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.framework.web.service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -13,13 +15,14 @@ import com.ruoyi.common.core.domain.model.LoginUser;
|
|||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.http.UserAgentUtils;
|
||||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
import com.ruoyi.common.utils.ip.IpUtils;
|
import com.ruoyi.common.utils.ip.IpUtils;
|
||||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||||
import eu.bitwalker.useragentutils.UserAgent;
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token验证处理
|
* token验证处理
|
||||||
@@ -29,6 +32,8 @@ import io.jsonwebtoken.SignatureAlgorithm;
|
|||||||
@Component
|
@Component
|
||||||
public class TokenService
|
public class TokenService
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TokenService.class);
|
||||||
|
|
||||||
// 令牌自定义标识
|
// 令牌自定义标识
|
||||||
@Value("${token.header}")
|
@Value("${token.header}")
|
||||||
private String header;
|
private String header;
|
||||||
@@ -45,7 +50,7 @@ public class TokenService
|
|||||||
|
|
||||||
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
|
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
|
||||||
|
|
||||||
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
|
private static final Long MILLIS_MINUTE_TWENTY = 20 * 60 * 1000L;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
@@ -72,6 +77,7 @@ public class TokenService
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
log.error("获取用户信息异常'{}'", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -115,20 +121,21 @@ public class TokenService
|
|||||||
|
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(Constants.LOGIN_USER_KEY, token);
|
claims.put(Constants.LOGIN_USER_KEY, token);
|
||||||
|
claims.put(Constants.JWT_USERNAME, loginUser.getUsername());
|
||||||
return createToken(claims);
|
return createToken(claims);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
|
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
|
||||||
*
|
*
|
||||||
* @param loginUser
|
* @param loginUser 登录信息
|
||||||
* @return 令牌
|
* @return 令牌
|
||||||
*/
|
*/
|
||||||
public void verifyToken(LoginUser loginUser)
|
public void verifyToken(LoginUser loginUser)
|
||||||
{
|
{
|
||||||
long expireTime = loginUser.getExpireTime();
|
long expireTime = loginUser.getExpireTime();
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
|
if (expireTime - currentTime <= MILLIS_MINUTE_TWENTY)
|
||||||
{
|
{
|
||||||
refreshToken(loginUser);
|
refreshToken(loginUser);
|
||||||
}
|
}
|
||||||
@@ -155,12 +162,12 @@ public class TokenService
|
|||||||
*/
|
*/
|
||||||
public void setUserAgent(LoginUser loginUser)
|
public void setUserAgent(LoginUser loginUser)
|
||||||
{
|
{
|
||||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||||
String ip = IpUtils.getIpAddr();
|
String ip = IpUtils.getIpAddr();
|
||||||
loginUser.setIpaddr(ip);
|
loginUser.setIpaddr(ip);
|
||||||
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
||||||
loginUser.setBrowser(userAgent.getBrowser().getName());
|
loginUser.setBrowser(UserAgentUtils.getBrowser(userAgent));
|
||||||
loginUser.setOs(userAgent.getOperatingSystem().getName());
|
loginUser.setOs(UserAgentUtils.getOperatingSystem(userAgent));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,4 +230,41 @@ public class TokenService
|
|||||||
{
|
{
|
||||||
return CacheConstants.LOGIN_TOKEN_KEY + uuid;
|
return CacheConstants.LOGIN_TOKEN_KEY + uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色权限变更后,刷新所有持有该角色的在线用户权限
|
||||||
|
*
|
||||||
|
* @param roleId 变更的角色ID
|
||||||
|
* @param permissionService 权限服务
|
||||||
|
*/
|
||||||
|
public void refreshPermissionByRoleId(Long roleId, SysPermissionService permissionService)
|
||||||
|
{
|
||||||
|
// 扫描所有在线 token
|
||||||
|
String pattern = CacheConstants.LOGIN_TOKEN_KEY + "*";
|
||||||
|
Collection<String> keys = redisCache.keys(pattern);
|
||||||
|
if (keys == null || keys.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String key : keys)
|
||||||
|
{
|
||||||
|
LoginUser loginUser = redisCache.getCacheObject(key);
|
||||||
|
if (loginUser == null || loginUser.getUser() == null || loginUser.getUser().isAdmin())
|
||||||
|
{
|
||||||
|
// 管理员拥有所有权限,跳过
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 判断该用户是否拥有此角色
|
||||||
|
boolean hasRole = loginUser.getUser().getRoles() != null
|
||||||
|
&& loginUser.getUser().getRoles().stream().anyMatch(r -> roleId.equals(r.getRoleId()));
|
||||||
|
if (!hasRole)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 刷新权限缓存
|
||||||
|
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
|
||||||
|
refreshToken(loginUser);
|
||||||
|
log.info("角色[{}]权限变更,已刷新在线用户[{}]的权限缓存", roleId, loginUser.getUsername());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -11,6 +11,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
|
|||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.enums.UserStatus;
|
import com.ruoyi.common.enums.UserStatus;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
@@ -40,17 +41,17 @@ public class UserDetailsServiceImpl implements UserDetailsService
|
|||||||
if (StringUtils.isNull(user))
|
if (StringUtils.isNull(user))
|
||||||
{
|
{
|
||||||
log.info("登录用户:{} 不存在.", username);
|
log.info("登录用户:{} 不存在.", username);
|
||||||
throw new ServiceException("登录用户:" + username + " 不存在");
|
throw new ServiceException(MessageUtils.message("user.not.exists"));
|
||||||
}
|
}
|
||||||
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||||
{
|
{
|
||||||
log.info("登录用户:{} 已被删除.", username);
|
log.info("登录用户:{} 已被删除.", username);
|
||||||
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
|
throw new ServiceException(MessageUtils.message("user.password.delete"));
|
||||||
}
|
}
|
||||||
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||||
{
|
{
|
||||||
log.info("登录用户:{} 已被停用.", username);
|
log.info("登录用户:{} 已被停用.", username);
|
||||||
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
|
throw new ServiceException(MessageUtils.message("user.blocked"));
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordService.validate(user);
|
passwordService.validate(user);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -23,18 +23,18 @@
|
|||||||
<artifactId>velocity-engine-core</artifactId>
|
<artifactId>velocity-engine-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- collections工具类 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-collections</groupId>
|
|
||||||
<artifactId>commons-collections</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 通用工具-->
|
<!-- 通用工具-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 阿里数据库连接池 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -21,12 +21,15 @@ public class GenConfig
|
|||||||
/** 生成包路径 */
|
/** 生成包路径 */
|
||||||
public static String packageName;
|
public static String packageName;
|
||||||
|
|
||||||
/** 自动去除表前缀,默认是false */
|
/** 自动去除表前缀 */
|
||||||
public static boolean autoRemovePre;
|
public static boolean autoRemovePre;
|
||||||
|
|
||||||
/** 表前缀(类名不会包含表前缀) */
|
/** 表前缀 */
|
||||||
public static String tablePrefix;
|
public static String tablePrefix;
|
||||||
|
|
||||||
|
/** 是否允许生成文件覆盖到本地(自定义路径) */
|
||||||
|
public static boolean allowOverwrite;
|
||||||
|
|
||||||
public static String getAuthor()
|
public static String getAuthor()
|
||||||
{
|
{
|
||||||
return author;
|
return author;
|
||||||
@@ -70,4 +73,15 @@ public class GenConfig
|
|||||||
{
|
{
|
||||||
GenConfig.tablePrefix = tablePrefix;
|
GenConfig.tablePrefix = tablePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAllowOverwrite()
|
||||||
|
{
|
||||||
|
return allowOverwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${allowOverwrite}")
|
||||||
|
public void setAllowOverwrite(boolean allowOverwrite)
|
||||||
|
{
|
||||||
|
GenConfig.allowOverwrite = allowOverwrite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.generator.controller;
|
package com.ruoyi.generator.controller;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -16,13 +17,21 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.alibaba.druid.DbType;
|
||||||
|
import com.alibaba.druid.sql.SQLUtils;
|
||||||
|
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||||
|
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.text.Convert;
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.sql.SqlUtil;
|
||||||
|
import com.ruoyi.generator.config.GenConfig;
|
||||||
import com.ruoyi.generator.domain.GenTable;
|
import com.ruoyi.generator.domain.GenTable;
|
||||||
import com.ruoyi.generator.domain.GenTableColumn;
|
import com.ruoyi.generator.domain.GenTableColumn;
|
||||||
import com.ruoyi.generator.service.IGenTableColumnService;
|
import com.ruoyi.generator.service.IGenTableColumnService;
|
||||||
@@ -56,7 +65,7 @@ public class GenController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改代码生成业务
|
* 获取代码生成信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('tool:gen:query')")
|
@PreAuthorize("@ss.hasPermi('tool:gen:query')")
|
||||||
@GetMapping(value = "/{tableId}")
|
@GetMapping(value = "/{tableId}")
|
||||||
@@ -104,15 +113,52 @@ public class GenController extends BaseController
|
|||||||
@PreAuthorize("@ss.hasPermi('tool:gen:import')")
|
@PreAuthorize("@ss.hasPermi('tool:gen:import')")
|
||||||
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
|
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importTable")
|
@PostMapping("/importTable")
|
||||||
public AjaxResult importTableSave(String tables)
|
public AjaxResult importTableSave(@RequestParam("tables") String tables, @RequestParam("tplWebType") String tplWebType)
|
||||||
{
|
{
|
||||||
String[] tableNames = Convert.toStrArray(tables);
|
String[] tableNames = Convert.toStrArray(tables);
|
||||||
// 查询表信息
|
// 查询表信息
|
||||||
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
|
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
|
||||||
genTableService.importGenTable(tableList);
|
genTableService.importGenTable(tableList, tplWebType, SecurityUtils.getUsername());
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表结构(保存)
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasRole('admin')")
|
||||||
|
@Log(title = "创建表", businessType = BusinessType.OTHER)
|
||||||
|
@PostMapping("/createTable")
|
||||||
|
public AjaxResult createTableSave(@RequestParam("sql") String sql, @RequestParam("tplWebType") String tplWebType)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SqlUtil.filterKeyword(sql);
|
||||||
|
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
|
||||||
|
List<String> tableNames = new ArrayList<>();
|
||||||
|
for (SQLStatement sqlStatement : sqlStatements)
|
||||||
|
{
|
||||||
|
if (sqlStatement instanceof MySqlCreateTableStatement)
|
||||||
|
{
|
||||||
|
MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
|
||||||
|
if (genTableService.createTable(createTableStatement.toString()))
|
||||||
|
{
|
||||||
|
String tableName = createTableStatement.getTableName().replaceAll("`", "");
|
||||||
|
tableNames.add(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
|
||||||
|
String operName = SecurityUtils.getUsername();
|
||||||
|
genTableService.importGenTable(tableList, tplWebType, operName);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return AjaxResult.error("创建表结构异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改保存代码生成业务
|
* 修改保存代码生成业务
|
||||||
*/
|
*/
|
||||||
@@ -169,6 +215,10 @@ public class GenController extends BaseController
|
|||||||
@GetMapping("/genCode/{tableName}")
|
@GetMapping("/genCode/{tableName}")
|
||||||
public AjaxResult genCode(@PathVariable("tableName") String tableName)
|
public AjaxResult genCode(@PathVariable("tableName") String tableName)
|
||||||
{
|
{
|
||||||
|
if (!GenConfig.isAllowOverwrite())
|
||||||
|
{
|
||||||
|
return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
|
||||||
|
}
|
||||||
genTableService.generatorCode(tableName);
|
genTableService.generatorCode(tableName);
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ public class GenTable extends BaseEntity
|
|||||||
/** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */
|
/** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */
|
||||||
private String tplCategory;
|
private String tplCategory;
|
||||||
|
|
||||||
|
/** 前端类型(element-ui模版 element-plus模版 element-plus-typescript模版) */
|
||||||
|
private String tplWebType;
|
||||||
|
|
||||||
/** 生成包路径 */
|
/** 生成包路径 */
|
||||||
@NotBlank(message = "生成包路径不能为空")
|
@NotBlank(message = "生成包路径不能为空")
|
||||||
private String packageName;
|
private String packageName;
|
||||||
@@ -61,6 +64,9 @@ public class GenTable extends BaseEntity
|
|||||||
@NotBlank(message = "作者不能为空")
|
@NotBlank(message = "作者不能为空")
|
||||||
private String functionAuthor;
|
private String functionAuthor;
|
||||||
|
|
||||||
|
/** 表单布局(单列 双列 三列) */
|
||||||
|
private Integer formColNum;
|
||||||
|
|
||||||
/** 生成代码方式(0zip压缩包 1自定义路径) */
|
/** 生成代码方式(0zip压缩包 1自定义路径) */
|
||||||
private String genType;
|
private String genType;
|
||||||
|
|
||||||
@@ -90,11 +96,14 @@ public class GenTable extends BaseEntity
|
|||||||
private String treeName;
|
private String treeName;
|
||||||
|
|
||||||
/** 上级菜单ID字段 */
|
/** 上级菜单ID字段 */
|
||||||
private String parentMenuId;
|
private Long parentMenuId;
|
||||||
|
|
||||||
/** 上级菜单名称字段 */
|
/** 上级菜单名称字段 */
|
||||||
private String parentMenuName;
|
private String parentMenuName;
|
||||||
|
|
||||||
|
/** 是否生成详情页 */
|
||||||
|
private boolean isView;
|
||||||
|
|
||||||
public Long getTableId()
|
public Long getTableId()
|
||||||
{
|
{
|
||||||
return tableId;
|
return tableId;
|
||||||
@@ -165,6 +174,16 @@ public class GenTable extends BaseEntity
|
|||||||
this.tplCategory = tplCategory;
|
this.tplCategory = tplCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTplWebType()
|
||||||
|
{
|
||||||
|
return tplWebType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTplWebType(String tplWebType)
|
||||||
|
{
|
||||||
|
this.tplWebType = tplWebType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPackageName()
|
public String getPackageName()
|
||||||
{
|
{
|
||||||
return packageName;
|
return packageName;
|
||||||
@@ -215,6 +234,16 @@ public class GenTable extends BaseEntity
|
|||||||
this.functionAuthor = functionAuthor;
|
this.functionAuthor = functionAuthor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getFormColNum()
|
||||||
|
{
|
||||||
|
return formColNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormColNum(Integer formColNum)
|
||||||
|
{
|
||||||
|
this.formColNum = formColNum;
|
||||||
|
}
|
||||||
|
|
||||||
public String getGenType()
|
public String getGenType()
|
||||||
{
|
{
|
||||||
return genType;
|
return genType;
|
||||||
@@ -305,12 +334,12 @@ public class GenTable extends BaseEntity
|
|||||||
this.treeName = treeName;
|
this.treeName = treeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParentMenuId()
|
public Long getParentMenuId()
|
||||||
{
|
{
|
||||||
return parentMenuId;
|
return parentMenuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParentMenuId(String parentMenuId)
|
public void setParentMenuId(Long parentMenuId)
|
||||||
{
|
{
|
||||||
this.parentMenuId = parentMenuId;
|
this.parentMenuId = parentMenuId;
|
||||||
}
|
}
|
||||||
@@ -325,6 +354,16 @@ public class GenTable extends BaseEntity
|
|||||||
this.parentMenuName = parentMenuName;
|
this.parentMenuName = parentMenuName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isView()
|
||||||
|
{
|
||||||
|
return isView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setView(boolean isView)
|
||||||
|
{
|
||||||
|
this.isView = isView;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSub()
|
public boolean isSub()
|
||||||
{
|
{
|
||||||
return isSub(this.tplCategory);
|
return isSub(this.tplCategory);
|
||||||
|
|||||||
@@ -80,4 +80,12 @@ public interface GenTableMapper
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteGenTableByIds(Long[] ids);
|
public int deleteGenTableByIds(Long[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表
|
||||||
|
*
|
||||||
|
* @param sql 表结构
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int createTable(String sql);
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-24
@@ -4,6 +4,8 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -27,7 +29,6 @@ import com.ruoyi.common.constant.Constants;
|
|||||||
import com.ruoyi.common.constant.GenConstants;
|
import com.ruoyi.common.constant.GenConstants;
|
||||||
import com.ruoyi.common.core.text.CharsetKit;
|
import com.ruoyi.common.core.text.CharsetKit;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.generator.domain.GenTable;
|
import com.ruoyi.generator.domain.GenTable;
|
||||||
import com.ruoyi.generator.domain.GenTableColumn;
|
import com.ruoyi.generator.domain.GenTableColumn;
|
||||||
@@ -129,9 +130,9 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
int row = genTableMapper.updateGenTable(genTable);
|
int row = genTableMapper.updateGenTable(genTable);
|
||||||
if (row > 0)
|
if (row > 0)
|
||||||
{
|
{
|
||||||
for (GenTableColumn cenTableColumn : genTable.getColumns())
|
for (GenTableColumn genTableColumn : genTable.getColumns())
|
||||||
{
|
{
|
||||||
genTableColumnMapper.updateGenTableColumn(cenTableColumn);
|
genTableColumnMapper.updateGenTableColumn(genTableColumn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +151,18 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
|
genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表
|
||||||
|
*
|
||||||
|
* @param sql 创建表语句
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean createTable(String sql)
|
||||||
|
{
|
||||||
|
return genTableMapper.createTable(sql) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入表结构
|
* 导入表结构
|
||||||
*
|
*
|
||||||
@@ -157,14 +170,14 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void importGenTable(List<GenTable> tableList)
|
public void importGenTable(List<GenTable> tableList, String tplWebType, String operName)
|
||||||
{
|
{
|
||||||
String operName = SecurityUtils.getUsername();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (GenTable table : tableList)
|
for (GenTable table : tableList)
|
||||||
{
|
{
|
||||||
String tableName = table.getTableName();
|
String tableName = table.getTableName();
|
||||||
|
table.setTplWebType(tplWebType);
|
||||||
GenUtils.initTable(table, operName);
|
GenUtils.initTable(table, operName);
|
||||||
int row = genTableMapper.insertGenTable(table);
|
int row = genTableMapper.insertGenTable(table);
|
||||||
if (row > 0)
|
if (row > 0)
|
||||||
@@ -206,7 +219,7 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||||
|
|
||||||
// 获取模板列表
|
// 获取模板列表
|
||||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
List<String> templates = VelocityUtils.getTemplateList(table);
|
||||||
for (String template : templates)
|
for (String template : templates)
|
||||||
{
|
{
|
||||||
// 渲染模板
|
// 渲染模板
|
||||||
@@ -227,11 +240,7 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
@Override
|
@Override
|
||||||
public byte[] downloadCode(String tableName)
|
public byte[] downloadCode(String tableName)
|
||||||
{
|
{
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
return downloadCode(new String[] { tableName });
|
||||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
|
||||||
generatorCode(tableName, zip);
|
|
||||||
IOUtils.closeQuietly(zip);
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,10 +263,10 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||||
|
|
||||||
// 获取模板列表
|
// 获取模板列表
|
||||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
List<String> templates = VelocityUtils.getTemplateList(table);
|
||||||
for (String template : templates)
|
for (String template : templates)
|
||||||
{
|
{
|
||||||
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
|
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "api.ts.vm", "type.ts.vm", "index.ts.vm", "index.vue.vm", "index-tree.vue.vm", "view.vue.vm"))
|
||||||
{
|
{
|
||||||
// 渲染模板
|
// 渲染模板
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
@@ -342,9 +351,14 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
{
|
{
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||||
|
Map<String, StringBuffer> typeFiles = new HashMap<>();
|
||||||
for (String tableName : tableNames)
|
for (String tableName : tableNames)
|
||||||
{
|
{
|
||||||
generatorCode(tableName, zip);
|
generatorCode(tableName, zip, typeFiles);
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, StringBuffer> entry : typeFiles.entrySet())
|
||||||
|
{
|
||||||
|
writeToZip(zip, entry.getKey(), entry.getValue().toString());
|
||||||
}
|
}
|
||||||
IOUtils.closeQuietly(zip);
|
IOUtils.closeQuietly(zip);
|
||||||
return outputStream.toByteArray();
|
return outputStream.toByteArray();
|
||||||
@@ -353,7 +367,7 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
/**
|
/**
|
||||||
* 查询表信息并生成代码
|
* 查询表信息并生成代码
|
||||||
*/
|
*/
|
||||||
private void generatorCode(String tableName, ZipOutputStream zip)
|
private void generatorCode(String tableName, ZipOutputStream zip, Map<String, StringBuffer> typeFiles)
|
||||||
{
|
{
|
||||||
// 查询表信息
|
// 查询表信息
|
||||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||||
@@ -367,26 +381,53 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||||
|
|
||||||
// 获取模板列表
|
// 获取模板列表
|
||||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
List<String> templates = VelocityUtils.getTemplateList(table);
|
||||||
for (String template : templates)
|
for (String template : templates)
|
||||||
{
|
{
|
||||||
// 渲染模板
|
// 渲染模板
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
|
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
|
||||||
tpl.merge(context, sw);
|
tpl.merge(context, sw);
|
||||||
|
String fileName = VelocityUtils.getFileName(template, table);
|
||||||
|
// index-bak.ts 模版,追加内容
|
||||||
|
if (fileName.contains("index-bak.ts"))
|
||||||
|
{
|
||||||
|
if (!typeFiles.containsKey(fileName))
|
||||||
|
{
|
||||||
|
typeFiles.put(fileName, new StringBuffer(sw.toString()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Arrays.stream(sw.toString().split("\n")).filter(line -> line.startsWith("export * from")).forEach(line -> typeFiles.get(fileName).append("\n").append(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 其他文件正常添加
|
||||||
|
writeToZip(zip, fileName, sw.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字符串内容写入ZIP输出流
|
||||||
|
*
|
||||||
|
* @param zip ZIP输出流
|
||||||
|
* @param fileName ZIP条目名称(即文件名)
|
||||||
|
* @param content 要写入的内容
|
||||||
|
*/
|
||||||
|
private void writeToZip(ZipOutputStream zip, String fileName, String content)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 添加到zip
|
zip.putNextEntry(new ZipEntry(fileName));
|
||||||
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
|
IOUtils.write(content, zip, Constants.UTF8);
|
||||||
IOUtils.write(sw.toString(), zip, Constants.UTF8);
|
|
||||||
IOUtils.closeQuietly(sw);
|
|
||||||
zip.flush();
|
zip.flush();
|
||||||
zip.closeEntry();
|
zip.closeEntry();
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
log.error("渲染模板失败,表名:" + table.getTableName(), e);
|
log.error("写入ZIP文件失败,文件名: " + fileName, e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,6 +455,7 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
{
|
{
|
||||||
throw new ServiceException("树名称字段不能为空");
|
throw new ServiceException("树名称字段不能为空");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
|
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
|
||||||
{
|
{
|
||||||
if (StringUtils.isEmpty(genTable.getSubTableName()))
|
if (StringUtils.isEmpty(genTable.getSubTableName()))
|
||||||
@@ -426,7 +468,6 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置主键列信息
|
* 设置主键列信息
|
||||||
@@ -491,14 +532,16 @@ public class GenTableServiceImpl implements IGenTableService
|
|||||||
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
|
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
|
||||||
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
|
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
|
||||||
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
|
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
|
||||||
String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
|
Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID);
|
||||||
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
|
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
|
||||||
|
boolean isView = paramsObj.getBooleanValue(GenConstants.GEN_VIEW);
|
||||||
|
|
||||||
genTable.setTreeCode(treeCode);
|
genTable.setTreeCode(treeCode);
|
||||||
genTable.setTreeParentCode(treeParentCode);
|
genTable.setTreeParentCode(treeParentCode);
|
||||||
genTable.setTreeName(treeName);
|
genTable.setTreeName(treeName);
|
||||||
genTable.setParentMenuId(parentMenuId);
|
genTable.setParentMenuId(parentMenuId);
|
||||||
genTable.setParentMenuName(parentMenuName);
|
genTable.setParentMenuName(parentMenuName);
|
||||||
|
genTable.setView(isView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,12 +66,22 @@ public interface IGenTableService
|
|||||||
*/
|
*/
|
||||||
public void deleteGenTableByIds(Long[] tableIds);
|
public void deleteGenTableByIds(Long[] tableIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表
|
||||||
|
*
|
||||||
|
* @param sql 创建表语句
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean createTable(String sql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入表结构
|
* 导入表结构
|
||||||
*
|
*
|
||||||
* @param tableList 导入表列表
|
* @param tableList 导入表列表
|
||||||
|
* @param tplWebType 前端类型
|
||||||
|
* @param operName 操作人员
|
||||||
*/
|
*/
|
||||||
public void importGenTable(List<GenTable> tableList);
|
public void importGenTable(List<GenTable> tableList, String tplWebType, String operName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预览代码
|
* 预览代码
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ public class VelocityUtils
|
|||||||
/** 默认上级菜单,系统工具 */
|
/** 默认上级菜单,系统工具 */
|
||||||
private static final String DEFAULT_PARENT_MENU_ID = "3";
|
private static final String DEFAULT_PARENT_MENU_ID = "3";
|
||||||
|
|
||||||
|
/** Vue3 Element Plus 模版 */
|
||||||
|
private static final String ELEMENT_PLUS = "element-plus";
|
||||||
|
|
||||||
|
/** Vue3 Element Plus TypeScript 模版 */
|
||||||
|
private static final String ELEMENT_PLUS_TYPESSRIPT = "element-plus-typescript";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置模板变量信息
|
* 设置模板变量信息
|
||||||
*
|
*
|
||||||
@@ -54,6 +60,7 @@ public class VelocityUtils
|
|||||||
velocityContext.put("basePackage", getPackagePrefix(packageName));
|
velocityContext.put("basePackage", getPackagePrefix(packageName));
|
||||||
velocityContext.put("packageName", packageName);
|
velocityContext.put("packageName", packageName);
|
||||||
velocityContext.put("author", genTable.getFunctionAuthor());
|
velocityContext.put("author", genTable.getFunctionAuthor());
|
||||||
|
velocityContext.put("colSpan", getColSpan(genTable.getFormColNum()));
|
||||||
velocityContext.put("datetime", DateUtils.getDate());
|
velocityContext.put("datetime", DateUtils.getDate());
|
||||||
velocityContext.put("pkColumn", genTable.getPkColumn());
|
velocityContext.put("pkColumn", genTable.getPkColumn());
|
||||||
velocityContext.put("importList", getImportList(genTable));
|
velocityContext.put("importList", getImportList(genTable));
|
||||||
@@ -61,6 +68,7 @@ public class VelocityUtils
|
|||||||
velocityContext.put("columns", genTable.getColumns());
|
velocityContext.put("columns", genTable.getColumns());
|
||||||
velocityContext.put("table", genTable);
|
velocityContext.put("table", genTable);
|
||||||
velocityContext.put("dicts", getDicts(genTable));
|
velocityContext.put("dicts", getDicts(genTable));
|
||||||
|
setExtensionsContext(velocityContext, genTable.getOptions());
|
||||||
setMenuVelocityContext(velocityContext, genTable);
|
setMenuVelocityContext(velocityContext, genTable);
|
||||||
if (GenConstants.TPL_TREE.equals(tplCategory))
|
if (GenConstants.TPL_TREE.equals(tplCategory))
|
||||||
{
|
{
|
||||||
@@ -73,6 +81,13 @@ public class VelocityUtils
|
|||||||
return velocityContext;
|
return velocityContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setExtensionsContext(VelocityContext context, String options)
|
||||||
|
{
|
||||||
|
JSONObject paramsObj = JSONObject.parseObject(options);
|
||||||
|
boolean genView = genView(paramsObj);
|
||||||
|
context.put("genView", genView);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
|
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
|
||||||
{
|
{
|
||||||
String options = genTable.getOptions();
|
String options = genTable.getOptions();
|
||||||
@@ -123,11 +138,27 @@ public class VelocityUtils
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模板信息
|
* 获取模板信息
|
||||||
*
|
* @param tplCategory 生成的模板
|
||||||
|
* @param tplWebType 前端类型
|
||||||
* @return 模板列表
|
* @return 模板列表
|
||||||
*/
|
*/
|
||||||
public static List<String> getTemplateList(String tplCategory)
|
public static List<String> getTemplateList(GenTable table)
|
||||||
{
|
{
|
||||||
|
String tplWebType = table.getTplWebType();
|
||||||
|
String tplCategory = table.getTplCategory();
|
||||||
|
JSONObject paramsObj = JSONObject.parseObject(table.getOptions());
|
||||||
|
boolean isView = genView(paramsObj);
|
||||||
|
String useWebType = "vm/vue";
|
||||||
|
String apiTemplate = "vm/js/api.js.vm";
|
||||||
|
if (StringUtils.equals(ELEMENT_PLUS, tplWebType))
|
||||||
|
{
|
||||||
|
useWebType = "vm/vue/v3";
|
||||||
|
}
|
||||||
|
else if (StringUtils.equals(ELEMENT_PLUS_TYPESSRIPT, tplWebType))
|
||||||
|
{
|
||||||
|
useWebType = "vm/vue/v3ts";
|
||||||
|
apiTemplate = "vm/ts/api.ts.vm";
|
||||||
|
}
|
||||||
List<String> templates = new ArrayList<String>();
|
List<String> templates = new ArrayList<String>();
|
||||||
templates.add("vm/java/domain.java.vm");
|
templates.add("vm/java/domain.java.vm");
|
||||||
templates.add("vm/java/mapper.java.vm");
|
templates.add("vm/java/mapper.java.vm");
|
||||||
@@ -136,20 +167,29 @@ public class VelocityUtils
|
|||||||
templates.add("vm/java/controller.java.vm");
|
templates.add("vm/java/controller.java.vm");
|
||||||
templates.add("vm/xml/mapper.xml.vm");
|
templates.add("vm/xml/mapper.xml.vm");
|
||||||
templates.add("vm/sql/sql.vm");
|
templates.add("vm/sql/sql.vm");
|
||||||
templates.add("vm/js/api.js.vm");
|
templates.add(apiTemplate);
|
||||||
|
if (StringUtils.equals(ELEMENT_PLUS_TYPESSRIPT, tplWebType))
|
||||||
|
{
|
||||||
|
templates.add("vm/ts/type.ts.vm");
|
||||||
|
templates.add("vm/ts/index.ts.vm");
|
||||||
|
}
|
||||||
if (GenConstants.TPL_CRUD.equals(tplCategory))
|
if (GenConstants.TPL_CRUD.equals(tplCategory))
|
||||||
{
|
{
|
||||||
templates.add("vm/vue/index.vue.vm");
|
templates.add(useWebType + "/index.vue.vm");
|
||||||
}
|
}
|
||||||
else if (GenConstants.TPL_TREE.equals(tplCategory))
|
else if (GenConstants.TPL_TREE.equals(tplCategory))
|
||||||
{
|
{
|
||||||
templates.add("vm/vue/index-tree.vue.vm");
|
templates.add(useWebType + "/index-tree.vue.vm");
|
||||||
}
|
}
|
||||||
else if (GenConstants.TPL_SUB.equals(tplCategory))
|
else if (GenConstants.TPL_SUB.equals(tplCategory))
|
||||||
{
|
{
|
||||||
templates.add("vm/vue/index.vue.vm");
|
templates.add(useWebType + "/index.vue.vm");
|
||||||
templates.add("vm/java/sub-domain.java.vm");
|
templates.add("vm/java/sub-domain.java.vm");
|
||||||
}
|
}
|
||||||
|
if (isView)
|
||||||
|
{
|
||||||
|
templates.add(useWebType + "/view.vue.vm");
|
||||||
|
}
|
||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +249,18 @@ public class VelocityUtils
|
|||||||
{
|
{
|
||||||
fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
|
fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
|
||||||
}
|
}
|
||||||
|
else if (template.contains("api.ts.vm"))
|
||||||
|
{
|
||||||
|
fileName = StringUtils.format("{}/api/{}/{}.ts", vuePath, moduleName, businessName);
|
||||||
|
}
|
||||||
|
else if (template.contains("type.ts.vm"))
|
||||||
|
{
|
||||||
|
fileName = StringUtils.format("{}/types/api/{}/{}.ts", vuePath, moduleName, businessName);
|
||||||
|
}
|
||||||
|
else if (template.contains("index.ts.vm"))
|
||||||
|
{
|
||||||
|
fileName = StringUtils.format("{}/types/api/index-bak.ts", vuePath);
|
||||||
|
}
|
||||||
else if (template.contains("index.vue.vm"))
|
else if (template.contains("index.vue.vm"))
|
||||||
{
|
{
|
||||||
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
||||||
@@ -217,6 +269,10 @@ public class VelocityUtils
|
|||||||
{
|
{
|
||||||
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
||||||
}
|
}
|
||||||
|
else if (template.contains("view.vue.vm"))
|
||||||
|
{
|
||||||
|
fileName = StringUtils.format("{}/views/{}/{}/view.vue", vuePath, moduleName, businessName);
|
||||||
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +414,21 @@ public class VelocityUtils
|
|||||||
return StringUtils.EMPTY;
|
return StringUtils.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展功能/生成详情页
|
||||||
|
*
|
||||||
|
* @param paramsObj 生成其他选项
|
||||||
|
* @return 是否生成详细页
|
||||||
|
*/
|
||||||
|
public static boolean genView(JSONObject paramsObj)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotNull(paramsObj) && paramsObj.containsKey(GenConstants.GEN_VIEW))
|
||||||
|
{
|
||||||
|
return paramsObj.getBoolean(GenConstants.GEN_VIEW);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取树名称
|
* 获取树名称
|
||||||
*
|
*
|
||||||
@@ -399,4 +470,23 @@ public class VelocityUtils
|
|||||||
}
|
}
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取表单 el-col span
|
||||||
|
*
|
||||||
|
* @param formColNum 表单布局方式(1单列 2双列 3三列)
|
||||||
|
* @return span 数值字符串
|
||||||
|
*/
|
||||||
|
public static String getColSpan(int formColNum)
|
||||||
|
{
|
||||||
|
if (formColNum == 2)
|
||||||
|
{
|
||||||
|
return "12";
|
||||||
|
}
|
||||||
|
else if (formColNum == 3)
|
||||||
|
{
|
||||||
|
return "8";
|
||||||
|
}
|
||||||
|
return "24";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,3 +8,5 @@ gen:
|
|||||||
autoRemovePre: false
|
autoRemovePre: false
|
||||||
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
|
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
|
||||||
tablePrefix: sys_
|
tablePrefix: sys_
|
||||||
|
# 是否允许生成文件覆盖到本地(自定义路径),默认不允许
|
||||||
|
allowOverwrite: false
|
||||||
@@ -40,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
|
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
|
||||||
select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
|
select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
|
||||||
from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
|
from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
|
||||||
order by ordinal_position
|
order by ordinal_position
|
||||||
</select>
|
</select>
|
||||||
@@ -94,6 +94,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<set>
|
<set>
|
||||||
<if test="columnComment != null">column_comment = #{columnComment},</if>
|
<if test="columnComment != null">column_comment = #{columnComment},</if>
|
||||||
<if test="javaType != null">java_type = #{javaType},</if>
|
<if test="javaType != null">java_type = #{javaType},</if>
|
||||||
|
<if test="columnType != null">column_type = #{columnType},</if>
|
||||||
<if test="javaField != null">java_field = #{javaField},</if>
|
<if test="javaField != null">java_field = #{javaField},</if>
|
||||||
<if test="isInsert != null">is_insert = #{isInsert},</if>
|
<if test="isInsert != null">is_insert = #{isInsert},</if>
|
||||||
<if test="isEdit != null">is_edit = #{isEdit},</if>
|
<if test="isEdit != null">is_edit = #{isEdit},</if>
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="subTableFkName" column="sub_table_fk_name" />
|
<result property="subTableFkName" column="sub_table_fk_name" />
|
||||||
<result property="className" column="class_name" />
|
<result property="className" column="class_name" />
|
||||||
<result property="tplCategory" column="tpl_category" />
|
<result property="tplCategory" column="tpl_category" />
|
||||||
|
<result property="tplWebType" column="tpl_web_type" />
|
||||||
<result property="packageName" column="package_name" />
|
<result property="packageName" column="package_name" />
|
||||||
<result property="moduleName" column="module_name" />
|
<result property="moduleName" column="module_name" />
|
||||||
<result property="businessName" column="business_name" />
|
<result property="businessName" column="business_name" />
|
||||||
<result property="functionName" column="function_name" />
|
<result property="functionName" column="function_name" />
|
||||||
<result property="functionAuthor" column="function_author" />
|
<result property="functionAuthor" column="function_author" />
|
||||||
|
<result property="formColNum" column="form_col_num" />
|
||||||
<result property="genType" column="gen_type" />
|
<result property="genType" column="gen_type" />
|
||||||
<result property="genPath" column="gen_path" />
|
<result property="genPath" column="gen_path" />
|
||||||
<result property="options" column="options" />
|
<result property="options" column="options" />
|
||||||
@@ -54,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectGenTableVo">
|
<sql id="selectGenTableVo">
|
||||||
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
|
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, tpl_web_type, package_name, module_name, business_name, function_name, function_author, form_col_num, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
|
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
|
||||||
@@ -67,10 +69,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
AND date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
|
||||||
</if>
|
</if>
|
||||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
AND date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
@@ -78,7 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
|
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
|
||||||
select table_name, table_comment, create_time, update_time from information_schema.tables
|
select table_name, table_comment, create_time, update_time from information_schema.tables
|
||||||
where table_schema = (select database())
|
where table_schema = (select database())
|
||||||
AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
|
AND table_name NOT LIKE 'qrtz\_%' AND table_name NOT LIKE 'gen\_%'
|
||||||
AND table_name NOT IN (select table_name from gen_table)
|
AND table_name NOT IN (select table_name from gen_table)
|
||||||
<if test="tableName != null and tableName != ''">
|
<if test="tableName != null and tableName != ''">
|
||||||
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
|
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
|
||||||
@@ -87,17 +89,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
AND date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
|
||||||
</if>
|
</if>
|
||||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
AND date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
|
||||||
</if>
|
</if>
|
||||||
order by create_time desc
|
order by create_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectDbTableListByNames" resultMap="GenTableResult">
|
<select id="selectDbTableListByNames" resultMap="GenTableResult">
|
||||||
select table_name, table_comment, create_time, update_time from information_schema.tables
|
select table_name, table_comment, create_time, update_time from information_schema.tables
|
||||||
where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
|
where table_name NOT LIKE 'qrtz\_%' and table_name NOT LIKE 'gen\_%' and table_schema = (select database())
|
||||||
and table_name in
|
and table_name in
|
||||||
<foreach collection="array" item="name" open="(" separator="," close=")">
|
<foreach collection="array" item="name" open="(" separator="," close=")">
|
||||||
#{name}
|
#{name}
|
||||||
@@ -111,7 +113,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
|
<select id="selectGenTableById" parameterType="Long" 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.gen_type, t.gen_path, 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.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.form_col_num, 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
|
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
|
FROM gen_table t
|
||||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||||
@@ -119,7 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
|
<select id="selectGenTableByName" 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.gen_type, t.gen_path, 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.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.form_col_num, 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
|
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
|
FROM gen_table t
|
||||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||||
@@ -127,7 +129,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
|
<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,
|
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.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.form_col_num, 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
|
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
|
FROM gen_table t
|
||||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||||
@@ -140,11 +142,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="tableComment != null and tableComment != ''">table_comment,</if>
|
<if test="tableComment != null and tableComment != ''">table_comment,</if>
|
||||||
<if test="className != null and className != ''">class_name,</if>
|
<if test="className != null and className != ''">class_name,</if>
|
||||||
<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
|
<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
|
||||||
|
<if test="tplWebType != null and tplWebType != ''">tpl_web_type,</if>
|
||||||
<if test="packageName != null and packageName != ''">package_name,</if>
|
<if test="packageName != null and packageName != ''">package_name,</if>
|
||||||
<if test="moduleName != null and moduleName != ''">module_name,</if>
|
<if test="moduleName != null and moduleName != ''">module_name,</if>
|
||||||
<if test="businessName != null and businessName != ''">business_name,</if>
|
<if test="businessName != null and businessName != ''">business_name,</if>
|
||||||
<if test="functionName != null and functionName != ''">function_name,</if>
|
<if test="functionName != null and functionName != ''">function_name,</if>
|
||||||
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
|
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
|
||||||
|
<if test="formColNum != null">form_col_num,</if>
|
||||||
<if test="genType != null and genType != ''">gen_type,</if>
|
<if test="genType != null and genType != ''">gen_type,</if>
|
||||||
<if test="genPath != null and genPath != ''">gen_path,</if>
|
<if test="genPath != null and genPath != ''">gen_path,</if>
|
||||||
<if test="remark != null and remark != ''">remark,</if>
|
<if test="remark != null and remark != ''">remark,</if>
|
||||||
@@ -155,11 +159,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
|
<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
|
||||||
<if test="className != null and className != ''">#{className},</if>
|
<if test="className != null and className != ''">#{className},</if>
|
||||||
<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
|
<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
|
||||||
|
<if test="tplWebType != null and tplWebType != ''">#{tplWebType},</if>
|
||||||
<if test="packageName != null and packageName != ''">#{packageName},</if>
|
<if test="packageName != null and packageName != ''">#{packageName},</if>
|
||||||
<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
|
<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
|
||||||
<if test="businessName != null and businessName != ''">#{businessName},</if>
|
<if test="businessName != null and businessName != ''">#{businessName},</if>
|
||||||
<if test="functionName != null and functionName != ''">#{functionName},</if>
|
<if test="functionName != null and functionName != ''">#{functionName},</if>
|
||||||
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
|
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
|
||||||
|
<if test="formColNum != null">#{formColNum},</if>
|
||||||
<if test="genType != null and genType != ''">#{genType},</if>
|
<if test="genType != null and genType != ''">#{genType},</if>
|
||||||
<if test="genPath != null and genPath != ''">#{genPath},</if>
|
<if test="genPath != null and genPath != ''">#{genPath},</if>
|
||||||
<if test="remark != null and remark != ''">#{remark},</if>
|
<if test="remark != null and remark != ''">#{remark},</if>
|
||||||
@@ -168,6 +174,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<update id="createTable">
|
||||||
|
${sql}
|
||||||
|
</update>
|
||||||
|
|
||||||
<update id="updateGenTable" parameterType="GenTable">
|
<update id="updateGenTable" parameterType="GenTable">
|
||||||
update gen_table
|
update gen_table
|
||||||
<set>
|
<set>
|
||||||
@@ -177,9 +187,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
|
<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
|
||||||
<if test="className != null and className != ''">class_name = #{className},</if>
|
<if test="className != null and className != ''">class_name = #{className},</if>
|
||||||
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
|
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
|
||||||
|
<if test="formColNum != null">form_col_num = #{formColNum},</if>
|
||||||
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
|
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
|
||||||
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
|
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
|
||||||
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
|
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
|
||||||
|
<if test="tplWebType != null and tplWebType != ''">tpl_web_type = #{tplWebType},</if>
|
||||||
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
|
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
|
||||||
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
|
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
|
||||||
<if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
|
<if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ public class ${ClassName} extends ${Entity}
|
|||||||
{
|
{
|
||||||
return $column.javaField;
|
return $column.javaField;
|
||||||
}
|
}
|
||||||
#end
|
|
||||||
#end
|
|
||||||
|
|
||||||
|
#end
|
||||||
|
#end
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
public List<${subClassName}> get${subClassName}List()
|
public List<${subClassName}> get${subClassName}List()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
import type { AjaxResult, TableDataInfo, ${BusinessName}QueryParams, ${ClassName} } from '@/types'
|
||||||
|
|
||||||
|
// 查询${functionName}列表
|
||||||
|
#if($table.tree)
|
||||||
|
export function list${BusinessName}(query?: ${BusinessName}QueryParams): Promise<AjaxResult<${ClassName}[]>> {
|
||||||
|
#else
|
||||||
|
export function list${BusinessName}(query: ${BusinessName}QueryParams): Promise<TableDataInfo<${ClassName}[]>> {
|
||||||
|
#end
|
||||||
|
return request({
|
||||||
|
url: '/${moduleName}/${businessName}/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询${functionName}详细
|
||||||
|
export function get${BusinessName}(${pkColumn.javaField}: number): Promise<AjaxResult<${ClassName}>> {
|
||||||
|
return request({
|
||||||
|
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增${functionName}
|
||||||
|
export function add${BusinessName}(data: ${ClassName}): Promise<AjaxResult> {
|
||||||
|
return request({
|
||||||
|
url: '/${moduleName}/${businessName}',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改${functionName}
|
||||||
|
export function update${BusinessName}(data: ${ClassName}): Promise<AjaxResult> {
|
||||||
|
return request({
|
||||||
|
url: '/${moduleName}/${businessName}',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除${functionName}
|
||||||
|
export function del${BusinessName}(${pkColumn.javaField}: number | number[]): Promise<AjaxResult> {
|
||||||
|
return request({
|
||||||
|
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* API 类型统一导出
|
||||||
|
*/
|
||||||
|
....
|
||||||
|
|
||||||
|
// 防止覆盖,需手动追加下面代码到index.ts文件中,追加好后此文件可删除
|
||||||
|
|
||||||
|
// ${moduleName} 模块
|
||||||
|
export * from "./${moduleName}/${businessName}";
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import type { PageDomain, BaseEntity } from "../common";
|
||||||
|
|
||||||
|
/** ${functionName}配置分页查询参数 */
|
||||||
|
export interface ${BusinessName}QueryParams extends PageDomain {
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if($column.query)
|
||||||
|
#set($type = "string")
|
||||||
|
#if($column.javaType == "Long" || $column.javaType == "Integer")
|
||||||
|
#set($type = "number")
|
||||||
|
#elseif($column.javaType == "Boolean")
|
||||||
|
#set($type = "boolean")
|
||||||
|
#end
|
||||||
|
/** ${column.columnComment} */
|
||||||
|
${column.javaField}?: ${type};
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ${functionName}配置信息 */
|
||||||
|
export interface ${ClassName} extends BaseEntity {
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#set($type = "string")
|
||||||
|
#if($column.javaType == "Long" || $column.javaType == "Integer")
|
||||||
|
#set($type = "number")
|
||||||
|
#elseif($column.javaType == "Boolean")
|
||||||
|
#set($type = "boolean")
|
||||||
|
#end
|
||||||
|
/** ${column.columnComment} */
|
||||||
|
${column.javaField}?: ${type};
|
||||||
|
#end
|
||||||
|
#if($table.sub)
|
||||||
|
/** $table.subTable.functionName信息 */
|
||||||
|
${subclassName}List?: ${subClassName}[];
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
#if($table.sub)
|
||||||
|
|
||||||
|
/** ${subTable.functionName}配置信息 */
|
||||||
|
export interface ${subClassName} extends BaseEntity {
|
||||||
|
#foreach ($column in $subTable.columns)
|
||||||
|
#set($type = "string")
|
||||||
|
#if($column.javaType == "Long" || $column.javaType == "Integer")
|
||||||
|
#set($type = "number")
|
||||||
|
#elseif($column.javaType == "Boolean")
|
||||||
|
#set($type = "boolean")
|
||||||
|
#end
|
||||||
|
/** ${column.columnComment} */
|
||||||
|
${column.javaField}?: ${type};
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -139,34 +139,55 @@
|
|||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
#if($genView)
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-view"
|
||||||
|
@click="handleViewData(scope.row)"
|
||||||
|
v-hasPermi="['${permissionPrefix}:query']"
|
||||||
|
>详情</el-button>
|
||||||
|
#end
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
v-hasPermi="['${permissionPrefix}:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
@click="handleAdd(scope.row)"
|
@click="handleAdd(scope.row)"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
v-hasPermi="['${permissionPrefix}:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
<!-- 添加或修改${functionName}对话框 -->
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
#if($table.formColNum == 2)
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
#foreach($column in $columns)
|
#foreach($column in $columns)
|
||||||
#set($field=$column.javaField)
|
#set($field=$column.javaField)
|
||||||
#if($column.insert && !$column.pk)
|
#if($column.insert && !$column.pk)
|
||||||
@@ -179,26 +200,37 @@
|
|||||||
#end
|
#end
|
||||||
#set($dictType=$column.dictType)
|
#set($dictType=$column.dictType)
|
||||||
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
|
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${treeParentCode}">
|
<el-form-item label="${comment}" prop="${treeParentCode}">
|
||||||
<treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="请选择${comment}" />
|
<treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="请选择${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "input")
|
#elseif($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<editor v-model="form.${field}" :min-height="192"/>
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
@@ -213,13 +245,17 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && $dictType)
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option label="请选择字典生成" value="" />
|
<el-option label="请选择字典生成" value="" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@@ -230,13 +266,17 @@
|
|||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
@@ -250,13 +290,17 @@
|
|||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "datetime")
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-date-picker clearable
|
<el-date-picker clearable
|
||||||
v-model="form.${field}"
|
v-model="form.${field}"
|
||||||
@@ -265,14 +309,18 @@
|
|||||||
placeholder="选择${comment}">
|
placeholder="选择${comment}">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "textarea")
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
@@ -283,9 +331,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
import Treeselect from "@riophae/vue-treeselect";
|
#if($genView)
|
||||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
|
#end
|
||||||
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "${BusinessName}",
|
name: "${BusinessName}",
|
||||||
@@ -293,6 +344,9 @@ export default {
|
|||||||
dicts: [${dicts}],
|
dicts: [${dicts}],
|
||||||
#end
|
#end
|
||||||
components: {
|
components: {
|
||||||
|
#if($genView)
|
||||||
|
${BusinessName}ViewDrawer,
|
||||||
|
#end
|
||||||
Treeselect
|
Treeselect
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -346,18 +400,18 @@ export default {
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true;
|
this.loading = true
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
this.queryParams.params = {};
|
this.queryParams.params = {}
|
||||||
#break
|
#break
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@@ -365,40 +419,40 @@ export default {
|
|||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
|
||||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
list${BusinessName}(this.queryParams).then(response => {
|
list${BusinessName}(this.queryParams).then(response => {
|
||||||
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
this.loading = false;
|
this.loading = false
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 转换${functionName}数据结构 */
|
/** 转换${functionName}数据结构 */
|
||||||
normalizer(node) {
|
normalizer(node) {
|
||||||
if (node.children && !node.children.length) {
|
if (node.children && !node.children.length) {
|
||||||
delete node.children;
|
delete node.children
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: node.${treeCode},
|
id: node.${treeCode},
|
||||||
label: node.${treeName},
|
label: node.${treeName},
|
||||||
children: node.children
|
children: node.children
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
/** 查询${functionName}下拉树结构 */
|
/** 查询${functionName}下拉树结构 */
|
||||||
getTreeselect() {
|
getTreeselect() {
|
||||||
list${BusinessName}().then(response => {
|
list${BusinessName}().then(response => {
|
||||||
this.${businessName}Options = [];
|
this.${businessName}Options = []
|
||||||
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
|
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
|
||||||
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
this.${businessName}Options.push(data);
|
this.${businessName}Options.push(data)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
cancel() {
|
cancel() {
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.reset();
|
this.reset()
|
||||||
},
|
},
|
||||||
// 表单重置
|
// 表单重置
|
||||||
reset() {
|
reset() {
|
||||||
@@ -410,61 +464,67 @@ export default {
|
|||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
};
|
}
|
||||||
this.resetForm("form");
|
this.resetForm("form")
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.getList();
|
this.getList()
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
this.daterange${AttrName} = [];
|
this.daterange${AttrName} = []
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm")
|
||||||
this.handleQuery();
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd(row) {
|
handleAdd(row) {
|
||||||
this.reset();
|
this.reset()
|
||||||
this.getTreeselect();
|
this.getTreeselect()
|
||||||
if (row != null && row.${treeCode}) {
|
if (row != null && row.${treeCode}) {
|
||||||
this.form.${treeParentCode} = row.${treeCode};
|
this.form.${treeParentCode} = row.${treeCode}
|
||||||
} else {
|
} else {
|
||||||
this.form.${treeParentCode} = 0;
|
this.form.${treeParentCode} = 0
|
||||||
}
|
}
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "添加${functionName}";
|
this.title = "添加${functionName}"
|
||||||
},
|
},
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
toggleExpandAll() {
|
toggleExpandAll() {
|
||||||
this.refreshTable = false;
|
this.refreshTable = false
|
||||||
this.isExpandAll = !this.isExpandAll;
|
this.isExpandAll = !this.isExpandAll
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.refreshTable = true;
|
this.refreshTable = true
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
#if($genView)
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
handleViewData(row) {
|
||||||
|
this.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
},
|
||||||
|
#end
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate(row) {
|
handleUpdate(row) {
|
||||||
this.reset();
|
this.reset()
|
||||||
this.getTreeselect();
|
this.getTreeselect()
|
||||||
if (row != null) {
|
if (row != null) {
|
||||||
this.form.${treeParentCode} = row.${treeCode};
|
this.form.${treeParentCode} = row.${treeParentCode}
|
||||||
}
|
}
|
||||||
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
||||||
this.form = response.data;
|
this.form = response.data
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
this.form.$column.javaField = this.form.${column.javaField}.split(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "修改${functionName}";
|
this.title = "修改${functionName}"
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
submitForm() {
|
submitForm() {
|
||||||
@@ -472,34 +532,34 @@ export default {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
this.form.$column.javaField = this.form.${column.javaField}.join(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
if (this.form.${pkColumn.javaField} != null) {
|
if (this.form.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(this.form).then(response => {
|
update${BusinessName}(this.form).then(response => {
|
||||||
this.#[[$modal]]#.msgSuccess("修改成功");
|
this.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.getList();
|
this.getList()
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(this.form).then(response => {
|
add${BusinessName}(this.form).then(response => {
|
||||||
this.#[[$modal]]#.msgSuccess("新增成功");
|
this.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.getList();
|
this.getList()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
|
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
|
||||||
return del${BusinessName}(row.${pkColumn.javaField});
|
return del${BusinessName}(row.${pkColumn.javaField})
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList()
|
||||||
this.#[[$modal]]#.msgSuccess("删除成功");
|
this.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
}).catch(() => {});
|
}).catch(() => {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="single"
|
:disabled="single"
|
||||||
@click="handleUpdate"
|
@click="handleUpdate"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
v-hasPermi="['${permissionPrefix}:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="multiple"
|
:disabled="multiple"
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
v-hasPermi="['${permissionPrefix}:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
icon="el-icon-download"
|
icon="el-icon-download"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:export']"
|
v-hasPermi="['${permissionPrefix}:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@@ -153,19 +153,28 @@
|
|||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
#if($genView)
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-view"
|
||||||
|
@click="handleViewData(scope.row)"
|
||||||
|
v-hasPermi="['${permissionPrefix}:query']"
|
||||||
|
>详情</el-button>
|
||||||
|
#end
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
v-hasPermi="['${permissionPrefix}:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
v-hasPermi="['${permissionPrefix}:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -179,9 +188,21 @@
|
|||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
<!-- 添加或修改${functionName}对话框 -->
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
#if($table.formColNum == 2)
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
#foreach($column in $columns)
|
#foreach($column in $columns)
|
||||||
#set($field=$column.javaField)
|
#set($field=$column.javaField)
|
||||||
#if($column.insert && !$column.pk)
|
#if($column.insert && !$column.pk)
|
||||||
@@ -194,22 +215,31 @@
|
|||||||
#end
|
#end
|
||||||
#set($dictType=$column.dictType)
|
#set($dictType=$column.dictType)
|
||||||
#if($column.htmlType == "input")
|
#if($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<editor v-model="form.${field}" :min-height="192"/>
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
@@ -224,13 +254,17 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && $dictType)
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option label="请选择字典生成" value="" />
|
<el-option label="请选择字典生成" value="" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@@ -241,13 +275,17 @@
|
|||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
@@ -261,13 +299,17 @@
|
|||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "datetime")
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-date-picker clearable
|
<el-date-picker clearable
|
||||||
v-model="form.${field}"
|
v-model="form.${field}"
|
||||||
@@ -276,14 +318,18 @@
|
|||||||
placeholder="请选择${comment}">
|
placeholder="请选择${comment}">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "textarea")
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
</el-row>
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
|
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
@@ -353,10 +399,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
#if($genView)
|
||||||
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
|
#end
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "${BusinessName}",
|
name: "${BusinessName}",
|
||||||
|
#if($genView)
|
||||||
|
components: { ${BusinessName}ViewDrawer },
|
||||||
|
#end
|
||||||
#if(${dicts} != '')
|
#if(${dicts} != '')
|
||||||
dicts: [${dicts}],
|
dicts: [${dicts}],
|
||||||
#end
|
#end
|
||||||
@@ -423,18 +475,18 @@ export default {
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true;
|
this.loading = true
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
this.queryParams.params = {};
|
this.queryParams.params = {}
|
||||||
#break
|
#break
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@@ -442,21 +494,21 @@ export default {
|
|||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
|
||||||
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
|
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
|
||||||
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
|
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
list${BusinessName}(this.queryParams).then(response => {
|
list${BusinessName}(this.queryParams).then(response => {
|
||||||
this.${businessName}List = response.rows;
|
this.${businessName}List = response.rows
|
||||||
this.total = response.total;
|
this.total = response.total
|
||||||
this.loading = false;
|
this.loading = false
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
cancel() {
|
cancel() {
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.reset();
|
this.reset()
|
||||||
},
|
},
|
||||||
// 表单重置
|
// 表单重置
|
||||||
reset() {
|
reset() {
|
||||||
@@ -468,27 +520,27 @@ export default {
|
|||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
};
|
}
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
this.${subclassName}List = [];
|
this.${subclassName}List = []
|
||||||
#end
|
#end
|
||||||
this.resetForm("form");
|
this.resetForm("form")
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1
|
||||||
this.getList();
|
this.getList()
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
this.daterange${AttrName} = [];
|
this.daterange${AttrName} = []
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm")
|
||||||
this.handleQuery();
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
@@ -498,27 +550,27 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.reset();
|
this.reset()
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "添加${functionName}";
|
this.title = "添加${functionName}"
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate(row) {
|
handleUpdate(row) {
|
||||||
this.reset();
|
this.reset()
|
||||||
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
|
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
|
||||||
get${BusinessName}(${pkColumn.javaField}).then(response => {
|
get${BusinessName}(${pkColumn.javaField}).then(response => {
|
||||||
this.form = response.data;
|
this.form = response.data
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
this.form.$column.javaField = this.form.${column.javaField}.split(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
this.${subclassName}List = response.data.${subclassName}List;
|
this.${subclassName}List = response.data.${subclassName}List
|
||||||
#end
|
#end
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "修改${functionName}";
|
this.title = "修改${functionName}"
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
submitForm() {
|
submitForm() {
|
||||||
@@ -526,70 +578,76 @@ export default {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
this.form.$column.javaField = this.form.${column.javaField}.join(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
this.form.${subclassName}List = this.${subclassName}List;
|
this.form.${subclassName}List = this.${subclassName}List
|
||||||
#end
|
#end
|
||||||
if (this.form.${pkColumn.javaField} != null) {
|
if (this.form.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(this.form).then(response => {
|
update${BusinessName}(this.form).then(response => {
|
||||||
this.#[[$modal]]#.msgSuccess("修改成功");
|
this.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.getList();
|
this.getList()
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(this.form).then(response => {
|
add${BusinessName}(this.form).then(response => {
|
||||||
this.#[[$modal]]#.msgSuccess("新增成功");
|
this.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.getList();
|
this.getList()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
|
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids
|
||||||
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
|
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
|
||||||
return del${BusinessName}(${pkColumn.javaField}s);
|
return del${BusinessName}(${pkColumn.javaField}s)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList()
|
||||||
this.#[[$modal]]#.msgSuccess("删除成功");
|
this.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
}).catch(() => {});
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
/** ${subTable.functionName}序号 */
|
/** ${subTable.functionName}序号 */
|
||||||
row${subClassName}Index({ row, rowIndex }) {
|
row${subClassName}Index({ row, rowIndex }) {
|
||||||
row.index = rowIndex + 1;
|
row.index = rowIndex + 1
|
||||||
},
|
},
|
||||||
/** ${subTable.functionName}添加按钮操作 */
|
/** ${subTable.functionName}添加按钮操作 */
|
||||||
handleAdd${subClassName}() {
|
handleAdd${subClassName}() {
|
||||||
let obj = {};
|
let obj = {}
|
||||||
#foreach($column in $subTable.columns)
|
#foreach($column in $subTable.columns)
|
||||||
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
||||||
#elseif($column.list && "" != $javaField)
|
#elseif($column.list && "" != $javaField)
|
||||||
obj.$column.javaField = "";
|
obj.$column.javaField = ""
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
this.${subclassName}List.push(obj);
|
this.${subclassName}List.push(obj)
|
||||||
},
|
},
|
||||||
/** ${subTable.functionName}删除按钮操作 */
|
/** ${subTable.functionName}删除按钮操作 */
|
||||||
handleDelete${subClassName}() {
|
handleDelete${subClassName}() {
|
||||||
if (this.checked${subClassName}.length == 0) {
|
if (this.checked${subClassName}.length == 0) {
|
||||||
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
|
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
|
||||||
} else {
|
} else {
|
||||||
const ${subclassName}List = this.${subclassName}List;
|
const ${subclassName}List = this.${subclassName}List
|
||||||
const checked${subClassName} = this.checked${subClassName};
|
const checked${subClassName} = this.checked${subClassName}
|
||||||
this.${subclassName}List = ${subclassName}List.filter(function(item) {
|
this.${subclassName}List = ${subclassName}List.filter(function(item) {
|
||||||
return checked${subClassName}.indexOf(item.index) == -1
|
return checked${subClassName}.indexOf(item.index) == -1
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 复选框选中数据 */
|
/** 复选框选中数据 */
|
||||||
handle${subClassName}SelectionChange(selection) {
|
handle${subClassName}SelectionChange(selection) {
|
||||||
this.checked${subClassName} = selection.map(item => item.index)
|
this.checked${subClassName} = selection.map(item => item.index)
|
||||||
},
|
},
|
||||||
|
#end
|
||||||
|
#if($genView)
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
handleViewData(row) {
|
||||||
|
this.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
},
|
||||||
#end
|
#end
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
@@ -598,5 +656,5 @@ export default {
|
|||||||
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
|
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
plain
|
plain
|
||||||
icon="Plus"
|
icon="Plus"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -136,16 +136,31 @@
|
|||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
|
#if($genView)
|
||||||
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
|
<el-button link type="primary" icon="View" @click="handleViewData(scope.row)" v-hasPermi="['${permissionPrefix}:query']">详情</el-button>
|
||||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
|
#end
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${permissionPrefix}:add']">新增</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
<!-- 添加或修改${functionName}对话框 -->
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
#if($table.formColNum == 2)
|
||||||
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" v-model="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
#foreach($column in $columns)
|
#foreach($column in $columns)
|
||||||
#set($field=$column.javaField)
|
#set($field=$column.javaField)
|
||||||
#if($column.insert && !$column.pk)
|
#if($column.insert && !$column.pk)
|
||||||
@@ -158,6 +173,7 @@
|
|||||||
#end
|
#end
|
||||||
#set($dictType=$column.dictType)
|
#set($dictType=$column.dictType)
|
||||||
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
|
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${treeParentCode}">
|
<el-form-item label="${comment}" prop="${treeParentCode}">
|
||||||
<el-tree-select
|
<el-tree-select
|
||||||
v-model="form.${treeParentCode}"
|
v-model="form.${treeParentCode}"
|
||||||
@@ -168,23 +184,33 @@
|
|||||||
check-strictly
|
check-strictly
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "input")
|
#elseif($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<editor v-model="form.${field}" :min-height="192"/>
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
@@ -199,13 +225,17 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && $dictType)
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option label="请选择字典生成" value="" />
|
<el-option label="请选择字典生成" value="" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@@ -216,13 +246,17 @@
|
|||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
@@ -236,13 +270,17 @@
|
|||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "datetime")
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-date-picker clearable
|
<el-date-picker clearable
|
||||||
v-model="form.${field}"
|
v-model="form.${field}"
|
||||||
@@ -251,14 +289,18 @@
|
|||||||
placeholder="选择${comment}">
|
placeholder="选择${comment}">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "textarea")
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
@@ -271,26 +313,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="${BusinessName}">
|
<script setup name="${BusinessName}">
|
||||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
#if($genView)
|
||||||
const { proxy } = getCurrentInstance();
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
#if(${dicts} != '')
|
|
||||||
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
|
||||||
const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
const ${businessName}List = ref([]);
|
const { proxy } = getCurrentInstance()
|
||||||
const ${businessName}Options = ref([]);
|
#if(${dicts} != '')
|
||||||
const open = ref(false);
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
const loading = ref(true);
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
const showSearch = ref(true);
|
#end
|
||||||
const title = ref("");
|
|
||||||
const isExpandAll = ref(true);
|
const ${businessName}List = ref([])
|
||||||
const refreshTable = ref(true);
|
const ${businessName}Options = ref([])
|
||||||
|
const open = ref(false)
|
||||||
|
const loading = ref(true)
|
||||||
|
const showSearch = ref(true)
|
||||||
|
const title = ref("")
|
||||||
|
const isExpandAll = ref(true)
|
||||||
|
const refreshTable = ref(true)
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
const daterange${AttrName} = ref([]);
|
const daterange${AttrName} = ref([])
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
|
||||||
@@ -299,7 +344,7 @@ const data = reactive({
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.query)
|
#if($column.query)
|
||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
@@ -318,51 +363,51 @@ const data = reactive({
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data)
|
||||||
|
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
queryParams.value.params = {};
|
queryParams.value.params = {}
|
||||||
#break
|
#break
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
|
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
list${BusinessName}(queryParams.value).then(response => {
|
list${BusinessName}(queryParams.value).then(response => {
|
||||||
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询${functionName}下拉树结构 */
|
/** 查询${functionName}下拉树结构 */
|
||||||
function getTreeselect() {
|
function getTreeselect() {
|
||||||
list${BusinessName}().then(response => {
|
list${BusinessName}().then(response => {
|
||||||
${businessName}Options.value = [];
|
${businessName}Options.value = []
|
||||||
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
|
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
|
||||||
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
|
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
${businessName}Options.value.push(data);
|
${businessName}Options.value.push(data)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消按钮
|
/** 取消按钮 */
|
||||||
function cancel() {
|
function cancel() {
|
||||||
open.value = false;
|
open.value = false
|
||||||
reset();
|
reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单重置
|
/** 表单重置 */
|
||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
@@ -372,13 +417,13 @@ function reset() {
|
|||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
};
|
}
|
||||||
proxy.resetForm("${businessName}Ref");
|
proxy.resetForm("${businessName}Ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
getList();
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
@@ -386,52 +431,59 @@ function resetQuery() {
|
|||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
daterange${AttrName}.value = [];
|
daterange${AttrName}.value = []
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
proxy.resetForm("queryRef");
|
proxy.resetForm("queryRef")
|
||||||
handleQuery();
|
handleQuery()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
function handleAdd(row) {
|
function handleAdd(row) {
|
||||||
reset();
|
reset()
|
||||||
getTreeselect();
|
getTreeselect()
|
||||||
if (row != null && row.${treeCode}) {
|
if (row != null && row.${treeCode}) {
|
||||||
form.value.${treeParentCode} = row.${treeCode};
|
form.value.${treeParentCode} = row.${treeCode}
|
||||||
} else {
|
} else {
|
||||||
form.value.${treeParentCode} = 0;
|
form.value.${treeParentCode} = 0
|
||||||
}
|
}
|
||||||
open.value = true;
|
open.value = true
|
||||||
title.value = "添加${functionName}";
|
title.value = "添加${functionName}"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
function toggleExpandAll() {
|
function toggleExpandAll() {
|
||||||
refreshTable.value = false;
|
refreshTable.value = false
|
||||||
isExpandAll.value = !isExpandAll.value;
|
isExpandAll.value = !isExpandAll.value
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
refreshTable.value = true;
|
refreshTable.value = true
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
#if($genView)
|
||||||
|
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
function handleViewData(row) {
|
||||||
|
proxy.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
async function handleUpdate(row) {
|
async function handleUpdate(row) {
|
||||||
reset();
|
reset()
|
||||||
await getTreeselect();
|
await getTreeselect()
|
||||||
if (row != null) {
|
if (row != null) {
|
||||||
form.value.${treeParentCode} = row.${treeCode};
|
form.value.${treeParentCode} = row.${treeParentCode}
|
||||||
}
|
}
|
||||||
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
||||||
form.value = response.data;
|
form.value = response.data
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
form.value.$column.javaField = form.value.${column.javaField}.split(",");
|
form.value.$column.javaField = form.value.${column.javaField}.split(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
open.value = true;
|
open.value = true
|
||||||
title.value = "修改${functionName}";
|
title.value = "修改${functionName}"
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
@@ -440,35 +492,35 @@ function submitForm() {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
form.value.$column.javaField = form.value.${column.javaField}.join(",");
|
form.value.$column.javaField = form.value.${column.javaField}.join(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
if (form.value.${pkColumn.javaField} != null) {
|
if (form.value.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(form.value).then(response => {
|
update${BusinessName}(form.value).then(() => {
|
||||||
proxy.#[[$modal]]#.msgSuccess("修改成功");
|
proxy.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
open.value = false;
|
open.value = false
|
||||||
getList();
|
getList()
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(form.value).then(response => {
|
add${BusinessName}(form.value).then(() => {
|
||||||
proxy.#[[$modal]]#.msgSuccess("新增成功");
|
proxy.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
open.value = false;
|
open.value = false
|
||||||
getList();
|
getList()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
function handleDelete(row) {
|
function handleDelete(row) {
|
||||||
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
|
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
|
||||||
return del${BusinessName}(row.${pkColumn.javaField});
|
return del${BusinessName}(row.${pkColumn.javaField})
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
getList();
|
getList()
|
||||||
proxy.#[[$modal]]#.msgSuccess("删除成功");
|
proxy.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
}).catch(() => {});
|
}).catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
getList();
|
getList()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
plain
|
plain
|
||||||
icon="Plus"
|
icon="Plus"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
icon="Edit"
|
icon="Edit"
|
||||||
:disabled="single"
|
:disabled="single"
|
||||||
@click="handleUpdate"
|
@click="handleUpdate"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:edit']"
|
v-hasPermi="['${permissionPrefix}:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
icon="Delete"
|
icon="Delete"
|
||||||
:disabled="multiple"
|
:disabled="multiple"
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:remove']"
|
v-hasPermi="['${permissionPrefix}:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
plain
|
plain
|
||||||
icon="Download"
|
icon="Download"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['${moduleName}:${businessName}:export']"
|
v-hasPermi="['${permissionPrefix}:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@@ -148,8 +148,11 @@
|
|||||||
#end
|
#end
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
|
#if($genView)
|
||||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
|
<el-button link type="primary" icon="View" @click="handleViewData(scope.row)" v-hasPermi="['${permissionPrefix}:query']">详情</el-button>
|
||||||
|
#end
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -162,9 +165,21 @@
|
|||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
<!-- 添加或修改${functionName}对话框 -->
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
#if($table.formColNum == 2)
|
||||||
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" v-model="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
#foreach($column in $columns)
|
#foreach($column in $columns)
|
||||||
#set($field=$column.javaField)
|
#set($field=$column.javaField)
|
||||||
#if($column.insert && !$column.pk)
|
#if($column.insert && !$column.pk)
|
||||||
@@ -177,22 +192,31 @@
|
|||||||
#end
|
#end
|
||||||
#set($dictType=$column.dictType)
|
#set($dictType=$column.dictType)
|
||||||
#if($column.htmlType == "input")
|
#if($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "imageUpload")
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<image-upload v-model="form.${field}"/>
|
<image-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "fileUpload")
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<file-upload v-model="form.${field}"/>
|
<file-upload v-model="form.${field}"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "editor")
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<editor v-model="form.${field}" :min-height="192"/>
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
@@ -207,13 +231,17 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "select" && $dictType)
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option label="请选择字典生成" value="" />
|
<el-option label="请选择字典生成" value="" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@@ -224,13 +252,17 @@
|
|||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox>请选择字典生成</el-checkbox>
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
@@ -244,13 +276,17 @@
|
|||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio label="1">请选择字典生成</el-radio>
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "datetime")
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-date-picker clearable
|
<el-date-picker clearable
|
||||||
v-model="form.${field}"
|
v-model="form.${field}"
|
||||||
@@ -259,14 +295,18 @@
|
|||||||
placeholder="请选择${comment}">
|
placeholder="请选择${comment}">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#elseif($column.htmlType == "textarea")
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
</el-row>
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
|
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
@@ -277,9 +317,13 @@
|
|||||||
<el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">删除</el-button>
|
<el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">删除</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
|
<el-table :data="${subclassName}List" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
|
||||||
<el-table-column type="selection" width="50" align="center" />
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
<el-table-column label="序号" align="center" prop="index" width="50"/>
|
<el-table-column label="序号" width="60">
|
||||||
|
<template #default="{ $index }">
|
||||||
|
{{ $index + 1 }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
#foreach($column in $subTable.columns)
|
#foreach($column in $subTable.columns)
|
||||||
#set($javaField=$column.javaField)
|
#set($javaField=$column.javaField)
|
||||||
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
@@ -343,33 +387,36 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="${BusinessName}">
|
<script setup name="${BusinessName}">
|
||||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
#if($genView)
|
||||||
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
|
#end
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance()
|
||||||
#if(${dicts} != '')
|
#if(${dicts} != '')
|
||||||
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
#end
|
#end
|
||||||
|
|
||||||
const ${businessName}List = ref([]);
|
const ${businessName}List = ref([])
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
const ${subclassName}List = ref([]);
|
const ${subclassName}List = ref([])
|
||||||
#end
|
#end
|
||||||
const open = ref(false);
|
const open = ref(false)
|
||||||
const loading = ref(true);
|
const loading = ref(true)
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true)
|
||||||
const ids = ref([]);
|
const ids = ref([])
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
const checked${subClassName} = ref([]);
|
const checked${subClassName} = ref([])
|
||||||
#end
|
#end
|
||||||
const single = ref(true);
|
const single = ref(true)
|
||||||
const multiple = ref(true);
|
const multiple = ref(true)
|
||||||
const total = ref(0);
|
const total = ref(0)
|
||||||
const title = ref("");
|
const title = ref("")
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
const daterange${AttrName} = ref([]);
|
const daterange${AttrName} = ref([])
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
|
|
||||||
@@ -380,7 +427,7 @@ const data = reactive({
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.query)
|
#if($column.query)
|
||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
@@ -399,42 +446,42 @@ const data = reactive({
|
|||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data)
|
||||||
|
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
queryParams.value.params = {};
|
queryParams.value.params = {}
|
||||||
#break
|
#break
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
|
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
list${BusinessName}(queryParams.value).then(response => {
|
list${BusinessName}(queryParams.value).then(response => {
|
||||||
${businessName}List.value = response.rows;
|
${businessName}List.value = response.rows
|
||||||
total.value = response.total;
|
total.value = response.total
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消按钮
|
/** 取消按钮 */
|
||||||
function cancel() {
|
function cancel() {
|
||||||
open.value = false;
|
open.value = false
|
||||||
reset();
|
reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单重置
|
/** 表单重置 */
|
||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
@@ -444,17 +491,17 @@ function reset() {
|
|||||||
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
};
|
}
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
${subclassName}List.value = [];
|
${subclassName}List.value = []
|
||||||
#end
|
#end
|
||||||
proxy.resetForm("${businessName}Ref");
|
proxy.resetForm("${businessName}Ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1
|
||||||
getList();
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
@@ -462,44 +509,44 @@ function resetQuery() {
|
|||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
daterange${AttrName}.value = [];
|
daterange${AttrName}.value = []
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
proxy.resetForm("queryRef");
|
proxy.resetForm("queryRef")
|
||||||
handleQuery();
|
handleQuery()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多选框选中数据
|
/** 多选框选中数据 */
|
||||||
function handleSelectionChange(selection) {
|
function handleSelectionChange(selection) {
|
||||||
ids.value = selection.map(item => item.${pkColumn.javaField});
|
ids.value = selection.map(item => item.${pkColumn.javaField})
|
||||||
single.value = selection.length != 1;
|
single.value = selection.length != 1
|
||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
reset();
|
reset()
|
||||||
open.value = true;
|
open.value = true
|
||||||
title.value = "添加${functionName}";
|
title.value = "添加${functionName}"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
function handleUpdate(row) {
|
function handleUpdate(row) {
|
||||||
reset();
|
reset()
|
||||||
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
|
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
|
||||||
get${BusinessName}(_${pkColumn.javaField}).then(response => {
|
get${BusinessName}(_${pkColumn.javaField}).then(response => {
|
||||||
form.value = response.data;
|
form.value = response.data
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
form.value.$column.javaField = form.value.${column.javaField}.split(",");
|
form.value.$column.javaField = form.value.${column.javaField}.split(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
${subclassName}List.value = response.data.${subclassName}List;
|
${subclassName}List.value = response.data.${subclassName}List
|
||||||
#end
|
#end
|
||||||
open.value = true;
|
open.value = true
|
||||||
title.value = "修改${functionName}";
|
title.value = "修改${functionName}"
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
@@ -508,68 +555,63 @@ function submitForm() {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.htmlType == "checkbox")
|
#if($column.htmlType == "checkbox")
|
||||||
form.value.$column.javaField = form.value.${column.javaField}.join(",");
|
form.value.$column.javaField = form.value.${column.javaField}.join(",")
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
form.value.${subclassName}List = ${subclassName}List.value;
|
form.value.${subclassName}List = ${subclassName}List.value
|
||||||
#end
|
#end
|
||||||
if (form.value.${pkColumn.javaField} != null) {
|
if (form.value.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(form.value).then(response => {
|
update${BusinessName}(form.value).then(() => {
|
||||||
proxy.#[[$modal]]#.msgSuccess("修改成功");
|
proxy.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
open.value = false;
|
open.value = false
|
||||||
getList();
|
getList()
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(form.value).then(response => {
|
add${BusinessName}(form.value).then(() => {
|
||||||
proxy.#[[$modal]]#.msgSuccess("新增成功");
|
proxy.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
open.value = false;
|
open.value = false
|
||||||
getList();
|
getList()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
function handleDelete(row) {
|
function handleDelete(row) {
|
||||||
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
|
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value
|
||||||
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
|
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
|
||||||
return del${BusinessName}(_${pkColumn.javaField}s);
|
return del${BusinessName}(_${pkColumn.javaField}s)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
getList();
|
getList()
|
||||||
proxy.#[[$modal]]#.msgSuccess("删除成功");
|
proxy.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
}).catch(() => {});
|
}).catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
/** ${subTable.functionName}序号 */
|
|
||||||
function row${subClassName}Index({ row, rowIndex }) {
|
|
||||||
row.index = rowIndex + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ${subTable.functionName}添加按钮操作 */
|
/** ${subTable.functionName}添加按钮操作 */
|
||||||
function handleAdd${subClassName}() {
|
function handleAdd${subClassName}() {
|
||||||
let obj = {};
|
let obj = {}
|
||||||
#foreach($column in $subTable.columns)
|
#foreach($column in $subTable.columns)
|
||||||
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
||||||
#elseif($column.list && "" != $javaField)
|
#elseif($column.list && "" != $javaField)
|
||||||
obj.$column.javaField = "";
|
obj.$column.javaField = undefined
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
${subclassName}List.value.push(obj);
|
${subclassName}List.value.push(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ${subTable.functionName}删除按钮操作 */
|
/** ${subTable.functionName}删除按钮操作 */
|
||||||
function handleDelete${subClassName}() {
|
function handleDelete${subClassName}() {
|
||||||
if (checked${subClassName}.value.length == 0) {
|
if (checked${subClassName}.value.length == 0) {
|
||||||
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
|
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
|
||||||
} else {
|
} else {
|
||||||
const ${subclassName}s = ${subclassName}List.value;
|
const ${subclassName}s = ${subclassName}List.value
|
||||||
const checked${subClassName}s = checked${subClassName}.value;
|
const checked${subClassName}s = checked${subClassName}.value
|
||||||
${subclassName}List.value = ${subclassName}s.filter(function(item) {
|
${subclassName}List.value = ${subclassName}s.filter(function(item) {
|
||||||
return checked${subClassName}s.indexOf(item.index) == -1
|
return checked${subClassName}s.indexOf(item.index) == -1
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,6 +620,13 @@ function handle${subClassName}SelectionChange(selection) {
|
|||||||
checked${subClassName}.value = selection.map(item => item.index)
|
checked${subClassName}.value = selection.map(item => item.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
#if($genView)
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
function handleViewData(row) {
|
||||||
|
proxy.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
}
|
||||||
|
|
||||||
#end
|
#end
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
function handleExport() {
|
function handleExport() {
|
||||||
@@ -586,5 +635,5 @@ function handleExport() {
|
|||||||
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
|
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
|
||||||
}
|
}
|
||||||
|
|
||||||
getList();
|
getList()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
如果使用的是RuoYi-Vue3前端,那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer title="${functionName}详情" v-model="visible" direction="rtl" size="60%" append-to-body :before-close="handleClose" class="detail-drawer">
|
||||||
|
<div v-loading="loading" class="drawer-content">
|
||||||
|
<h4 class="section-header">基本信息</h4>
|
||||||
|
#set($i = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if(!$column.pk && $column.list)
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#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($i % 2 == 0)
|
||||||
|
<el-row :gutter="20" class="mb8">
|
||||||
|
#end
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="info-item">
|
||||||
|
<label class="info-label">${comment}:</label>
|
||||||
|
<span class="info-value plaintext">
|
||||||
|
#if("" != $dictType)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
<dict-tag :options="${dictType}" :value="info.${javaField} ? info.${javaField}.split(',') : []" />
|
||||||
|
#else
|
||||||
|
<dict-tag :options="${dictType}" :value="info.${javaField}" />
|
||||||
|
#end
|
||||||
|
#elseif($column.htmlType == "datetime")
|
||||||
|
{{ parseTime(info.${javaField}, '{y}-{m}-{d}') }}
|
||||||
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<image-preview :src="info.${javaField}" :width="60" :height="60" />
|
||||||
|
#else
|
||||||
|
{{ info.${javaField} }}
|
||||||
|
#end
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
#set($i = $i + 1)
|
||||||
|
#if($i % 2 == 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($i % 2 != 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="${BusinessName}ViewDrawer">
|
||||||
|
import { get${BusinessName} } from '@/api/${moduleName}/${businessName}'
|
||||||
|
|
||||||
|
#if(${dicts} != '')
|
||||||
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
|
#end
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const info = reactive({})
|
||||||
|
|
||||||
|
const open = async (${pkColumn.javaField}) => {
|
||||||
|
visible.value = true
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await get${BusinessName}(${pkColumn.javaField})
|
||||||
|
Object.assign(info, res.data || {})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取${functionName}信息失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
visible.value = false
|
||||||
|
Object.keys(info).forEach(key => delete info[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,528 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if($column.query)
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
#if($column.htmlType == "input")
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.${column.javaField}"
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-date-picker clearable
|
||||||
|
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}" style="width: 308px">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="daterange${AttrName}"
|
||||||
|
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="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
icon="Sort"
|
||||||
|
@click="toggleExpandAll"
|
||||||
|
>展开/折叠</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-if="refreshTable"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="${businessName}List"
|
||||||
|
row-key="${treeCode}"
|
||||||
|
:default-expand-all="isExpandAll"
|
||||||
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||||
|
>
|
||||||
|
#foreach($column in $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)
|
||||||
|
#elseif($column.list && $column.htmlType == "datetime")
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && $column.htmlType == "imageUpload")
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && "" != $column.dictType)
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||||
|
<template #default="scope">
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
|
||||||
|
#else
|
||||||
|
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
|
||||||
|
#end
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#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 #default="scope">
|
||||||
|
#if($genView)
|
||||||
|
<el-button link type="primary" icon="View" @click="handleViewData(scope.row)" v-hasPermi="['${permissionPrefix}:query']">详情</el-button>
|
||||||
|
#end
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${permissionPrefix}:add']">新增</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
|
#if($table.formColNum == 2)
|
||||||
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" v-model="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#set($field=$column.javaField)
|
||||||
|
#if($column.insert && !$column.pk)
|
||||||
|
#if(($column.usableColumn) || (!$column.superColumn))
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${treeParentCode}">
|
||||||
|
<el-tree-select
|
||||||
|
v-model="form.${treeParentCode}"
|
||||||
|
:data="${businessName}Options"
|
||||||
|
:props="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
|
||||||
|
value-key="${treeCode}"
|
||||||
|
placeholder="请选择${comment}"
|
||||||
|
check-strictly
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<image-upload v-model="form.${field}"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<file-upload v-model="form.${field}"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="${comment}">
|
||||||
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-checkbox-group v-model="form.${field}">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value">
|
||||||
|
{{dict.label}}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-checkbox-group v-model="form.${field}">
|
||||||
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-radio-group v-model="form.${field}">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-radio-group v-model="form.${field}">
|
||||||
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-date-picker clearable
|
||||||
|
v-model="form.${field}"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="选择${comment}">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="${BusinessName}">
|
||||||
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
#if($genView)
|
||||||
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
|
#end
|
||||||
|
import type { ${ClassName}, ${BusinessName}QueryParams } from "@/types/api/${moduleName}/${businessName}"
|
||||||
|
import type { TreeSelect } from '@/types/api/common'
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
#if(${dicts} != '')
|
||||||
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
|
#end
|
||||||
|
|
||||||
|
const ${businessName}List = ref<any[]>([])
|
||||||
|
const ${businessName}Options = ref<TreeSelect[]>([])
|
||||||
|
const open = ref<boolean>(false)
|
||||||
|
const loading = ref<boolean>(true)
|
||||||
|
const showSearch = ref<boolean>(true)
|
||||||
|
const title = ref<string>("")
|
||||||
|
const isExpandAll = ref<boolean>(true)
|
||||||
|
const refreshTable = ref<boolean>(true)
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
const daterange${AttrName} = ref([])
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
form: {} as ${ClassName},
|
||||||
|
queryParams: {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.query)
|
||||||
|
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
} as ${BusinessName}QueryParams,
|
||||||
|
rules: {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.required)
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
$column.javaField: [
|
||||||
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
|
]#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data)
|
||||||
|
|
||||||
|
/** 查询${functionName}列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
queryParams.value.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 != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
list${BusinessName}(queryParams.value).then(response => {
|
||||||
|
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询${functionName}下拉树结构 */
|
||||||
|
function getTreeselect() {
|
||||||
|
list${BusinessName}().then(response => {
|
||||||
|
${businessName}Options.value = []
|
||||||
|
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
|
||||||
|
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
|
||||||
|
${businessName}Options.value.push(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
function cancel() {
|
||||||
|
open.value = false
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
|
#else
|
||||||
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
proxy.resetForm("${businessName}Ref")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
daterange${AttrName}.value = []
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
proxy.resetForm("queryRef")
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function handleAdd(row: ${ClassName}) {
|
||||||
|
reset()
|
||||||
|
getTreeselect()
|
||||||
|
if (row != null && row.${treeCode}) {
|
||||||
|
form.value.${treeParentCode} = row.${treeCode}
|
||||||
|
} else {
|
||||||
|
form.value.${treeParentCode} = 0
|
||||||
|
}
|
||||||
|
open.value = true
|
||||||
|
title.value = "添加${functionName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
function toggleExpandAll() {
|
||||||
|
refreshTable.value = false
|
||||||
|
isExpandAll.value = !isExpandAll.value
|
||||||
|
nextTick(() => {
|
||||||
|
refreshTable.value = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#if($genView)
|
||||||
|
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
function handleViewData(row: ${ClassName}) {
|
||||||
|
proxy.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
async function handleUpdate(row: ${ClassName}) {
|
||||||
|
reset()
|
||||||
|
await getTreeselect()
|
||||||
|
if (row != null) {
|
||||||
|
form.value.${treeParentCode} = row.${treeParentCode}
|
||||||
|
}
|
||||||
|
get${BusinessName}(row.${pkColumn.javaField}!).then(response => {
|
||||||
|
form.value = response.data
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
form.value.$column.javaField = form.value.${column.javaField}.split(",")
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
open.value = true
|
||||||
|
title.value = "修改${functionName}"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.#[[$]]#refs["${businessName}Ref"].validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
form.value.$column.javaField = form.value.${column.javaField}.join(",")
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
if (form.value.${pkColumn.javaField} != null) {
|
||||||
|
update${BusinessName}(form.value).then(() => {
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
|
open.value = false
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
add${BusinessName}(form.value).then(() => {
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
|
open.value = false
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
function handleDelete(row: ${ClassName}) {
|
||||||
|
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
|
||||||
|
return del${BusinessName}(row.${pkColumn.javaField}!)
|
||||||
|
}).then(() => {
|
||||||
|
getList()
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
getList()
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,644 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if($column.query)
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
#if($column.htmlType == "input")
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.${column.javaField}"
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
|
||||||
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
|
<el-date-picker clearable
|
||||||
|
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}" style="width: 308px">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="daterange${AttrName}"
|
||||||
|
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="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['${permissionPrefix}:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="Edit"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['${permissionPrefix}:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="Delete"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['${permissionPrefix}:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="Download"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['${permissionPrefix}:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
#foreach($column in $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)
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" />
|
||||||
|
#elseif($column.list && $column.htmlType == "datetime")
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && $column.htmlType == "imageUpload")
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && "" != $column.dictType)
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||||
|
<template #default="scope">
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
|
||||||
|
#else
|
||||||
|
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
|
||||||
|
#end
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && "" != $javaField)
|
||||||
|
<el-table-column label="${comment}" align="center" prop="${javaField}" />
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
#if($genView)
|
||||||
|
<el-button link type="primary" icon="View" @click="handleViewData(scope.row)" v-hasPermi="['${permissionPrefix}:query']">详情</el-button>
|
||||||
|
#end
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
#if($genView)
|
||||||
|
<!-- ${functionName}详情抽屉 -->
|
||||||
|
<${businessName}-view-drawer ref="${businessName}ViewRef" />
|
||||||
|
#end
|
||||||
|
<!-- 添加或修改${functionName}对话框 -->
|
||||||
|
#if($table.formColNum == 2)
|
||||||
|
#set($dialogWidth = "800px")
|
||||||
|
#elseif($table.formColNum == 3)
|
||||||
|
#set($dialogWidth = "1100px")
|
||||||
|
#else
|
||||||
|
#set($dialogWidth = "500px")
|
||||||
|
#end
|
||||||
|
<el-dialog :title="title" v-model="open" width="${dialogWidth}" append-to-body>
|
||||||
|
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#set($field=$column.javaField)
|
||||||
|
#if($column.insert && !$column.pk)
|
||||||
|
#if(($column.usableColumn) || (!$column.superColumn))
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#if($column.htmlType == "input")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<image-upload v-model="form.${field}"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "fileUpload")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<file-upload v-model="form.${field}"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "editor")
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="${comment}">
|
||||||
|
<editor v-model="form.${field}" :min-height="192"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:value="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:value="dict.value"
|
||||||
|
#end
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "select" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-checkbox-group v-model="form.${field}">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value">
|
||||||
|
{{dict.label}}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-checkbox-group v-model="form.${field}">
|
||||||
|
<el-checkbox>请选择字典生成</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-radio-group v-model="form.${field}">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in ${dictType}"
|
||||||
|
:key="dict.value"
|
||||||
|
#if($column.javaType == "Integer" || $column.javaType == "Long")
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
#else
|
||||||
|
:label="dict.value"
|
||||||
|
#end
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-radio-group v-model="form.${field}">
|
||||||
|
<el-radio label="1">请选择字典生成</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "datetime")
|
||||||
|
<el-col :span="${colSpan}">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-date-picker clearable
|
||||||
|
v-model="form.${field}"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择${comment}">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#elseif($column.htmlType == "textarea")
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
|
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</el-row>
|
||||||
|
#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="Plus" @click="handleAdd${subClassName}">添加</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-table :data="${subclassName}List" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
|
||||||
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
|
<el-table-column label="序号" width="60">
|
||||||
|
<template #default="{ $index }">
|
||||||
|
{{ $index + 1 }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#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 && $column.htmlType == "input")
|
||||||
|
<el-table-column label="$comment" prop="${javaField}" width="150">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && $column.htmlType == "datetime")
|
||||||
|
<el-table-column label="$comment" prop="${javaField}" width="240">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-date-picker clearable
|
||||||
|
v-model="scope.row.$javaField"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择$comment">
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
|
||||||
|
<el-table-column label="$comment" prop="${javaField}" width="150">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in $column.dictType"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
|
||||||
|
<el-table-column label="$comment" prop="${javaField}" width="150">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
|
||||||
|
<el-option label="请选择字典生成" value="" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</el-table>
|
||||||
|
#end
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="${BusinessName}">
|
||||||
|
#if($table.sub)
|
||||||
|
import type { ${ClassName}, ${subClassName}, ${BusinessName}QueryParams } from "@/types/api/${moduleName}/${businessName}"
|
||||||
|
#else
|
||||||
|
import type { ${ClassName}, ${BusinessName}QueryParams } from "@/types/api/${moduleName}/${businessName}"
|
||||||
|
#end
|
||||||
|
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
#if($genView)
|
||||||
|
import ${BusinessName}ViewDrawer from "./view"
|
||||||
|
#end
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
#if(${dicts} != '')
|
||||||
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
|
#end
|
||||||
|
|
||||||
|
const ${businessName}List = ref<${ClassName}[]>([])
|
||||||
|
#if($table.sub)
|
||||||
|
const ${subclassName}List = ref([])
|
||||||
|
#end
|
||||||
|
const open = ref<boolean>(false)
|
||||||
|
const loading = ref<boolean>(true)
|
||||||
|
const showSearch = ref<boolean>(true)
|
||||||
|
const ids = ref<number[]>([])
|
||||||
|
#if($table.sub)
|
||||||
|
const checked${subClassName} = ref([])
|
||||||
|
#end
|
||||||
|
const single = ref<boolean>(true)
|
||||||
|
const multiple = ref<boolean>(true)
|
||||||
|
const total = ref<number>(0)
|
||||||
|
const title = ref<string>("")
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
const daterange${AttrName} = ref<string[]>([])
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
form: {} as ${ClassName},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.query)
|
||||||
|
$column.javaField: undefined#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
} as ${BusinessName}QueryParams,
|
||||||
|
rules: {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.required)
|
||||||
|
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
||||||
|
#if($parentheseIndex != -1)
|
||||||
|
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
||||||
|
#else
|
||||||
|
#set($comment=$column.columnComment)
|
||||||
|
#end
|
||||||
|
$column.javaField: [
|
||||||
|
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
|
||||||
|
]#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data)
|
||||||
|
|
||||||
|
/** 查询${functionName}列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
queryParams.value.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 != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
|
||||||
|
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
|
||||||
|
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
list${BusinessName}(queryParams.value).then(response => {
|
||||||
|
${businessName}List.value = response.rows
|
||||||
|
total.value = response.total
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
function cancel() {
|
||||||
|
open.value = false
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
$column.javaField: []#if($foreach.count != $columns.size()),#end
|
||||||
|
#else
|
||||||
|
$column.javaField: null#if($foreach.count != $columns.size()),#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
#if($table.sub)
|
||||||
|
${subclassName}List.value = []
|
||||||
|
#end
|
||||||
|
proxy.resetForm("${businessName}Ref")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
queryParams.value.pageNum = 1
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
|
daterange${AttrName}.value = []
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
proxy.resetForm("queryRef")
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
function handleSelectionChange(selection: ${ClassName}[]) {
|
||||||
|
ids.value = selection.map(item => item.${pkColumn.javaField})
|
||||||
|
single.value = selection.length != 1
|
||||||
|
multiple.value = !selection.length
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function handleAdd() {
|
||||||
|
reset()
|
||||||
|
open.value = true
|
||||||
|
title.value = "添加${functionName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
function handleUpdate(row: ${ClassName}) {
|
||||||
|
reset()
|
||||||
|
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value[0]
|
||||||
|
get${BusinessName}(_${pkColumn.javaField}).then(response => {
|
||||||
|
form.value = response.data
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
form.value.$column.javaField = form.value.${column.javaField}.split(",")
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($table.sub)
|
||||||
|
${subclassName}List.value = response.data?.${subclassName}List ?? []
|
||||||
|
#end
|
||||||
|
open.value = true
|
||||||
|
title.value = "修改${functionName}"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.#[[$]]#refs["${businessName}Ref"].validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
form.value.$column.javaField = form.value.${column.javaField}.join(",")
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($table.sub)
|
||||||
|
form.value.${subclassName}List = ${subclassName}List.value
|
||||||
|
#end
|
||||||
|
if (form.value.${pkColumn.javaField} != null) {
|
||||||
|
update${BusinessName}(form.value).then(() => {
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("修改成功")
|
||||||
|
open.value = false
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
add${BusinessName}(form.value).then(() => {
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("新增成功")
|
||||||
|
open.value = false
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
function handleDelete(row: ${ClassName}) {
|
||||||
|
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value
|
||||||
|
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
|
||||||
|
return del${BusinessName}(_${pkColumn.javaField}s)
|
||||||
|
}).then(() => {
|
||||||
|
getList()
|
||||||
|
proxy.#[[$modal]]#.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
#if($table.sub)
|
||||||
|
/** ${subTable.functionName}添加按钮操作 */
|
||||||
|
function handleAdd${subClassName}() {
|
||||||
|
let obj: ${subClassName} = {}
|
||||||
|
#foreach($column in $subTable.columns)
|
||||||
|
#if($column.pk || $column.javaField == ${subTableFkclassName})
|
||||||
|
#elseif($column.list && "" != $javaField)
|
||||||
|
obj.$column.javaField = undefined
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
${subclassName}List.value.push(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ${subTable.functionName}删除按钮操作 */
|
||||||
|
function handleDelete${subClassName}() {
|
||||||
|
if (checked${subClassName}.value.length == 0) {
|
||||||
|
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
|
||||||
|
} else {
|
||||||
|
const ${subclassName}s = ${subclassName}List.value
|
||||||
|
const checked${subClassName}s = checked${subClassName}.value
|
||||||
|
${subclassName}List.value = ${subclassName}s.filter(function(item: any) {
|
||||||
|
return checked${subClassName}s.indexOf(item.index) == -1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 复选框选中数据 */
|
||||||
|
function handle${subClassName}SelectionChange(selection: any[]) {
|
||||||
|
checked${subClassName}.value = selection.map(item => item.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
#if($genView)
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
function handleViewData(row: ${ClassName}) {
|
||||||
|
proxy.#[[$]]#refs["${businessName}ViewRef"].open(row.${pkColumn.javaField})
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
function handleExport() {
|
||||||
|
proxy.download('${moduleName}/${businessName}/export', {
|
||||||
|
...queryParams.value
|
||||||
|
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
|
||||||
|
}
|
||||||
|
|
||||||
|
getList()
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer title="${functionName}详情" v-model="visible" direction="rtl" size="60%" append-to-body :before-close="handleClose" class="detail-drawer">
|
||||||
|
<div v-loading="loading" class="drawer-content">
|
||||||
|
<h4 class="section-header">基本信息</h4>
|
||||||
|
#set($i = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if(!$column.pk && $column.list)
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#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($i % 2 == 0)
|
||||||
|
<el-row :gutter="20" class="mb8">
|
||||||
|
#end
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="info-item">
|
||||||
|
<label class="info-label">${comment}:</label>
|
||||||
|
<span class="info-value plaintext">
|
||||||
|
#if("" != $dictType)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
<dict-tag :options="${dictType}" :value="info.${javaField} ? info.${javaField}.split(',') : []" />
|
||||||
|
#else
|
||||||
|
<dict-tag :options="${dictType}" :value="info.${javaField}" />
|
||||||
|
#end
|
||||||
|
#elseif($column.htmlType == "datetime")
|
||||||
|
{{ parseTime(info.${javaField}, '{y}-{m}-{d}') }}
|
||||||
|
#elseif($column.htmlType == "imageUpload")
|
||||||
|
<image-preview :src="info.${javaField}" :width="60" :height="60" />
|
||||||
|
#else
|
||||||
|
{{ info.${javaField} }}
|
||||||
|
#end
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
#set($i = $i + 1)
|
||||||
|
#if($i % 2 == 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($i % 2 != 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="${BusinessName}ViewDrawer">
|
||||||
|
import type { ${ClassName} } from "@/types/api/${moduleName}/${businessName}"
|
||||||
|
import { get${BusinessName} } from '@/api/${moduleName}/${businessName}'
|
||||||
|
#if(${dicts} != '')
|
||||||
|
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||||
|
|
||||||
|
const { ${dictsNoSymbol} } = useDict(${dicts})
|
||||||
|
#end
|
||||||
|
|
||||||
|
const visible = ref<boolean>(false)
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
const info = reactive<Partial<${ClassName}>>({})
|
||||||
|
|
||||||
|
const open = async (#if($pkColumn.javaType == "Long" || $pkColumn.javaType == "Integer")${pkColumn.javaField}: number#else${pkColumn.javaField}: string#end): Promise<void> => {
|
||||||
|
visible.value = true
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await get${BusinessName}(${pkColumn.javaField})
|
||||||
|
Object.assign(info, res.data ?? {})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取${functionName}信息失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = (): void => {
|
||||||
|
visible.value = false
|
||||||
|
Object.keys(info).forEach(key => delete (info as any)[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer title="${functionName}详情" :visible.sync="visible" direction="rtl" size="60%" append-to-body :before-close="handleClose" custom-class="detail-drawer">
|
||||||
|
<div v-loading="loading" class="drawer-content">
|
||||||
|
<h4 class="section-header">基本信息</h4>
|
||||||
|
#set($i = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if(!$column.pk && $column.list)
|
||||||
|
#set($dictType=$column.dictType)
|
||||||
|
#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($i % 2 == 0)
|
||||||
|
<el-row :gutter="20" class="mb8">
|
||||||
|
#end
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="info-item">
|
||||||
|
<label class="info-label">${comment}:</label>
|
||||||
|
<span class="info-value plaintext">
|
||||||
|
#if("" != $dictType)
|
||||||
|
#if($column.htmlType == "checkbox")
|
||||||
|
<dict-tag :options="dict.type.${dictType}" :value="info.${javaField} ? info.${javaField}.split(',') : []" />
|
||||||
|
#else
|
||||||
|
<dict-tag :options="dict.type.${dictType}" :value="info.${javaField}" />
|
||||||
|
#end
|
||||||
|
#elseif($column.htmlType == "datetime")
|
||||||
|
{{ parseTime(info.${javaField}, '{y}-{m}-{d}') }}
|
||||||
|
#else
|
||||||
|
{{ info.${javaField} }}
|
||||||
|
#end
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
#set($i = $i + 1)
|
||||||
|
#if($i % 2 == 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($i % 2 != 0)
|
||||||
|
</el-row>
|
||||||
|
#end
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { get${BusinessName} } from '@/api/${moduleName}/${businessName}'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: '${BusinessName}ViewDrawer',
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if("" != $column.dictType)
|
||||||
|
#set($hasDicts = true)
|
||||||
|
#break
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if($hasDicts)
|
||||||
|
dicts: [#foreach($column in $columns)#if("" != $column.dictType)'${column.dictType}'#if($foreach.hasNext), #end#end#end],
|
||||||
|
#end
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
info: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open(${pkColumn.javaField}) {
|
||||||
|
this.visible = true
|
||||||
|
this.loading = true
|
||||||
|
get${BusinessName}(${pkColumn.javaField}).then(res => {
|
||||||
|
this.info = res.data || {}
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -12,12 +12,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
|
|
||||||
<resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
|
<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" />
|
<collection property="${subclassName}List" ofType="${subClassName}" column="${pkColumn.columnName}" select="select${subClassName}List" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<resultMap type="${subClassName}" id="${subClassName}Result">
|
<resultMap type="${subClassName}" id="${subClassName}Result">
|
||||||
#foreach ($column in $subTable.columns)
|
#foreach ($column in $subTable.columns)
|
||||||
<result property="${column.javaField}" column="sub_${column.columnName}" />
|
<result property="${column.javaField}" column="${column.columnName}" />
|
||||||
#end
|
#end
|
||||||
</resultMap>
|
</resultMap>
|
||||||
#end
|
#end
|
||||||
@@ -63,14 +63,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<include refid="select${ClassName}Vo"/>
|
<include refid="select${ClassName}Vo"/>
|
||||||
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
|
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
|
||||||
#elseif($table.sub)
|
#elseif($table.sub)
|
||||||
select#foreach($column in $columns) a.$column.columnName#if($foreach.count != $columns.size()),#end#end,
|
select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end
|
||||||
#foreach($column in $subTable.columns) b.$column.columnName as sub_$column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
|
from ${tableName}
|
||||||
|
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
|
||||||
from ${tableName} a
|
|
||||||
left join ${subTableName} b on b.${subTableFkName} = a.${pkColumn.columnName}
|
|
||||||
where a.${pkColumn.columnName} = #{${pkColumn.javaField}}
|
|
||||||
#end
|
#end
|
||||||
</select>
|
</select>
|
||||||
|
#if($table.sub)
|
||||||
|
|
||||||
|
<select id="select${subClassName}List" resultMap="${subClassName}Result">
|
||||||
|
select#foreach ($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
|
||||||
|
from ${subTableName}
|
||||||
|
where ${subTableFkName} = #{${subTableFkName}}
|
||||||
|
</select>
|
||||||
|
#end
|
||||||
|
|
||||||
<insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
|
<insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
|
||||||
insert into ${tableName}
|
insert into ${tableName}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.6</version>
|
<version>3.9.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
// // 集群配置
|
// // 集群配置
|
||||||
// prop.put("org.quartz.jobStore.isClustered", "true");
|
// prop.put("org.quartz.jobStore.isClustered", "true");
|
||||||
// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
||||||
// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
|
// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "10");
|
||||||
// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
|
// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
|
||||||
//
|
//
|
||||||
// // sqlserver 启用
|
// // sqlserver 启用
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public class SysJobController extends BaseController
|
|||||||
@PreAuthorize("@ss.hasPermi('monitor:job:remove')")
|
@PreAuthorize("@ss.hasPermi('monitor:job:remove')")
|
||||||
@Log(title = "定时任务", businessType = BusinessType.DELETE)
|
@Log(title = "定时任务", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{jobIds}")
|
@DeleteMapping("/{jobIds}")
|
||||||
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
|
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException
|
||||||
{
|
{
|
||||||
jobService.deleteJobByIds(jobIds);
|
jobService.deleteJobByIds(jobIds);
|
||||||
return success();
|
return success();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.ruoyi.quartz.domain;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
@@ -44,10 +45,12 @@ public class SysJobLog extends BaseEntity
|
|||||||
private String exceptionInfo;
|
private String exceptionInfo;
|
||||||
|
|
||||||
/** 开始时间 */
|
/** 开始时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
|
||||||
/** 停止时间 */
|
/** 结束时间 */
|
||||||
private Date stopTime;
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
public Long getJobLogId()
|
public Long getJobLogId()
|
||||||
{
|
{
|
||||||
@@ -129,14 +132,14 @@ public class SysJobLog extends BaseEntity
|
|||||||
this.startTime = startTime;
|
this.startTime = startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getStopTime()
|
public Date getEndTime()
|
||||||
{
|
{
|
||||||
return stopTime;
|
return endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStopTime(Date stopTime)
|
public void setEndTime(Date endTime)
|
||||||
{
|
{
|
||||||
this.stopTime = stopTime;
|
this.endTime = endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -149,7 +152,7 @@ public class SysJobLog extends BaseEntity
|
|||||||
.append("status", getStatus())
|
.append("status", getStatus())
|
||||||
.append("exceptionInfo", getExceptionInfo())
|
.append("exceptionInfo", getExceptionInfo())
|
||||||
.append("startTime", getStartTime())
|
.append("startTime", getStartTime())
|
||||||
.append("stopTime", getStopTime())
|
.append("stopTime", getEndTime())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user