Compare commits

...

127 Commits

Author SHA1 Message Date
RuoYi 69256940df 若依 3.2 2020-10-10 09:38:21 +08:00
RuoYi b9f686be53 升级druid到最新版本v1.2.1 2020-10-09 11:45:33 +08:00
RuoYi 521ff51238 升级fastjson到最新版1.2.74 2020-10-09 11:45:06 +08:00
若依 f67c97e095 !102 rouyi.js中添加日期范围方法dateRange获取bug修复
Merge pull request !102 from zora/master
2020-10-09 11:37:18 +08:00
RuoYi dd721ff894 修正定时任务执行一次权限标识 2020-10-07 13:36:55 +08:00
RuoYi ae4290bdda 修复页签关闭所有固定标签路由不刷新问题 2020-10-03 20:05:24 +08:00
RuoYi c19fec2cf8 格式化代码 2020-10-03 20:05:06 +08:00
RuoYi 669c42795a 表单构建布局型组件新增按钮 2020-10-03 17:47:24 +08:00
RuoYi 0d79f10c2f jna指定版本 2020-10-03 11:43:23 +08:00
RuoYi d3595cd930 修正菜单提示信息错误 2020-10-03 11:15:18 +08:00
shizhenwei 5b0525d05c [修改]此工具类应使用参数dateRange而非bind在model上的dateRange 2020-09-27 13:22:23 +08:00
RuoYi fb07677c32 左侧菜单文字过长显示省略号 2020-09-24 19:21:55 +08:00
RuoYi a82a3d9465 升级oshi到最新版本v5.2.5 2020-09-22 18:25:58 +08:00
RuoYi 28bceda630 修正文字错误 2020-09-22 11:09:18 +08:00
RuoYi 69829827fe 菜单&数据权限新增(展开/折叠 全选/全不选 父子联动) 2020-09-21 14:10:01 +08:00
若依 89607fb028 !100 解决添加用户角色时报错问题
Merge pull request !100 from wensanpi/master
2020-09-21 10:31:59 +08:00
wensanpi 1aa18c523d update ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml. 2020-09-20 17:38:21 +08:00
RuoYi abeb8d7fd8 菜单新增是否缓存keep-alive 2020-09-20 10:34:03 +08:00
RuoYi 478fae0d28 菜单&数据权限新增(展开/折叠 全选/全不选 父子联动) 2020-09-19 13:42:37 +08:00
RuoYi 0ecf27f8d6 去除多余的空格 2020-09-18 17:09:27 +08:00
RuoYi 0a5bb34fbf 升级springboot到2.1.17 提升安全性 2020-09-18 16:51:27 +08:00
RuoYi 9e38c7de2e 代码生成支持同步数据库 2020-09-18 10:24:21 +08:00
RuoYi 9ca28d6dbf 表格操作列间距调整 2020-09-18 10:23:31 +08:00
RuoYi 497f98ba90 导入excel整形值校验优化 2020-09-17 18:22:50 +08:00
RuoYi a948affb2d 代码生成支持富文本控件 2020-09-15 15:53:27 +08:00
RuoYi 57b49dd5fa 限制系统内置参数不允许删除 2020-09-15 15:51:12 +08:00
RuoYi 9c0ed9c424 修复通知公告longblob类型乱码问题 2020-09-10 18:23:12 +08:00
RuoYi 70ab18052c 富文本工具栏样式对齐 2020-09-10 16:56:33 +08:00
RuoYi aeb02c79d8 修正注释图标路径 2020-09-10 16:53:58 +08:00
RuoYi 33793d8eff Excel导出类型NUMERIC支持精度浮点类型 2020-09-09 11:30:34 +08:00
RuoYi 9652906954 降级druid到版本v1.1.22,防止出现一些错误 2020-09-09 10:08:31 +08:00
RuoYi 9fccc7de40 修正调用目标字符串最大长度 2020-09-07 16:40:38 +08:00
RuoYi 599be64fa8 升级jjwt到0.9.1 2020-09-07 16:40:21 +08:00
RuoYi 50ac363682 升级druid到最新版本v1.1.23 2020-09-04 14:47:07 +08:00
若依 f84b157419 !87 数据权限中的空值处理
Merge pull request !87 from sproutcat/master
2020-09-04 14:17:32 +08:00
若依 f4536d5d2e !86 数据字典缓存处理的一点小问题
Merge pull request !86 from 说一/master
2020-09-04 14:07:47 +08:00
若依 aed958b1be !82 修复Editor组件在传入内容为null时无法响应式更新其内容的bug
Merge pull request !82 from HaoRan/N/A
2020-09-04 14:04:08 +08:00
tzg 0a51f7d743 空值处理 2020-09-02 14:59:10 +08:00
dawn 3fd9147afb 解决“在只填加了字典类型,没有添加字典数据时,会出现缓存了空集合,即使后边添加了字典数据也没用,只能清空redis缓存。”的问题,小问题就是判断稍稍改了下,若依大大让我pr当个贡献者,很荣幸很欣慰。感谢! 2020-09-02 10:14:34 +08:00
RuoYi 4f86b6d9ca 修改公告内容字段类型 2020-09-01 18:07:59 +08:00
HaoRan a65c287075 修复Editor组件无法对响应式更新null值问题 2020-08-31 02:10:01 +08:00
RuoYi 1af0d1665c 数据权限判断对象类型 2020-08-28 15:45:54 +08:00
RuoYi 4e32788b36 修正数据库字符串类型nvarchar 2020-08-28 14:11:32 +08:00
RuoYi 068c3e6f0d 优化递归子节点 2020-08-28 10:14:59 +08:00
RuoYi dd6640086e 代码生成树模板去掉多余双引号 2020-08-27 17:34:06 +08:00
RuoYi be54188ba6 导出Excel调整targetAttr获取值方法,防止get方法不规范 2020-08-26 15:39:46 +08:00
RuoYi a4e2339f90 生成页面时不忽略remark属性 2020-08-26 14:24:37 +08:00
RuoYi bf771ae5c8 Excel注解支持自动统计数据总和 2020-08-26 11:37:49 +08:00
RuoYi fa5596bb20 Editor组件优化,支持自定义高度&图片冲突问题 2020-08-22 13:18:41 +08:00
RuoYi eb30fc4b1a 修改公告内容字段类型 2020-08-22 13:11:40 +08:00
RuoYi 0446d211df 设置默认排序顺序 2020-08-19 17:02:23 +08:00
RuoYi da146c2a70 Excel注解支持设置BigDecimal精度&舍入规则 2020-08-19 11:20:31 +08:00
RuoYi 7de5358dcd 升级fastjson到最新版1.2.73 2020-08-19 11:17:24 +08:00
RuoYi 549c7ee97a 代码生成添加select必填选项 2020-08-18 18:15:12 +08:00
RuoYi 5fcf342f5a 修改sass为node-sass,避免el-icon图标乱码 2020-08-18 17:36:20 +08:00
若依 c89722a7dd !74 update ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java.
Merge pull request !74 from Lyy/N/A
2020-08-18 17:30:18 +08:00
若依 61e10f2783 !73 代码生成:select的表单验证失效
Merge pull request !73 from sunshine/master
2020-08-18 17:30:03 +08:00
若依 c6912ca1d5 !64 修改sass为node-sass,避免el-icon图标乱码
Merge pull request !64 from 心悦李国楠/dev-心悦
2020-08-18 17:27:19 +08:00
若依 5c4f0c5503 !65 根节点为子部门时,树状结构显示问题
Merge pull request !65 from GSTong/master
2020-08-18 17:21:51 +08:00
Lyy 4f7702b22a update ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java.
修改注释,CRSF禁用
2020-08-17 17:05:33 +08:00
sunshine 04e294b3e5 代码生成:select的表单验证失效 2020-08-17 12:08:34 +08:00
RuoYi d596d5bb8e 还原 addDateRange js 函数 2020-08-13 12:08:24 +08:00
RuoYi 8f9f0c04cc 若依 3.1 2020-08-13 10:27:56 +08:00
RuoYi 1bad003fe3 修改公私钥 2020-08-12 11:55:26 +08:00
RuoYi ad4df6245d 优化防重复提交拦截器,请求没有消息头则使用地址 2020-08-11 11:24:55 +08:00
gst 0070297fe1 根节点为子部门时,树状结构显示问题 2020-08-11 10:59:02 +08:00
RuoYi 71ec44a545 修正在线用户日志记录类型 2020-08-10 17:26:11 +08:00
RuoYi 1efae4a588 优化防重复提交拦截器,接口请求非json数据不获取Body消息体 2020-08-10 17:10:34 +08:00
liguonan 650359c357 修改sass为node-sass,避免el-icon图标乱码 2020-08-10 16:28:50 +08:00
RuoYi a78211ca00 优化上级菜单不能选择自己 2020-08-10 12:20:52 +08:00
RuoYi 74f52677be 表格右侧工具栏组件 2020-08-10 10:12:39 +08:00
若依 60d5c03e65 !63 重写表格工具栏右侧添加刷新&显隐查询栏
Merge pull request !63 from 平凡/重写表格工具栏右侧添加刷新&显隐查询栏
2020-08-10 09:53:27 +08:00
平凡 5b04f388e9 重写表格工具栏右侧添加刷新&显隐查询栏 2020-08-09 11:07:10 +08:00
RuoYi a7eb07c7a0 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue 2020-08-07 16:07:02 +08:00
RuoYi d0b315f4a5 删除重复的placeholder 2020-08-07 16:03:45 +08:00
若依 a6051d4638 !60 代码注释错误
Merge pull request !60 from waylon/master
2020-08-07 15:56:44 +08:00
wanglei c4ee9ea7c8 修复注释错误 2020-08-07 14:26:30 +08:00
RuoYi 7c39f92538 修复富文本空格和缩进保存后不生效问题 2020-08-07 12:26:15 +08:00
RuoYi 51fa66f61a 唯一限制条件只返回单条数据 2020-08-05 14:28:45 +08:00
RuoYi 3b61ed56b0 添加获取当前的环境配置方法 2020-08-05 12:56:32 +08:00
若依 db904f679e !57 若干 ruoyi-ui 前端公共工具函数优化
Merge pull request !57 from FungLeo/master
2020-08-05 11:39:56 +08:00
若依 98982515f7 !55 修复在线用户判断逻辑
Merge pull request !55 from 心悦李国楠/dev-心悦
2020-08-05 11:39:09 +08:00
若依 1a7baa0639 !58 cell的cellType由Numeric修正为String
Merge pull request !58 from 4ook/master
2020-08-05 11:38:44 +08:00
mazh a9695d1756 修复BUG: 导出Excel功能, 当attr的cellType为String时, cell的cellType由Numeric修正为String。 2020-08-05 11:28:57 +08:00
fungleo d78f642201 Merge remote-tracking branch 'upstream/master' 2020-08-05 10:26:05 +08:00
fungleo 26dfee2ce8 彻底重写回显数据字典方法 2020-08-05 10:24:54 +08:00
RuoYi b56898858d 超时登录后页面跳转到首页 2020-08-05 10:04:43 +08:00
fungleo 503dd64e3f 优化 addDateRange js 函数 2020-08-04 14:32:29 +08:00
fungleo 876ecf21c7 优化构建树形数据JS方法 2020-08-04 14:11:02 +08:00
fungleo 107672419e Merge remote-tracking branch 'upstream/master' 2020-08-04 11:59:42 +08:00
RuoYi 21d07c1d71 修复角色的权限分配后,未实时生效问题 2020-08-04 11:51:25 +08:00
fungleo d8d636fdbd 优化 回显数据字典(字符串数组)JS 函数 2020-08-04 11:39:43 +08:00
RuoYi 743fce7829 优化防重提交唯一标识 2020-08-04 11:07:37 +08:00
liguonan de2ac66f0b 修复在线用户判断逻辑 2020-08-03 17:57:33 +08:00
RuoYi 8b5d254242 全局异常状态汉化拦截处理 2020-08-03 09:11:49 +08:00
RuoYi a7eb0f98ac README 2020-08-03 09:02:28 +08:00
RuoYi 4dcf737db0 表格工具栏右侧添加刷新&显隐查询栏 2020-08-01 15:45:38 +08:00
RuoYi b32d0724b7 升级vue-cli版本到4.4.4 2020-07-31 22:35:30 +08:00
若依 8deacb702e !54 update ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml.
Merge pull request !54 from yongdaidai/N/A
2020-07-31 16:50:28 +08:00
若依 5be8d46d05 !51 优化生成vue文件的vm模板文件
Merge pull request !51 from FungLeo/master
2020-07-31 16:49:51 +08:00
yongdaidai fb19dd3e4e update ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml.
解决如果导入多个同名部门dept_name,parent_id相同,但是删除状态(del_flag)不同,导致查询结果为多条,mybatis不能映射为一条数据的问题.
2020-07-31 14:59:23 +08:00
RuoYi cbf4795fd5 表单类型为Integer/Long设置整形默认值 2020-07-30 21:47:50 +08:00
RuoYi 5d74ed32bd 表单类型为Integer/Long设置整形默认值 2020-07-30 16:03:44 +08:00
若依 6afaced3cf !53 update ruoyi-ui/src/views/system/role/index.vue.
Merge pull request !53 from abbfun/N/A
2020-07-30 10:04:11 +08:00
abbfun f3976c0792 update ruoyi-ui/src/views/system/role/index.vue.
权限修正(角色导出权限)
2020-07-29 21:16:53 +08:00
RuoYi 22225a5119 HTML过滤器改为将html转义 2020-07-28 17:28:09 +08:00
RuoYi fe030cc022 修改 node-sass 为 dart-sass 2020-07-27 16:55:51 +08:00
fungleo ca657b0482 优化 index-tree.vue.vm 文件,undefined 修改为 null 2020-07-26 17:33:42 +08:00
fungleo c1d1ace36d 优化index.vue.vm模板,!=1修改为严格不等;undefined修改为null 2020-07-26 17:29:40 +08:00
RuoYi 6e7d7aba93 代码生成支持自定义路径 2020-07-24 15:37:57 +08:00
RuoYi 388e36ed4d 优化参数 2020-07-23 21:45:22 +08:00
若依 5d89d0b36a !49 代码生成器默认mapper路径与默认mapperScan路径不一致
Merge pull request !49 from HaoRan/master
2020-07-23 21:25:10 +08:00
若依 55095a50b5 !48 ExcelUtil 功能优化
Merge pull request !48 from soulCoke/master
2020-07-23 21:25:02 +08:00
HR.Hu ee4b4de7b1 修复 代码生成器默认mapper路径与默认mapperScan路径不一致的bug 2020-07-23 21:01:18 +08:00
RuoYi 92c6301285 Excel支持分割字符串组内容 2020-07-23 18:58:45 +08:00
RuoYi 5c6adb25fc 代码生成支持复选框 2020-07-23 17:02:55 +08:00
soulCoke 8dd3ca5bb6 excel 导入数字不需要格式化 ,导入允许列和属性个数不一致。 2020-07-23 15:54:03 +08:00
Sxile be778ba370 修复参数注释 2020-07-23 14:54:11 +08:00
RuoYi 52d48fa63e 检查字符支持小数点&降级改成异常提醒 2020-07-23 11:29:40 +08:00
RuoYi df3ef54b41 验证码类型支持(数组计算、字符验证) 2020-07-23 11:17:04 +08:00
RuoYi 1e40e60dbf 支持CORS跨域请求 2020-07-22 15:25:42 +08:00
若依 133a10ecf2 !47 修复和优化前端 utils 工具函数
Merge pull request !47 from FungLeo/master
2020-07-22 13:00:51 +08:00
RuoYi 6a84ae42a5 代码生成支持选择上级菜单 2020-07-21 15:52:11 +08:00
RuoYi b2d79b62d1 代码生成支持选择上级菜单 2020-07-21 11:21:20 +08:00
fungleo a09a342f58 优化 uitls/ruoyi.js 中 selectDictLabel 方法,数组迭代器换为 some
提高性能
2020-07-21 10:22:07 +08:00
fungleo 3e1bd8e3bc 修复 utils/index.js 中不包含 parseTime 函数的 bug 2020-07-21 10:18:56 +08:00
RuoYi 8a076e175f Excel导出导入支持dictType字典类型 2020-07-20 15:25:05 +08:00
113 changed files with 2230 additions and 804 deletions
+2 -1
View File
@@ -37,7 +37,8 @@ nbdist/
# Others # Others
*.log *.log
*.xml.versionsBackup *.xml.versionsBackup
*.swp
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
+10 -10
View File
@@ -6,8 +6,8 @@
* 支持加载动态权限菜单,多方式轻松权限控制。 * 支持加载动态权限菜单,多方式轻松权限控制。
* 高效率开发,使用代码生成器可以一键生成前后端代码。 * 高效率开发,使用代码生成器可以一键生成前后端代码。
* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。 * 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) * 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
* 阿里云优惠券:[点我进入](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)   * 阿里云优惠券:[点我进入](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)  
## 内置功能 ## 内置功能
@@ -46,27 +46,27 @@
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr> </tr>
<tr> <tr>
+29 -7
View File
@@ -6,29 +6,32 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.0.0</version> <version>3.2.0</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.0.0</ruoyi.version> <ruoyi.version>3.2.0</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>
<mybatis.boot.version>1.3.2</mybatis.boot.version> <mybatis.boot.version>1.3.2</mybatis.boot.version>
<druid.version>1.1.14</druid.version> <druid.version>1.2.1</druid.version>
<bitwalker.version>1.19</bitwalker.version> <bitwalker.version>1.19</bitwalker.version>
<swagger.version>2.9.2</swagger.version> <swagger.version>2.9.2</swagger.version>
<kaptcha.version>2.3.2</kaptcha.version>
<pagehelper.boot.version>1.2.5</pagehelper.boot.version> <pagehelper.boot.version>1.2.5</pagehelper.boot.version>
<fastjson.version>1.2.70</fastjson.version> <fastjson.version>1.2.74</fastjson.version>
<oshi.version>3.9.1</oshi.version> <oshi.version>5.2.5</oshi.version>
<jna.version>5.5.0</jna.version>
<commons.io.version>2.5</commons.io.version> <commons.io.version>2.5</commons.io.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version> <commons.fileupload.version>1.3.3</commons.fileupload.version>
<poi.version>3.17</poi.version> <poi.version>3.17</poi.version>
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<jwt.version>0.9.0</jwt.version> <jwt.version>0.9.1</jwt.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
@@ -39,7 +42,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version> <version>2.1.17.RELEASE</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@@ -71,6 +74,18 @@
<artifactId>oshi-core</artifactId> <artifactId>oshi-core</artifactId>
<version>${oshi.version}</version> <version>${oshi.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
<!-- swagger2--> <!-- swagger2-->
<dependency> <dependency>
@@ -137,6 +152,13 @@
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
<version>${jwt.version}</version> <version>${jwt.version}</version>
</dependency> </dependency>
<!--验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!-- 定时任务--> <!-- 定时任务-->
<dependency> <dependency>
+2 -2
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -95,7 +95,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId> <artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<configuration> <configuration>
<failOnMissingWebXml>false</failOnMissingWebXml> <failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName> <warName>${project.artifactId}</warName>
@@ -1,16 +1,20 @@
package com.ruoyi.web.controller.common; package com.ruoyi.web.controller.common;
import java.io.ByteArrayOutputStream; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
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.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.VerifyCodeUtils;
import com.ruoyi.common.utils.sign.Base64; import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.common.utils.uuid.IdUtils;
@@ -22,8 +26,18 @@ import com.ruoyi.common.utils.uuid.IdUtils;
@RestController @RestController
public class CaptchaController public class CaptchaController
{ {
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
// 验证码类型
@Value("${ruoyi.captchaType}")
private String captchaType;
/** /**
* 生成验证码 * 生成验证码
@@ -31,32 +45,42 @@ public class CaptchaController
@GetMapping("/captchaImage") @GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException public AjaxResult getCode(HttpServletResponse response) throws IOException
{ {
// 生成随机字串 // 保存验证码信息
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
// 唯一标识
String uuid = IdUtils.simpleUUID(); String uuid = IdUtils.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
redisCache.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); String capStr = null, code = null;
// 生成图片 BufferedImage image = null;
int w = 111, h = 36;
ByteArrayOutputStream stream = new ByteArrayOutputStream(); // 生成验证码
VerifyCodeUtils.outputImage(w, h, stream, verifyCode); if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try try
{ {
AjaxResult ajax = AjaxResult.success(); ImageIO.write(image, "jpg", os);
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(stream.toByteArray()));
return ajax;
} }
catch (Exception e) catch (IOException e)
{ {
e.printStackTrace();
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
finally
{ AjaxResult ajax = AjaxResult.success();
stream.close(); ajax.put("uuid", uuid);
} ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
} }
} }
@@ -38,18 +38,18 @@ public class SysLogininforController extends BaseController
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "日志", businessType = BusinessType.EXPORT) @Log(title = "日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@GetMapping("/export") @GetMapping("/export")
public AjaxResult export(SysLogininfor logininfor) public AjaxResult export(SysLogininfor logininfor)
{ {
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
return util.exportExcel(list, "日志"); return util.exportExcel(list, "日志");
} }
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "日志", businessType = BusinessType.DELETE) @Log(title = "日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}") @DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds) public AjaxResult remove(@PathVariable Long[] infoIds)
{ {
@@ -57,7 +57,7 @@ public class SysLogininforController extends BaseController
} }
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "日志", businessType = BusinessType.CLEAN) @Log(title = "日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean") @DeleteMapping("/clean")
public AjaxResult clean() public AjaxResult clean()
{ {
@@ -82,7 +82,7 @@ public class SysUserOnlineController extends BaseController
* 强退用户 * 强退用户
*/ */
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.DELETE) @Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}") @DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId) public AjaxResult forceLogout(@PathVariable String tokenId)
{ {
@@ -126,7 +126,11 @@ public class SysMenuController extends BaseController
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
{ {
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
} }
menu.setUpdateBy(SecurityUtils.getUsername()); menu.setUpdateBy(SecurityUtils.getUsername());
return toAjax(menuService.updateMenu(menu)); return toAjax(menuService.updateMenu(menu));
@@ -17,11 +17,17 @@ import com.ruoyi.common.constant.UserConstants;
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.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
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.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/** /**
* 角色信息 * 角色信息
@@ -35,6 +41,15 @@ public class SysRoleController extends BaseController
@Autowired @Autowired
private ISysRoleService roleService; private ISysRoleService roleService;
@Autowired
private TokenService tokenService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private ISysUserService userService;
@PreAuthorize("@ss.hasPermi('system:role:list')") @PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysRole role) public TableDataInfo list(SysRole role)
@@ -103,7 +118,20 @@ public class SysRoleController extends BaseController
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
} }
role.setUpdateBy(SecurityUtils.getUsername()); role.setUpdateBy(SecurityUtils.getUsername());
return toAjax(roleService.updateRole(role));
if (roleService.updateRole(role) > 0)
{
// 更新缓存用户权限
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
tokenService.setLoginUser(loginUser);
}
return AjaxResult.success();
}
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
} }
/** /**
@@ -3,15 +3,17 @@ ruoyi:
# 名称 # 名称
name: RuoYi name: RuoYi
# 版本 # 版本
version: 3.0.0 version: 3.2.0
# 版权年份 # 版权年份
copyrightYear: 2019 copyrightYear: 2020
# 实例演示开关 # 实例演示开关
demoEnabled: true demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath # 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: D:/ruoyi/uploadPath profile: D:/ruoyi/uploadPath
# 获取ip地址开关 # 获取ip地址开关
addressEnabled: false addressEnabled: false
# 验证码类型 math 数组计算 char 字符验证
captchaType: math
# 开发环境配置 # 开发环境配置
server: server:
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal;
/** /**
* 自定义导出Excel数据注解 * 自定义导出Excel数据注解
@@ -29,11 +30,31 @@ public @interface Excel
*/ */
public String dateFormat() default ""; public String dateFormat() default "";
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/** /**
* 读取内容转表达式 (如: 0=男,1=女,2=未知) * 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/ */
public String readConverterExp() default ""; public String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/** /**
* 导出类型(0数字 1字符串) * 导出类型(0数字 1字符串)
*/ */
@@ -79,6 +100,11 @@ public @interface Excel
*/ */
public String targetAttr() default ""; public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/** /**
* 字段类型(0:导出导入;1:仅导出;2:仅导入) * 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/ */
@@ -115,4 +141,4 @@ public @interface Excel
return this.value; return this.value;
} }
} }
} }
@@ -61,6 +61,11 @@ public class Constants
* 登录用户 redis key * 登录用户 redis key
*/ */
public static final String LOGIN_TOKEN_KEY = "login_tokens:"; public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/** /**
* 验证码有效期(分钟) * 验证码有效期(分钟)
@@ -22,8 +22,14 @@ public class GenConstants
/** 树名称字段 */ /** 树名称字段 */
public static final String TREE_NAME = "treeName"; public static final String TREE_NAME = "treeName";
/** 上级菜单ID字段 */
public static final String PARENT_MENU_ID = "parentMenuId";
/** 上级菜单名称字段 */
public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */ /** 数据库字符串类型 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text", public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2", "tinytext", "text",
"mediumtext", "longtext" }; "mediumtext", "longtext" };
/** 数据库时间类型 */ /** 数据库时间类型 */
@@ -68,6 +74,9 @@ public class GenConstants
/** 日期控件 */ /** 日期控件 */
public static final String HTML_DATETIME = "datetime"; public static final String HTML_DATETIME = "datetime";
/** 富文本控件 */
public static final String HTML_EDITOR = "editor";
/** 字符串类型 */ /** 字符串类型 */
public static final String TYPE_STRING = "String"; public static final String TYPE_STRING = "String";
@@ -41,6 +41,9 @@ public class SysMenu extends BaseEntity
/** 是否为外链(0是 1否) */ /** 是否为外链(0是 1否) */
private String isFrame; private String isFrame;
/** 是否缓存(0缓存 1不缓存) */
private String isCache;
/** 类型(M目录 C菜单 F按钮) */ /** 类型(M目录 C菜单 F按钮) */
private String menuType; private String menuType;
@@ -144,6 +147,16 @@ public class SysMenu extends BaseEntity
this.isFrame = isFrame; this.isFrame = isFrame;
} }
public String getIsCache()
{
return isCache;
}
public void setIsCache(String isCache)
{
this.isCache = isCache;
}
@NotBlank(message = "菜单类型不能为空") @NotBlank(message = "菜单类型不能为空")
public String getMenuType() public String getMenuType()
{ {
@@ -216,6 +229,7 @@ public class SysMenu extends BaseEntity
.append("path", getPath()) .append("path", getPath())
.append("component", getComponent()) .append("component", getComponent())
.append("isFrame", getIsFrame()) .append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType()) .append("menuType", getMenuType())
.append("visible", getVisible()) .append("visible", getVisible())
.append("status ", getStatus()) .append("status ", getStatus())
@@ -37,6 +37,12 @@ public class SysRole extends BaseEntity
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限")
private String dataScope; private String dataScope;
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
private boolean deptCheckStrictly;
/** 角色状态(0正常 1停用) */ /** 角色状态(0正常 1停用) */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
@@ -128,6 +134,26 @@ public class SysRole extends BaseEntity
this.dataScope = dataScope; this.dataScope = dataScope;
} }
public boolean isMenuCheckStrictly()
{
return menuCheckStrictly;
}
public void setMenuCheckStrictly(boolean menuCheckStrictly)
{
this.menuCheckStrictly = menuCheckStrictly;
}
public boolean isDeptCheckStrictly()
{
return deptCheckStrictly;
}
public void setDeptCheckStrictly(boolean deptCheckStrictly)
{
this.deptCheckStrictly = deptCheckStrictly;
}
public String getStatus() public String getStatus()
{ {
return status; return status;
@@ -186,6 +212,8 @@ public class SysRole extends BaseEntity
.append("roleKey", getRoleKey()) .append("roleKey", getRoleKey())
.append("roleSort", getRoleSort()) .append("roleSort", getRoleSort())
.append("dataScope", getDataScope()) .append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus()) .append("status", getStatus())
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
@@ -68,12 +68,12 @@ public class SysUser extends BaseEntity
/** 删除标志(0代表存在 2代表删除) */ /** 删除标志(0代表存在 2代表删除) */
private String delFlag; private String delFlag;
/** 最后登IP */ /** 最后登IP */
@Excel(name = "最后登IP", type = Type.EXPORT) @Excel(name = "最后登IP", type = Type.EXPORT)
private String loginIp; private String loginIp;
/** 最后登时间 */ /** 最后登时间 */
@Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 部门对象 */ /** 部门对象 */
@@ -22,7 +22,7 @@ public class LoginUser implements UserDetails
private String token; private String token;
/** /**
* 登时间 * 登时间
*/ */
private Long loginTime; private Long loginTime;
@@ -18,8 +18,8 @@ public class PageDomain
/** 排序列 */ /** 排序列 */
private String orderByColumn; private String orderByColumn;
/** 排序的方向 "desc" 或者 "asc". */ /** 排序的方向desc或者asc */
private String isAsc; private String isAsc = "asc";
public String getOrderBy() public String getOrderBy()
{ {
@@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
/** /**
* spring redis 工具类 * spring redis 工具类
* *
* @author ruoyi * @author ruoyi
**/ **/
@SuppressWarnings(value = { "unchecked", "rawtypes" }) @SuppressWarnings(value = { "unchecked", "rawtypes" })
@@ -109,7 +109,7 @@ public class RedisCache
* 缓存List数据 * 缓存List数据
* *
* @param key 缓存的键值 * @param key 缓存的键值
* @param values 待缓存的List数据 * @param dataList 待缓存的List数据
* @return 缓存的对象 * @return 缓存的对象
*/ */
public <T> long setCacheList(final String key, final List<T> dataList) public <T> long setCacheList(final String key, final List<T> dataList)
@@ -216,7 +216,7 @@ public class RedisCache
/** /**
* 获得缓存的基本对象列表 * 获得缓存的基本对象列表
* *
* @param pattern 字符串前缀 * @param pattern 字符串前缀
* @return 对象列表 * @return 对象列表
*/ */
@@ -2,7 +2,6 @@ package com.ruoyi.common.utils;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
@@ -15,6 +14,11 @@ import com.ruoyi.common.utils.spring.SpringUtils;
*/ */
public class DictUtils public class DictUtils
{ {
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/** /**
* 设置字典缓存 * 设置字典缓存
* *
@@ -37,12 +41,116 @@ public class DictUtils
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj)) if (StringUtils.isNotNull(cacheObj))
{ {
List<SysDictData> DictDatas = StringUtils.cast(cacheObj); List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
return DictDatas; return dictDatas;
} }
return null; return null;
} }
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue)
{
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel)
{
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String value : dictValue.split(separator))
{
if (value.equals(dict.getDictValue()))
{
propertyString.append(dict.getDictLabel() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictValue.equals(dict.getDictValue()))
{
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String label : dictLabel.split(separator))
{
if (label.equals(dict.getDictLabel()))
{
propertyString.append(dict.getDictValue() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictLabel.equals(dict.getDictLabel()))
{
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/** /**
* 清空字典缓存 * 清空字典缓存
*/ */
@@ -15,7 +15,7 @@ import com.ruoyi.common.utils.uuid.IdUtils;
/** /**
* 文件上传工具类 * 文件上传工具类
* *
* @author ruoyi * @author ruoyi
*/ */
public class FileUploadUtils public class FileUploadUtils
@@ -89,7 +89,7 @@ public class FileUploadUtils
* *
* @param baseDir 相对应用的基目录 * @param baseDir 相对应用的基目录
* @param file 上传的文件 * @param file 上传的文件
* @param extension 上传文件类型 * @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名 * @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小 * @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长 * @throws FileNameLengthLimitExceededException 文件名太长
@@ -215,7 +215,7 @@ public class FileUploadUtils
/** /**
* 获取文件名的后缀 * 获取文件名的后缀
* *
* @param file 表单文件 * @param file 表单文件
* @return 后缀名 * @return 后缀名
*/ */
@@ -228,4 +228,4 @@ public class FileUploadUtils
} }
return extension; return extension;
} }
} }
@@ -14,7 +14,7 @@ import javax.servlet.http.HttpServletRequest;
* *
* @author ruoyi * @author ruoyi
*/ */
public class FileUtils public class FileUtils extends org.apache.commons.io.FileUtils
{ {
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
@@ -144,7 +144,10 @@ public class EscapeUtil
public static void main(String[] args) public static void main(String[] args)
{ {
String html = "alert('11111');"; String html = "<script>alert(1);</script>";
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123";
// String html = "123>";
System.out.println(EscapeUtil.clean(html)); System.out.println(EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html)); System.out.println(EscapeUtil.escape(html));
System.out.println(EscapeUtil.unescape(html)); System.out.println(EscapeUtil.unescape(html));
@@ -131,7 +131,7 @@ public final class HTMLFilter
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
stripComment = true; stripComment = true;
encodeQuotes = true; encodeQuotes = true;
alwaysMakeTags = true; alwaysMakeTags = false;
} }
/** /**
@@ -208,7 +208,7 @@ public final class HTMLFilter
s = processRemoveBlanks(s); s = processRemoveBlanks(s);
s = validateEntities(s); // s = validateEntities(s);
return s; return s;
} }
@@ -245,6 +245,7 @@ public final class HTMLFilter
// try and form html // try and form html
// //
s = regexReplace(P_END_ARROW, "", s); s = regexReplace(P_END_ARROW, "", s);
// 不追加结束标签
s = regexReplace(P_BODY_TO_END, "<$1>", s); s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s); s = regexReplace(P_XML_CONTENT, "$1<$2", s);
@@ -6,7 +6,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
@@ -16,6 +15,7 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFDateUtil;
@@ -50,6 +50,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils; import com.ruoyi.common.utils.reflect.ReflectUtils;
@@ -102,6 +103,16 @@ public class ExcelUtil<T>
*/ */
private List<Object[]> fields; private List<Object[]> fields;
/**
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/** /**
* 实体对象 * 实体对象
*/ */
@@ -199,7 +210,10 @@ public class ExcelUtil<T>
// 设置类的私有字段属性可访问. // 设置类的私有字段属性可访问.
field.setAccessible(true); field.setAccessible(true);
Integer column = cellMap.get(attr.name()); Integer column = cellMap.get(attr.name());
fieldsMap.put(column, field); if (column != null)
{
fieldsMap.put(column, field);
}
} }
} }
for (int i = 1; i < rows; i++) for (int i = 1; i < rows; i++)
@@ -229,19 +243,19 @@ public class ExcelUtil<T>
val = Convert.toStr(val); val = Convert.toStr(val);
} }
} }
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
{ {
val = Convert.toInt(val); val = Convert.toInt(val);
} }
else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) else if (Long.TYPE == fieldType || Long.class == fieldType)
{ {
val = Convert.toLong(val); val = Convert.toLong(val);
} }
else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) else if (Double.TYPE == fieldType || Double.class == fieldType)
{ {
val = Convert.toDouble(val); val = Convert.toDouble(val);
} }
else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) else if (Float.TYPE == fieldType || Float.class == fieldType)
{ {
val = Convert.toFloat(val); val = Convert.toFloat(val);
} }
@@ -270,7 +284,11 @@ public class ExcelUtil<T>
} }
else if (StringUtils.isNotEmpty(attr.readConverterExp())) else if (StringUtils.isNotEmpty(attr.readConverterExp()))
{ {
val = reverseByExp(String.valueOf(val), attr.readConverterExp()); val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
} }
ReflectUtils.invokeSetter(entity, propertyName, val); ReflectUtils.invokeSetter(entity, propertyName, val);
} }
@@ -334,6 +352,7 @@ public class ExcelUtil<T>
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index, row); fillExcelData(index, row);
addStatisticsRow();
} }
} }
String filename = encodingFilename(sheetName); String filename = encodingFilename(sheetName);
@@ -440,6 +459,15 @@ public class ExcelUtil<T>
headerFont.setColor(IndexedColors.WHITE.getIndex()); headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont); style.setFont(headerFont);
styles.put("header", style); styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font totalFont = wb.createFont();
totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10);
style.setFont(totalFont);
styles.put("total", style);
return styles; return styles;
} }
@@ -469,13 +497,13 @@ public class ExcelUtil<T>
{ {
if (ColumnType.STRING == attr.cellType()) if (ColumnType.STRING == attr.cellType())
{ {
cell.setCellType(CellType.NUMERIC); cell.setCellType(CellType.STRING);
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
} }
else if (ColumnType.NUMERIC == attr.cellType()) else if (ColumnType.NUMERIC == attr.cellType())
{ {
cell.setCellType(CellType.NUMERIC); cell.setCellType(CellType.NUMERIC);
cell.setCellValue(Integer.parseInt(value + "")); cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
} }
} }
@@ -529,19 +557,30 @@ public class ExcelUtil<T>
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
String dateFormat = attr.dateFormat(); String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp(); String readConverterExp = attr.readConverterExp();
String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{ {
cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp)); cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
}
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
} }
else else
{ {
// 设置列类型 // 设置列类型
setCellVo(value, attr, cell); setCellVo(value, attr, cell);
} }
addStatisticsData(column, Convert.toStr(value), attr);
} }
} }
catch (Exception e) catch (Exception e)
@@ -613,28 +652,36 @@ public class ExcelUtil<T>
* *
* @param propertyValue 参数值 * @param propertyValue 参数值
* @param converterExp 翻译注解 * @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值 * @return 解析后值
* @throws Exception
*/ */
public static String convertByExp(String propertyValue, String converterExp) throws Exception public static String convertByExp(String propertyValue, String converterExp, String separator)
{ {
try StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{ {
String[] convertSource = converterExp.split(","); String[] itemArray = item.split("=");
for (String item : convertSource) if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[0].equals(value))
{
propertyString.append(itemArray[1] + separator);
break;
}
}
}
else
{ {
String[] itemArray = item.split("=");
if (itemArray[0].equals(propertyValue)) if (itemArray[0].equals(propertyValue))
{ {
return itemArray[1]; return itemArray[1];
} }
} }
} }
catch (Exception e) return StringUtils.stripEnd(propertyString.toString(), separator);
{
throw e;
}
return propertyValue;
} }
/** /**
@@ -642,28 +689,109 @@ public class ExcelUtil<T>
* *
* @param propertyValue 参数值 * @param propertyValue 参数值
* @param converterExp 翻译注解 * @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值 * @return 解析后值
* @throws Exception
*/ */
public static String reverseByExp(String propertyValue, String converterExp) throws Exception public static String reverseByExp(String propertyValue, String converterExp, String separator)
{ {
try StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{ {
String[] convertSource = converterExp.split(","); String[] itemArray = item.split("=");
for (String item : convertSource) if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[1].equals(value))
{
propertyString.append(itemArray[0] + separator);
break;
}
}
}
else
{ {
String[] itemArray = item.split("=");
if (itemArray[1].equals(propertyValue)) if (itemArray[1].equals(propertyValue))
{ {
return itemArray[0]; return itemArray[0];
} }
} }
} }
catch (Exception e) return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public static String convertDictByExp(String dictValue, String dictType, String separator)
{
return DictUtils.getDictLabel(dictType, dictValue, separator);
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典值
*/
public static String reverseDictByExp(String dictLabel, String dictType, String separator)
{
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/**
* 合计统计信息
*/
private void addStatisticsData(Integer index, String text, Excel entity)
{
if (entity != null && entity.isStatistics())
{ {
throw e; Double temp = 0D;
if (!statistics.containsKey(index))
{
statistics.put(index, temp);
}
try
{
temp = Double.valueOf(text);
}
catch (NumberFormatException e)
{
}
statistics.put(index, statistics.get(index) + temp);
}
}
/**
* 创建统计行
*/
public void addStatisticsRow()
{
if (statistics.size() > 0)
{
Cell cell = null;
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
Set<Integer> keys = statistics.keySet();
cell = row.createCell(0);
cell.setCellStyle(styles.get("total"));
cell.setCellValue("合计");
for (Integer key : keys)
{
cell = row.createCell(key);
cell.setCellStyle(styles.get("total"));
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
}
statistics.clear();
} }
return propertyValue;
} }
/** /**
@@ -735,9 +863,9 @@ public class ExcelUtil<T>
if (StringUtils.isNotEmpty(name)) if (StringUtils.isNotEmpty(name))
{ {
Class<?> clazz = o.getClass(); Class<?> clazz = o.getClass();
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); Field field = clazz.getDeclaredField(name);
Method method = clazz.getMethod(methodName); field.setAccessible(true);
o = method.invoke(o); o = field.get(o);
} }
return o; return o;
} }
@@ -843,7 +971,7 @@ public class ExcelUtil<T>
{ {
if ((Double) val % 1 > 0) if ((Double) val % 1 > 0)
{ {
val = new DecimalFormat("0.00").format(val); val = new BigDecimal(val.toString());
} }
else else
{ {
@@ -5,7 +5,10 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
/** /**
* spring工具类 方便在非spring管理环境中获取bean * spring工具类 方便在非spring管理环境中获取bean
@@ -13,17 +16,25 @@ import org.springframework.stereotype.Component;
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public final class SpringUtils implements BeanFactoryPostProcessor public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{ {
/** Spring应用上下文环境 */ /** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory; private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{ {
SpringUtils.beanFactory = beanFactory; SpringUtils.beanFactory = beanFactory;
} }
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}
/** /**
* 获取对象 * 获取对象
* *
@@ -111,4 +122,25 @@ public final class SpringUtils implements BeanFactoryPostProcessor
{ {
return (T) AopContext.currentProxy(); return (T) AopContext.currentProxy();
} }
/**
* 获取当前的环境配置,无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile()
{
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
} }
@@ -1,5 +1,6 @@
package com.ruoyi.common.utils.sql; package com.ruoyi.common.utils.sql;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
/** /**
@@ -10,9 +11,9 @@ import com.ruoyi.common.utils.StringUtils;
public class SqlUtil public class SqlUtil
{ {
/** /**
* 仅支持字母、数字、下划线、空格、逗号(支持多个字段排序) * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/ */
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,]+"; public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/** /**
* 检查字符,防止注入绕过 * 检查字符,防止注入绕过
@@ -21,7 +22,7 @@ public class SqlUtil
{ {
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{ {
return StringUtils.EMPTY; throw new BaseException("参数不符合规范,不能进行查询");
} }
return value; return value;
} }
+13 -11
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -35,22 +35,24 @@
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<exclusions>
<exclusion>
<artifactId>javax.servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 获取系统信息 --> <!-- 获取系统信息 -->
<dependency> <dependency>
<groupId>com.github.oshi</groupId> <groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId> <artifactId>oshi-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
</dependency>
<!-- 系统模块--> <!-- 系统模块-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@@ -20,7 +20,7 @@ import com.ruoyi.framework.web.service.TokenService;
/** /**
* 数据过滤处理 * 数据过滤处理
* *
* @author ruoyi * @author ruoyi
*/ */
@Aspect @Aspect
@@ -79,11 +79,11 @@ public class DataScopeAspect
} }
// 获取当前的用户 // 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
SysUser currentUser = loginUser.getUser(); if (StringUtils.isNotNull(loginUser))
if (currentUser != null)
{ {
SysUser currentUser = loginUser.getUser();
// 如果是超级管理员,则不过滤数据 // 如果是超级管理员,则不过滤数据
if (!currentUser.isAdmin()) if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{ {
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias()); controllerDataScope.userAlias());
@@ -93,10 +93,10 @@ public class DataScopeAspect
/** /**
* 数据范围过滤 * 数据范围过滤
* *
* @param joinPoint 切点 * @param joinPoint 切点
* @param user 用户 * @param user 用户
* @param alias 别名 * @param userAlias 别名
*/ */
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{ {
@@ -142,8 +142,12 @@ public class DataScopeAspect
if (StringUtils.isNotBlank(sqlString.toString())) if (StringUtils.isNotBlank(sqlString.toString()))
{ {
BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0]; Object params = joinPoint.getArgs()[0];
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
} }
} }
@@ -0,0 +1,83 @@
package com.ruoyi.framework.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import static com.google.code.kaptcha.Constants.*;
/**
* 验证码配置
*
* @author ruoyi
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
@@ -0,0 +1,75 @@
package com.ruoyi.framework.config;
import java.util.Random;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
* 验证码文本生成器
*
* @author ruoyi
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}
@@ -1,7 +1,11 @@
package com.ruoyi.framework.config; 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.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -39,4 +43,24 @@ public class ResourcesConfig implements WebMvcConfigurer
{ {
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
} }
/**
* 跨域配置
*/
@Bean
public CorsFilter corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置访问源地址
config.addAllowedOrigin("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 对接口配置跨域设置
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
} }
@@ -12,6 +12,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.web.filter.CorsFilter;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
@@ -47,6 +49,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/ */
@Autowired @Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter; private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@Autowired
private CorsFilter corsFilter;
/** /**
* 解决 无法直接注入 AuthenticationManager * 解决 无法直接注入 AuthenticationManager
@@ -80,7 +88,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
protected void configure(HttpSecurity httpSecurity) throws Exception protected void configure(HttpSecurity httpSecurity) throws Exception
{ {
httpSecurity httpSecurity
// CRSF禁用,因为不使用session // CSRF禁用,因为不使用session
.csrf().disable() .csrf().disable()
// 认证失败处理类 // 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
@@ -112,6 +120,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter // 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
} }
@@ -13,7 +13,7 @@ import com.ruoyi.common.utils.ServletUtils;
/** /**
* 防止重复提交拦截器 * 防止重复提交拦截器
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
@@ -46,8 +46,8 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
/** /**
* 验证是否重复提交由子类实现具体的防重复提交的规则 * 验证是否重复提交由子类实现具体的防重复提交的规则
* *
* @param httpServletRequest * @param request
* @return * @return
* @throws Exception * @throws Exception
*/ */
@@ -5,8 +5,10 @@ import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper; import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@@ -26,7 +28,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
public final String REPEAT_TIME = "repeatTime"; public final String REPEAT_TIME = "repeatTime";
public final String CACHE_REPEAT_KEY = "repeatData"; // 令牌自定义标识
@Value("${token.header}")
private String header;
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@@ -47,8 +51,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
@Override @Override
public boolean isRepeatSubmit(HttpServletRequest request) public boolean isRepeatSubmit(HttpServletRequest request)
{ {
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; String nowParams = "";
String nowParams = HttpHelper.getBodyString(repeatedlyRequest); if (request instanceof RepeatedlyRequestWrapper)
{
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
nowParams = HttpHelper.getBodyString(repeatedlyRequest);
}
// body参数为空,获取Parameter的数据 // body参数为空,获取Parameter的数据
if (StringUtils.isEmpty(nowParams)) if (StringUtils.isEmpty(nowParams))
@@ -62,7 +70,17 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
// 请求地址(作为存放cache的key值) // 请求地址(作为存放cache的key值)
String url = request.getRequestURI(); String url = request.getRequestURI();
Object sessionObj = redisCache.getCacheObject(CACHE_REPEAT_KEY); // 唯一值(没有消息头则使用请求地址)
String submitKey = request.getHeader(header);
if (StringUtils.isEmpty(submitKey))
{
submitKey = url;
}
// 唯一标识(指定key + 消息头)
String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cache_repeat_key);
if (sessionObj != null) if (sessionObj != null)
{ {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
@@ -77,7 +95,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
} }
Map<String, Object> cacheMap = new HashMap<String, Object>(); Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap); cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(CACHE_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS); redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS);
return false; return false;
} }
@@ -25,7 +25,7 @@ public class AsyncFactory
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
/** /**
* 记录登信息 * 记录登信息
* *
* @param username 用户名 * @param username 用户名
* @param status 状态 * @param status 状态
@@ -189,7 +189,7 @@ public class Server
private void setSysFiles(OperatingSystem os) private void setSysFiles(OperatingSystem os)
{ {
FileSystem fileSystem = os.getFileSystem(); FileSystem fileSystem = os.getFileSystem();
OSFileStore[] fsArray = fileSystem.getFileStores(); List<OSFileStore> fsArray = fileSystem.getFileStores();
for (OSFileStore fs : fsArray) for (OSFileStore fs : fsArray)
{ {
long free = fs.getUsableSpace(); long free = fs.getUsableSpace();
@@ -22,7 +22,7 @@ import io.jsonwebtoken.SignatureAlgorithm;
/** /**
* token验证处理 * token验证处理
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
@@ -51,7 +51,7 @@ public class TokenService
/** /**
* 获取用户身份信息 * 获取用户身份信息
* *
* @return 用户信息 * @return 用户信息
*/ */
public LoginUser getLoginUser(HttpServletRequest request) public LoginUser getLoginUser(HttpServletRequest request)
@@ -95,7 +95,7 @@ public class TokenService
/** /**
* 创建令牌 * 创建令牌
* *
* @param loginUser 用户信息 * @param loginUser 用户信息
* @return 令牌 * @return 令牌
*/ */
@@ -113,8 +113,8 @@ public class TokenService
/** /**
* 验证令牌有效期,相差不足20分钟,自动刷新缓存 * 验证令牌有效期,相差不足20分钟,自动刷新缓存
* *
* @param token 令牌 * @param loginUser
* @return 令牌 * @return 令牌
*/ */
public void verifyToken(LoginUser loginUser) public void verifyToken(LoginUser loginUser)
@@ -129,7 +129,7 @@ public class TokenService
/** /**
* 刷新令牌有效期 * 刷新令牌有效期
* *
* @param loginUser 登录信息 * @param loginUser 登录信息
*/ */
public void refreshToken(LoginUser loginUser) public void refreshToken(LoginUser loginUser)
@@ -140,10 +140,10 @@ public class TokenService
String userKey = getTokenKey(loginUser.getToken()); String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
} }
/** /**
* 设置用户代理信息 * 设置用户代理信息
* *
* @param loginUser 登录信息 * @param loginUser 登录信息
*/ */
public void setUserAgent(LoginUser loginUser) public void setUserAgent(LoginUser loginUser)
@@ -155,7 +155,7 @@ public class TokenService
loginUser.setBrowser(userAgent.getBrowser().getName()); loginUser.setBrowser(userAgent.getBrowser().getName());
loginUser.setOs(userAgent.getOperatingSystem().getName()); loginUser.setOs(userAgent.getOperatingSystem().getName());
} }
/** /**
* 从数据声明生成令牌 * 从数据声明生成令牌
* *
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -148,15 +148,39 @@ public class GenController extends BaseController
} }
/** /**
* 生成代码 * 生成代码(下载方式)
*/
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/download/{tableName}")
public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
{
byte[] data = genTableService.downloadCode(tableName);
genCode(response, data);
}
/**
* 生成代码(自定义路径)
*/ */
@PreAuthorize("@ss.hasPermi('tool:gen:code')") @PreAuthorize("@ss.hasPermi('tool:gen:code')")
@Log(title = "代码生成", businessType = BusinessType.GENCODE) @Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/genCode/{tableName}") @GetMapping("/genCode/{tableName}")
public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException public AjaxResult genCode(@PathVariable("tableName") String tableName)
{ {
byte[] data = genTableService.generatorCode(tableName); genTableService.generatorCode(tableName);
genCode(response, data); return AjaxResult.success();
}
/**
* 同步数据库
*/
@PreAuthorize("@ss.hasPermi('tool:gen:edit')")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@GetMapping("/synchDb/{tableName}")
public AjaxResult synchDb(@PathVariable("tableName") String tableName)
{
genTableService.synchDb(tableName);
return AjaxResult.success();
} }
/** /**
@@ -168,7 +192,7 @@ public class GenController extends BaseController
public void batchGenCode(HttpServletResponse response, String tables) throws IOException public void batchGenCode(HttpServletResponse response, String tables) throws IOException
{ {
String[] tableNames = Convert.toStrArray(tables); String[] tableNames = Convert.toStrArray(tables);
byte[] data = genTableService.generatorCode(tableNames); byte[] data = genTableService.downloadCode(tableNames);
genCode(response, data); genCode(response, data);
} }
@@ -178,9 +202,11 @@ public class GenController extends BaseController
private void genCode(HttpServletResponse response, byte[] data) throws IOException private void genCode(HttpServletResponse response, byte[] data) throws IOException
{ {
response.reset(); response.reset();
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\""); response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
response.addHeader("Content-Length", "" + data.length); response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8"); response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream()); IOUtils.write(data, response.getOutputStream());
} }
} }
@@ -55,6 +55,12 @@ public class GenTable extends BaseEntity
@NotBlank(message = "作者不能为空") @NotBlank(message = "作者不能为空")
private String functionAuthor; private String functionAuthor;
/** 生成代码方式(0zip压缩包 1自定义路径) */
private String genType;
/** 生成路径(不填默认项目路径) */
private String genPath;
/** 主键信息 */ /** 主键信息 */
private GenTableColumn pkColumn; private GenTableColumn pkColumn;
@@ -74,6 +80,12 @@ public class GenTable extends BaseEntity
/** 树名称字段 */ /** 树名称字段 */
private String treeName; private String treeName;
/** 上级菜单ID字段 */
private String parentMenuId;
/** 上级菜单名称字段 */
private String parentMenuName;
public Long getTableId() public Long getTableId()
{ {
return tableId; return tableId;
@@ -174,6 +186,26 @@ public class GenTable extends BaseEntity
this.functionAuthor = functionAuthor; this.functionAuthor = functionAuthor;
} }
public String getGenType()
{
return genType;
}
public void setGenType(String genType)
{
this.genType = genType;
}
public String getGenPath()
{
return genPath;
}
public void setGenPath(String genPath)
{
this.genPath = genPath;
}
public GenTableColumn getPkColumn() public GenTableColumn getPkColumn()
{ {
return pkColumn; return pkColumn;
@@ -234,6 +266,26 @@ public class GenTable extends BaseEntity
this.treeName = treeName; this.treeName = treeName;
} }
public String getParentMenuId()
{
return parentMenuId;
}
public void setParentMenuId(String parentMenuId)
{
this.parentMenuId = parentMenuId;
}
public String getParentMenuName()
{
return parentMenuName;
}
public void setParentMenuName(String parentMenuName)
{
this.parentMenuName = parentMenuName;
}
public boolean isTree() public boolean isTree()
{ {
return isTree(this.tplCategory); return isTree(this.tplCategory);
@@ -268,4 +320,4 @@ public class GenTable extends BaseEntity
} }
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY); return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
} }
} }
@@ -59,7 +59,7 @@ public class GenTableColumn extends BaseEntity
/** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */ /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
private String queryType; private String queryType;
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件) */ /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、editor富文本控件 */
private String htmlType; private String htmlType;
/** 字典类型 */ /** 字典类型 */
@@ -340,7 +340,7 @@ public class GenTableColumn extends BaseEntity
public static boolean isUsableColumn(String javaField) public static boolean isUsableColumn(String javaField)
{ {
// isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单 // isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum"); return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
} }
public String readConverterExp() public String readConverterExp()
@@ -17,7 +17,7 @@ public interface GenTableColumnMapper
* @return 列信息 * @return 列信息
*/ */
public List<GenTableColumn> selectDbTableColumnsByName(String tableName); public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
/** /**
* 查询业务字段列表 * 查询业务字段列表
* *
@@ -42,6 +42,14 @@ public interface GenTableColumnMapper
*/ */
public int updateGenTableColumn(GenTableColumn genTableColumn); public int updateGenTableColumn(GenTableColumn genTableColumn);
/**
* 删除业务字段
*
* @param genTableColumns 列数据
* @return 结果
*/
public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
/** /**
* 批量删除业务字段 * 批量删除业务字段
* *
@@ -1,11 +1,13 @@
package com.ruoyi.generator.service; package com.ruoyi.generator.service;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@@ -21,9 +23,11 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants; 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.exception.CustomException; import com.ruoyi.common.exception.CustomException;
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.FileUtils;
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.mapper.GenTableColumnMapper; import com.ruoyi.generator.mapper.GenTableColumnMapper;
@@ -202,13 +206,13 @@ public class GenTableServiceImpl implements IGenTableService
} }
/** /**
* 生成代码 * 生成代码(下载方式)
* *
* @param tableName 表名称 * @param tableName 表名称
* @return 数据 * @return 数据
*/ */
@Override @Override
public byte[] generatorCode(String tableName) public byte[] downloadCode(String tableName)
{ {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream); ZipOutputStream zip = new ZipOutputStream(outputStream);
@@ -218,13 +222,85 @@ public class GenTableServiceImpl implements IGenTableService
} }
/** /**
* 批量生成代码 * 生成代码(自定义路径)
*
* @param tableName 表名称
*/
@Override
public void generatorCode(String tableName)
{
// 查询表信息
GenTable table = genTableMapper.selectGenTableByName(tableName);
// 查询列信息
List<GenTableColumn> columns = table.getColumns();
setPkColumn(table, columns);
VelocityInitializer.initVelocity();
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates)
{
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
{
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try
{
String path = getGenPath(table, template);
FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
}
catch (IOException e)
{
throw new CustomException("渲染模板失败,表名:" + table.getTableName());
}
}
}
}
/**
* 同步数据库
*
* @param tableName 表名称
*/
@Override
@Transactional
public void synchDb(String tableName)
{
GenTable table = genTableMapper.selectGenTableByName(tableName);
List<GenTableColumn> tableColumns = table.getColumns();
List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
dbTableColumns.forEach(column -> {
if (!tableColumnNames.contains(column.getColumnName()))
{
GenUtils.initColumnField(column, table);
genTableColumnMapper.insertGenTableColumn(column);
}
});
List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
if (StringUtils.isNotEmpty(delColumns))
{
genTableColumnMapper.deleteGenTableColumns(delColumns);
}
}
/**
* 批量生成代码(下载方式)
* *
* @param tableNames 表数组 * @param tableNames 表数组
* @return 数据 * @return 数据
*/ */
@Override @Override
public byte[] generatorCode(String[] tableNames) public byte[] downloadCode(String[] tableNames)
{ {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream); ZipOutputStream zip = new ZipOutputStream(outputStream);
@@ -337,9 +413,31 @@ 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);
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
genTable.setTreeCode(treeCode); genTable.setTreeCode(treeCode);
genTable.setTreeParentCode(treeParentCode); genTable.setTreeParentCode(treeParentCode);
genTable.setTreeName(treeName); genTable.setTreeName(treeName);
genTable.setParentMenuId(parentMenuId);
genTable.setParentMenuName(parentMenuName);
} }
} }
}
/**
* 获取代码生成地址
*
* @param table 业务表信息
* @param template 模板文件路径
* @return 生成地址
*/
public static String getGenPath(GenTable table, String template)
{
String genPath = table.getGenPath();
if (StringUtils.equals(genPath, "/"))
{
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
}
return genPath + File.separator + VelocityUtils.getFileName(template, table);
}
}
@@ -75,20 +75,35 @@ public interface IGenTableService
public Map<String, String> previewCode(Long tableId); public Map<String, String> previewCode(Long tableId);
/** /**
* 生成代码 * 生成代码(下载方式)
* *
* @param tableName 表名称 * @param tableName 表名称
* @return 数据 * @return 数据
*/ */
public byte[] generatorCode(String tableName); public byte[] downloadCode(String tableName);
/** /**
* 批量生成代码 * 生成代码(自定义路径)
*
* @param tableName 表名称
* @return 数据
*/
public void generatorCode(String tableName);
/**
* 同步数据库
*
* @param tableName 表名称
*/
public void synchDb(String tableName);
/**
* 批量生成代码(下载方式)
* *
* @param tableNames 表数组 * @param tableNames 表数组
* @return 数据 * @return 数据
*/ */
public byte[] generatorCode(String[] tableNames); public byte[] downloadCode(String[] tableNames);
/** /**
* 修改保存参数校验 * 修改保存参数校验
@@ -111,6 +111,11 @@ public class GenUtils
{ {
column.setHtmlType(GenConstants.HTML_SELECT); column.setHtmlType(GenConstants.HTML_SELECT);
} }
// 内容字段设置富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{
column.setHtmlType(GenConstants.HTML_EDITOR);
}
} }
/** /**
@@ -195,7 +200,7 @@ public class GenUtils
/** /**
* 关键字替换 * 关键字替换
* *
* @param name 需要被替换的名字 * @param text 需要被替换的名字
* @return 替换后的名字 * @return 替换后的名字
*/ */
public static String replaceText(String text) public static String replaceText(String text)
@@ -12,7 +12,7 @@ import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn; import com.ruoyi.generator.domain.GenTableColumn;
/** /**
* 代码生成模板处理 * 模板处理工具类
* *
* @author ruoyi * @author ruoyi
*/ */
@@ -24,9 +24,12 @@ public class VelocityUtils
/** mybatis空间路径 */ /** mybatis空间路径 */
private static final String MYBATIS_PATH = "main/resources/mapper"; private static final String MYBATIS_PATH = "main/resources/mapper";
/** 默认上级菜单,系统工具 */
private static final String DEFAULT_PARENT_MENU_ID = "3";
/** /**
* 设置模板变量信息 * 设置模板变量信息
* *
* @return 模板列表 * @return 模板列表
*/ */
public static VelocityContext prepareContext(GenTable genTable) public static VelocityContext prepareContext(GenTable genTable)
@@ -55,6 +58,7 @@ public class VelocityUtils
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
velocityContext.put("columns", genTable.getColumns()); velocityContext.put("columns", genTable.getColumns());
velocityContext.put("table", genTable); velocityContext.put("table", genTable);
setMenuVelocityContext(velocityContext, genTable);
if (GenConstants.TPL_TREE.equals(tplCategory)) if (GenConstants.TPL_TREE.equals(tplCategory))
{ {
setTreeVelocityContext(velocityContext, genTable); setTreeVelocityContext(velocityContext, genTable);
@@ -62,6 +66,14 @@ public class VelocityUtils
return velocityContext; return velocityContext;
} }
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
{
String options = genTable.getOptions();
JSONObject paramsObj = JSONObject.parseObject(options);
String parentMenuId = getParentMenuId(paramsObj);
context.put("parentMenuId", parentMenuId);
}
public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
{ {
String options = genTable.getOptions(); String options = genTable.getOptions();
@@ -86,7 +98,7 @@ public class VelocityUtils
/** /**
* 获取模板信息 * 获取模板信息
* *
* @return 模板列表 * @return 模板列表
*/ */
public static List<String> getTemplateList(String tplCategory) public static List<String> getTemplateList(String tplCategory)
@@ -176,7 +188,7 @@ public class VelocityUtils
/** /**
* 获取包前缀 * 获取包前缀
* *
* @param packageName 包名称 * @param packageName 包名称
* @return 包前缀名称 * @return 包前缀名称
*/ */
@@ -189,8 +201,8 @@ public class VelocityUtils
/** /**
* 根据列类型获取导入包 * 根据列类型获取导入包
* *
* @param column 列集合 * @param columns 列集合
* @return 返回需要导入的包列表 * @return 返回需要导入的包列表
*/ */
public static HashSet<String> getImportList(List<GenTableColumn> columns) public static HashSet<String> getImportList(List<GenTableColumn> columns)
@@ -213,7 +225,7 @@ public class VelocityUtils
/** /**
* 获取权限前缀 * 获取权限前缀
* *
* @param moduleName 模块名称 * @param moduleName 模块名称
* @param businessName 业务名称 * @param businessName 业务名称
* @return 返回权限前缀 * @return 返回权限前缀
@@ -221,13 +233,27 @@ public class VelocityUtils
public static String getPermissionPrefix(String moduleName, String businessName) public static String getPermissionPrefix(String moduleName, String businessName)
{ {
return StringUtils.format("{}:{}", moduleName, businessName); return StringUtils.format("{}:{}", moduleName, businessName);
}
/**
* 获取上级菜单ID字段
*
* @param paramsObj 生成其他选项
* @return 上级菜单ID字段
*/
public static String getParentMenuId(JSONObject paramsObj)
{
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
{
return paramsObj.getString(GenConstants.PARENT_MENU_ID);
}
return DEFAULT_PARENT_MENU_ID;
} }
/** /**
* 获取树编码 * 获取树编码
* *
* @param options 生成其他选项 * @param paramsObj 生成其他选项
* @return 树编码 * @return 树编码
*/ */
public static String getTreecode(JSONObject paramsObj) public static String getTreecode(JSONObject paramsObj)
@@ -236,13 +262,13 @@ public class VelocityUtils
{ {
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
} }
return ""; return StringUtils.EMPTY;
} }
/** /**
* 获取树父编码 * 获取树父编码
* *
* @param options 生成其他选项 * @param paramsObj 生成其他选项
* @return 树父编码 * @return 树父编码
*/ */
public static String getTreeParentCode(JSONObject paramsObj) public static String getTreeParentCode(JSONObject paramsObj)
@@ -251,13 +277,13 @@ public class VelocityUtils
{ {
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
} }
return ""; return StringUtils.EMPTY;
} }
/** /**
* 获取树名称 * 获取树名称
* *
* @param options 生成其他选项 * @param paramsObj 生成其他选项
* @return 树名称 * @return 树名称
*/ */
public static String getTreeName(JSONObject paramsObj) public static String getTreeName(JSONObject paramsObj)
@@ -266,12 +292,12 @@ public class VelocityUtils
{ {
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
} }
return ""; return StringUtils.EMPTY;
} }
/** /**
* 获取需要在哪一列上面显示展开按钮 * 获取需要在哪一列上面显示展开按钮
* *
* @param genTable 业务表对象 * @param genTable 业务表对象
* @return 展开按钮列序号 * @return 展开按钮列序号
*/ */
@@ -117,4 +117,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</delete> </delete>
<delete id="deleteGenTableColumns">
delete from gen_table_column where column_id in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.columnId}
</foreach>
</delete>
</mapper> </mapper>
@@ -15,6 +15,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<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="genType" column="gen_type" />
<result property="genPath" column="gen_path" />
<result property="options" column="options" /> <result property="options" column="options" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
@@ -50,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectGenTableVo"> <sql id="selectGenTableVo">
select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, options, create_by, create_time, update_by, update_time, remark from gen_table select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
</sql> </sql>
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult"> <select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
@@ -106,7 +108,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.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.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort 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
@@ -114,7 +116,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.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.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort 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
@@ -132,6 +134,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<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="genType != null and genType != ''">gen_type,</if>
<if test="genPath != null and genPath != ''">gen_path,</if>
<if test="remark != null and remark != ''">remark,</if> <if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if> <if test="createBy != null and createBy != ''">create_by,</if>
create_time create_time
@@ -145,6 +149,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<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="genType != null and genType != ''">#{genType},</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>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate() sysdate()
@@ -158,6 +164,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if> <if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</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="genType != null and genType != ''">gen_type = #{genType},</if>
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if> <if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</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>
@@ -178,4 +186,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</delete> </delete>
</mapper> </mapper>
@@ -1,22 +1,22 @@
-- 菜单 SQL -- 菜单 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单'); values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
-- 按钮父菜单ID -- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID(); SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL -- 按钮 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}查询', @parentId, '1', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', ''); values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}新增', @parentId, '2', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', ''); values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}修改', @parentId, '3', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', ''); values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}删除', @parentId, '4', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', ''); values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}导出', @parentId, '5', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', ''); values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns) #foreach($column in $columns)
#if($column.query) #if($column.query)
#set($dictType=$column.dictType) #set($dictType=$column.dictType)
@@ -51,23 +51,23 @@
#end #end
#end #end
<el-form-item> <el-form-item>
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button <el-button
class="filter-item"
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button>
<el-button
class="filter-item"
type="primary" type="primary"
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-form-item> </el-col>
</el-form> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table <el-table
v-loading="loading" v-loading="loading"
@@ -139,8 +139,12 @@
<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>
#elseif($column.htmlType == "select" && "" != $dictType) #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}"> <el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option <el-option
v-for="dict in ${field}Options" v-for="dict in ${field}Options"
@@ -152,11 +156,28 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "select" && $dictType) #elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}"> <el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}"> <el-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>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${field}Options"
:key="dict.dictValue"
:label="dict.dictValue">
{{dict.dictLabel}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType) #elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<el-radio-group v-model="form.${field}"> <el-radio-group v-model="form.${field}">
@@ -204,14 +225,30 @@
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor';
#break
#end
#end
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
components: { Treeselect }, components: {
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
Treeselect
},
data() { data() {
return { return {
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 显示搜索条件
showSearch: true,
// ${functionName}表格数据 // ${functionName}表格数据
${businessName}List: [], ${businessName}List: [],
// ${functionName}树选项 // ${functionName}树选项
@@ -236,7 +273,7 @@ export default {
queryParams: { queryParams: {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.query) #if($column.query)
$column.javaField: undefined#if($velocityCount != $columns.size()),#end $column.javaField: null#if($velocityCount != $columns.size()),#end
#end #end
#end #end
@@ -253,9 +290,8 @@ export default {
#else #else
#set($comment=$column.columnComment) #set($comment=$column.columnComment)
#end #end
#set($comment=$column.columnComment)
$column.javaField: [ $column.javaField: [
{ required: true, message: "$comment不能为空", trigger: "blur" } { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($velocityCount != $columns.size()),#end ]#if($velocityCount != $columns.size()),#end
#end #end
@@ -312,7 +348,7 @@ export default {
#end #end
// $comment字典翻译 // $comment字典翻译
${column.javaField}Format(row, column) { ${column.javaField}Format(row, column) {
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField}); return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
}, },
#end #end
#end #end
@@ -326,10 +362,13 @@ export default {
this.form = { this.form = {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "radio") #if($column.htmlType == "radio")
$column.javaField: "0"#if($velocityCount != $columns.size()),#end $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($velocityCount != $columns.size()),#end
#else #else
$column.javaField: undefined#if($velocityCount != $columns.size()),#end $column.javaField: null#if($velocityCount != $columns.size()),#end
#end #end
#end #end
@@ -356,20 +395,30 @@ export default {
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
this.getTreeselect(); this.getTreeselect();
if (row != undefined) { if (row != null) {
this.form.${treeParentCode} = row.${treeCode}; this.form.${treeParentCode} = row.${treeCode};
} }
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)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end
#end
this.open = true; this.open = true;
this.title = "修改${functionName}"; this.title = "修改${functionName}";
}); });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm() {
this.#[[$]]#refs["form"].validate(valid => { this.#[[$]]#refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.${pkColumn.javaField} != undefined) { #foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end
#end
if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.msgSuccess("修改成功"); this.msgSuccess("修改成功");
@@ -404,4 +453,4 @@ export default {
} }
} }
}; };
</script> </script>
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns) #foreach($column in $columns)
#if($column.query) #if($column.query)
#set($dictType=$column.dictType) #set($dictType=$column.dictType)
@@ -51,7 +51,7 @@
#end #end
#end #end
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -95,6 +95,7 @@
v-hasPermi="['${moduleName}:${businessName}:export']" v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
@@ -167,8 +168,12 @@
<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>
#elseif($column.htmlType == "select" && "" != $dictType) #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}"> <el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option <el-option
v-for="dict in ${field}Options" v-for="dict in ${field}Options"
@@ -180,11 +185,28 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "select" && $dictType) #elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}"> <el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}"> <el-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>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${field}Options"
:key="dict.dictValue"
:label="dict.dictValue">
{{dict.dictLabel}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType) #elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<el-radio-group v-model="form.${field}"> <el-radio-group v-model="form.${field}">
@@ -230,9 +252,21 @@
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor';
#break
#end
#end
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
components: { Editor },
#break
#end
#end
data() { data() {
return { return {
// 遮罩层 // 遮罩层
@@ -243,6 +277,8 @@ export default {
single: true, single: true,
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// ${functionName}表格数据 // ${functionName}表格数据
@@ -269,7 +305,7 @@ export default {
pageSize: 10, pageSize: 10,
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.query) #if($column.query)
$column.javaField: undefined#if($velocityCount != $columns.size()),#end $column.javaField: null#if($velocityCount != $columns.size()),#end
#end #end
#end #end
@@ -286,9 +322,8 @@ export default {
#else #else
#set($comment=$column.columnComment) #set($comment=$column.columnComment)
#end #end
#set($comment=$column.columnComment)
$column.javaField: [ $column.javaField: [
{ required: true, message: "$comment不能为空", trigger: "blur" } { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($velocityCount != $columns.size()),#end ]#if($velocityCount != $columns.size()),#end
#end #end
@@ -326,7 +361,7 @@ export default {
#end #end
// $comment字典翻译 // $comment字典翻译
${column.javaField}Format(row, column) { ${column.javaField}Format(row, column) {
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField}); return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
}, },
#end #end
#end #end
@@ -340,10 +375,13 @@ export default {
this.form = { this.form = {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "radio") #if($column.htmlType == "radio")
$column.javaField: "0"#if($velocityCount != $columns.size()),#end $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($velocityCount != $columns.size()),#end
#else #else
$column.javaField: undefined#if($velocityCount != $columns.size()),#end $column.javaField: null#if($velocityCount != $columns.size()),#end
#end #end
#end #end
@@ -363,7 +401,7 @@ export default {
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.${pkColumn.javaField}) this.ids = selection.map(item => item.${pkColumn.javaField})
this.single = selection.length!=1 this.single = selection.length!==1
this.multiple = !selection.length this.multiple = !selection.length
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
@@ -378,15 +416,25 @@ export default {
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)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end
#end
this.open = true; this.open = true;
this.title = "修改${functionName}"; this.title = "修改${functionName}";
}); });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm() {
this.#[[$]]#refs["form"].validate(valid => { this.#[[$]]#refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.${pkColumn.javaField} != undefined) { #foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end
#end
if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.msgSuccess("修改成功"); this.msgSuccess("修改成功");
@@ -435,4 +483,4 @@ export default {
} }
} }
}; };
</script> </script>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -88,7 +88,7 @@ public class SysJob extends BaseEntity implements Serializable
} }
@NotBlank(message = "调用目标字符串不能为空") @NotBlank(message = "调用目标字符串不能为空")
@Size(min = 0, max = 1000, message = "调用目标字符串长度不能超过500个字符") @Size(min = 0, max = 500, message = "调用目标字符串长度不能超过500个字符")
public String getInvokeTarget() public String getInvokeTarget()
{ {
return invokeTarget; return invokeTarget;
@@ -66,7 +66,7 @@ public abstract class AbstractQuartzJob implements Job
* 执行后 * 执行后
* *
* @param context 工作执行上下文对象 * @param context 工作执行上下文对象
* @param sysScheduleJob 系统计划任务 * @param sysJob 系统计划任务
*/ */
protected void after(JobExecutionContext context, SysJob sysJob, Exception e) protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
{ {
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.2.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -13,10 +13,15 @@ public class MetaVo
private String title; private String title;
/** /**
* 设置该路由的图标,对应路径src/icons/svg * 设置该路由的图标,对应路径src/assets/icons/svg
*/ */
private String icon; private String icon;
/**
* 设置为true,则不会被 <keep-alive>缓存
*/
private boolean noCache;
public MetaVo() public MetaVo()
{ {
} }
@@ -27,6 +32,23 @@ public class MetaVo
this.icon = icon; this.icon = icon;
} }
public MetaVo(String title, String icon, boolean noCache)
{
this.title = title;
this.icon = icon;
this.noCache = noCache;
}
public boolean isNoCache()
{
return noCache;
}
public void setNoCache(boolean noCache)
{
this.noCache = noCache;
}
public String getTitle() public String getTitle()
{ {
return title; return title;
@@ -23,9 +23,10 @@ public interface SysDeptMapper
* 根据角色ID查询部门树信息 * 根据角色ID查询部门树信息
* *
* @param roleId 角色ID * @param roleId 角色ID
* @param deptCheckStrictly 部门树选择项是否关联显示
* @return 选中部门列表 * @return 选中部门列表
*/ */
public List<Integer> selectDeptListByRoleId(Long roleId); public List<Integer> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
/** /**
* 根据部门ID查询信息 * 根据部门ID查询信息
@@ -6,14 +6,14 @@ import com.ruoyi.common.core.domain.entity.SysMenu;
/** /**
* 菜单表 数据层 * 菜单表 数据层
* *
* @author ruoyi * @author ruoyi
*/ */
public interface SysMenuMapper public interface SysMenuMapper
{ {
/** /**
* 查询系统菜单列表 * 查询系统菜单列表
* *
* @param menu 菜单信息 * @param menu 菜单信息
* @return 菜单列表 * @return 菜单列表
*/ */
@@ -21,14 +21,14 @@ public interface SysMenuMapper
/** /**
* 根据用户所有权限 * 根据用户所有权限
* *
* @return 权限列表 * @return 权限列表
*/ */
public List<String> selectMenuPerms(); public List<String> selectMenuPerms();
/** /**
* 根据用户查询系统菜单列表 * 根据用户查询系统菜单列表
* *
* @param menu 菜单信息 * @param menu 菜单信息
* @return 菜单列表 * @return 菜单列表
*/ */
@@ -36,7 +36,7 @@ public interface SysMenuMapper
/** /**
* 根据用户ID查询权限 * 根据用户ID查询权限
* *
* @param userId 用户ID * @param userId 用户ID
* @return 权限列表 * @return 权限列表
*/ */
@@ -44,15 +44,15 @@ public interface SysMenuMapper
/** /**
* 根据用户ID查询菜单 * 根据用户ID查询菜单
* *
* @return 菜单列表 * @return 菜单列表
*/ */
public List<SysMenu> selectMenuTreeAll(); public List<SysMenu> selectMenuTreeAll();
/** /**
* 根据用户ID查询菜单 * 根据用户ID查询菜单
* *
* @param username 用户ID * @param userId 用户ID
* @return 菜单列表 * @return 菜单列表
*/ */
public List<SysMenu> selectMenuTreeByUserId(Long userId); public List<SysMenu> selectMenuTreeByUserId(Long userId);
@@ -61,13 +61,14 @@ public interface SysMenuMapper
* 根据角色ID查询菜单树信息 * 根据角色ID查询菜单树信息
* *
* @param roleId 角色ID * @param roleId 角色ID
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表 * @return 选中菜单列表
*/ */
public List<Integer> selectMenuListByRoleId(Long roleId); public List<Integer> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
/** /**
* 根据菜单ID查询信息 * 根据菜单ID查询信息
* *
* @param menuId 菜单ID * @param menuId 菜单ID
* @return 菜单信息 * @return 菜单信息
*/ */
@@ -75,7 +76,7 @@ public interface SysMenuMapper
/** /**
* 是否存在菜单子节点 * 是否存在菜单子节点
* *
* @param menuId 菜单ID * @param menuId 菜单ID
* @return 结果 * @return 结果
*/ */
@@ -83,7 +84,7 @@ public interface SysMenuMapper
/** /**
* 新增菜单信息 * 新增菜单信息
* *
* @param menu 菜单信息 * @param menu 菜单信息
* @return 结果 * @return 结果
*/ */
@@ -91,7 +92,7 @@ public interface SysMenuMapper
/** /**
* 修改菜单信息 * 修改菜单信息
* *
* @param menu 菜单信息 * @param menu 菜单信息
* @return 结果 * @return 结果
*/ */
@@ -99,7 +100,7 @@ public interface SysMenuMapper
/** /**
* 删除菜单管理信息 * 删除菜单管理信息
* *
* @param menuId 菜单ID * @param menuId 菜单ID
* @return 结果 * @return 结果
*/ */
@@ -107,7 +108,7 @@ public interface SysMenuMapper
/** /**
* 校验菜单名称是否唯一 * 校验菜单名称是否唯一
* *
* @param menuName 菜单名称 * @param menuName 菜单名称
* @param parentId 父菜单ID * @param parentId 父菜单ID
* @return 结果 * @return 结果
@@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.mapper.SysConfigMapper;
@@ -138,6 +139,14 @@ public class SysConfigServiceImpl implements ISysConfigService
@Override @Override
public int deleteConfigByIds(Long[] configIds) public int deleteConfigByIds(Long[] configIds)
{ {
for (Long configId : configIds)
{
SysConfig config = selectConfigById(configId);
if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
{
throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
}
}
int count = configMapper.deleteConfigByIds(configIds); int count = configMapper.deleteConfigByIds(configIds);
if (count > 0) if (count > 0)
{ {
@@ -10,9 +10,11 @@ import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect; import com.ruoyi.common.core.domain.TreeSelect;
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.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysDeptService;
/** /**
@@ -26,6 +28,9 @@ public class SysDeptServiceImpl implements ISysDeptService
@Autowired @Autowired
private SysDeptMapper deptMapper; private SysDeptMapper deptMapper;
@Autowired
private SysRoleMapper roleMapper;
/** /**
* 查询部门管理数据 * 查询部门管理数据
* *
@@ -93,7 +98,8 @@ public class SysDeptServiceImpl implements ISysDeptService
@Override @Override
public List<Integer> selectDeptListByRoleId(Long roleId) public List<Integer> selectDeptListByRoleId(Long roleId)
{ {
return deptMapper.selectDeptListByRoleId(roleId); SysRole role = roleMapper.selectRoleById(roleId);
return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
} }
/** /**
@@ -267,13 +273,7 @@ public class SysDeptServiceImpl implements ISysDeptService
{ {
if (hasChild(list, tChild)) if (hasChild(list, tChild))
{ {
// 判断是否有子节点 recursionFn(list, tChild);
Iterator<SysDept> it = childList.iterator();
while (it.hasNext())
{
SysDept n = (SysDept) it.next();
recursionFn(list, n);
}
} }
} }
} }
@@ -76,12 +76,12 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
public List<SysDictData> selectDictDataByType(String dictType) public List<SysDictData> selectDictDataByType(String dictType)
{ {
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType); List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
if (StringUtils.isNotNull(dictDatas)) if (StringUtils.isNotEmpty(dictDatas))
{ {
return dictDatas; return dictDatas;
} }
dictDatas = dictDataMapper.selectDictDataByType(dictType); dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (StringUtils.isNotNull(dictDatas)) if (StringUtils.isNotEmpty(dictDatas))
{ {
DictUtils.setDictCache(dictType, dictDatas); DictUtils.setDictCache(dictType, dictDatas);
return dictDatas; return dictDatas;
@@ -13,12 +13,14 @@ import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect; import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
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.system.domain.vo.MetaVo; import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.mapper.SysMenuMapper; import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper; import com.ruoyi.system.mapper.SysRoleMenuMapper;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysMenuService;
@@ -35,6 +37,9 @@ public class SysMenuServiceImpl implements ISysMenuService
@Autowired @Autowired
private SysMenuMapper menuMapper; private SysMenuMapper menuMapper;
@Autowired
private SysRoleMapper roleMapper;
@Autowired @Autowired
private SysRoleMenuMapper roleMenuMapper; private SysRoleMenuMapper roleMenuMapper;
@@ -124,7 +129,8 @@ public class SysMenuServiceImpl implements ISysMenuService
@Override @Override
public List<Integer> selectMenuListByRoleId(Long roleId) public List<Integer> selectMenuListByRoleId(Long roleId)
{ {
return menuMapper.selectMenuListByRoleId(roleId); SysRole role = roleMapper.selectRoleById(roleId);
return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
} }
/** /**
@@ -144,7 +150,7 @@ public class SysMenuServiceImpl implements ISysMenuService
router.setName(getRouteName(menu)); router.setName(getRouteName(menu));
router.setPath(getRouterPath(menu)); router.setPath(getRouterPath(menu));
router.setComponent(getComponent(menu)); router.setComponent(getComponent(menu));
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache())));
List<SysMenu> cMenus = menu.getChildren(); List<SysMenu> cMenus = menu.getChildren();
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
{ {
@@ -159,7 +165,7 @@ public class SysMenuServiceImpl implements ISysMenuService
children.setPath(menu.getPath()); children.setPath(menu.getPath());
children.setComponent(menu.getComponent()); children.setComponent(menu.getComponent());
children.setName(StringUtils.capitalize(menu.getPath())); children.setName(StringUtils.capitalize(menu.getPath()));
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache())));
childrenList.add(children); childrenList.add(children);
router.setChildren(childrenList); router.setChildren(childrenList);
} }
@@ -178,14 +184,19 @@ public class SysMenuServiceImpl implements ISysMenuService
public List<SysMenu> buildMenuTree(List<SysMenu> menus) public List<SysMenu> buildMenuTree(List<SysMenu> menus)
{ {
List<SysMenu> returnList = new ArrayList<SysMenu>(); List<SysMenu> returnList = new ArrayList<SysMenu>();
List<Long> tempList = new ArrayList<Long>();
for (SysMenu dept : menus)
{
tempList.add(dept.getMenuId());
}
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();) for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
{ {
SysMenu t = (SysMenu) iterator.next(); SysMenu menu = (SysMenu) iterator.next();
// 根据传入的某个父节点ID,遍历该父节点的所有子节点 // 如果是顶级节点, 遍历该父节点的所有子节点
if (t.getParentId() == 0) if (!tempList.contains(menu.getParentId()))
{ {
recursionFn(menus, t); recursionFn(menus, menu);
returnList.add(t); returnList.add(menu);
} }
} }
if (returnList.isEmpty()) if (returnList.isEmpty())
@@ -406,13 +417,7 @@ public class SysMenuServiceImpl implements ISysMenuService
{ {
if (hasChild(list, tChild)) if (hasChild(list, tChild))
{ {
// 判断是否有子节点 recursionFn(list, tChild);
Iterator<SysMenu> it = childList.iterator();
while (it.hasNext())
{
SysMenu n = (SysMenu) it.next();
recursionFn(list, n);
}
} }
} }
} }
@@ -75,7 +75,7 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
@Override @Override
public SysUserOnline loginUserToUserOnline(LoginUser user) public SysUserOnline loginUserToUserOnline(LoginUser user)
{ {
if (StringUtils.isNull(user) && StringUtils.isNull(user.getUser())) if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser()))
{ {
return null; return null;
} }
@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult"> <select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
<include refid="selectConfigVo"/> <include refid="selectConfigVo"/>
where config_key = #{configKey} where config_key = #{configKey} limit 1
</select> </select>
<insert id="insertConfig" parameterType="SysConfig"> <insert id="insertConfig" parameterType="SysConfig">
@@ -44,12 +44,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by d.parent_id, d.order_num order by d.parent_id, d.order_num
</select> </select>
<select id="selectDeptListByRoleId" parameterType="Long" resultType="Integer"> <select id="selectDeptListByRoleId" resultType="Integer">
select d.dept_id, d.parent_id select d.dept_id
from sys_dept d from sys_dept d
left join sys_role_dept rd on d.dept_id = rd.dept_id left join sys_role_dept rd on d.dept_id = rd.dept_id
where rd.role_id = #{roleId} where rd.role_id = #{roleId}
and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId}) <if test="deptCheckStrictly">
and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
</if>
order by d.parent_id, d.order_num order by d.parent_id, d.order_num
</select> </select>
@@ -64,7 +66,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="hasChildByDeptId" parameterType="Long" resultType="int"> <select id="hasChildByDeptId" parameterType="Long" resultType="int">
select count(1) from sys_dept select count(1) from sys_dept
where del_flag = '0' and parent_id = #{deptId} where del_flag = '0' and parent_id = #{deptId} limit 1
</select> </select>
<select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult"> <select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
@@ -77,7 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkDeptNameUnique" resultMap="SysDeptResult"> <select id="checkDeptNameUnique" resultMap="SysDeptResult">
<include refid="selectDeptVo"/> <include refid="selectDeptVo"/>
where dept_name=#{deptName} and parent_id = #{parentId} where dept_name=#{deptName} and parent_id = #{parentId} limit 1
</select> </select>
<insert id="insertDept" parameterType="SysDept"> <insert id="insertDept" parameterType="SysDept">
@@ -57,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult"> <select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult">
<include refid="selectDictTypeVo"/> <include refid="selectDictTypeVo"/>
where dict_type = #{dictType} where dict_type = #{dictType} limit 1
</select> </select>
<delete id="deleteDictTypeById" parameterType="Long"> <delete id="deleteDictTypeById" parameterType="Long">
@@ -13,6 +13,7 @@
<result property="path" column="path" /> <result property="path" column="path" />
<result property="component" column="component" /> <result property="component" column="component" />
<result property="isFrame" column="is_frame" /> <result property="isFrame" column="is_frame" />
<result property="isCache" column="is_cache" />
<result property="menuType" column="menu_type" /> <result property="menuType" column="menu_type" />
<result property="visible" column="visible" /> <result property="visible" column="visible" />
<result property="status" column="status" /> <result property="status" column="status" />
@@ -26,7 +27,7 @@
</resultMap> </resultMap>
<sql id="selectMenuVo"> <sql id="selectMenuVo">
select menu_id, menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time select menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
from sys_menu from sys_menu
</sql> </sql>
@@ -47,13 +48,13 @@
</select> </select>
<select id="selectMenuTreeAll" resultMap="SysMenuResult"> <select id="selectMenuTreeAll" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0 from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
order by m.parent_id, m.order_num order by m.parent_id, m.order_num
</select> </select>
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult"> <select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id left join sys_user_role ur on rm.role_id = ur.role_id
@@ -72,7 +73,7 @@
</select> </select>
<select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult"> <select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id left join sys_user_role ur on rm.role_id = ur.role_id
@@ -82,12 +83,14 @@
order by m.parent_id, m.order_num order by m.parent_id, m.order_num
</select> </select>
<select id="selectMenuListByRoleId" parameterType="Long" resultType="Integer"> <select id="selectMenuListByRoleId" resultType="Integer">
select m.menu_id, m.parent_id select m.menu_id
from sys_menu m from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id left join sys_role_menu rm on m.menu_id = rm.menu_id
where rm.role_id = #{roleId} where rm.role_id = #{roleId}
and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId}) <if test="menuCheckStrictly">
and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
</if>
order by m.parent_id, m.order_num order by m.parent_id, m.order_num
</select> </select>
@@ -118,7 +121,7 @@
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult"> <select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
<include refid="selectMenuVo"/> <include refid="selectMenuVo"/>
where menu_name=#{menuName} and parent_id = #{parentId} where menu_name=#{menuName} and parent_id = #{parentId} limit 1
</select> </select>
<update id="updateMenu" parameterType="SysMenu"> <update id="updateMenu" parameterType="SysMenu">
@@ -130,6 +133,7 @@
<if test="path != null and path != ''">path = #{path},</if> <if test="path != null and path != ''">path = #{path},</if>
<if test="component != null and component != ''">component = #{component},</if> <if test="component != null and component != ''">component = #{component},</if>
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if> <if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if> <if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
<if test="visible != null">visible = #{visible},</if> <if test="visible != null">visible = #{visible},</if>
<if test="status != null">status = #{status},</if> <if test="status != null">status = #{status},</if>
@@ -151,6 +155,7 @@
<if test="path != null and path != ''">path,</if> <if test="path != null and path != ''">path,</if>
<if test="component != null and component != ''">component,</if> <if test="component != null and component != ''">component,</if>
<if test="isFrame != null and isFrame != ''">is_frame,</if> <if test="isFrame != null and isFrame != ''">is_frame,</if>
<if test="isCache != null and isCache != ''">is_cache,</if>
<if test="menuType != null and menuType != ''">menu_type,</if> <if test="menuType != null and menuType != ''">menu_type,</if>
<if test="visible != null">visible,</if> <if test="visible != null">visible,</if>
<if test="status != null">status,</if> <if test="status != null">status,</if>
@@ -167,6 +172,7 @@
<if test="path != null and path != ''">#{path},</if> <if test="path != null and path != ''">#{path},</if>
<if test="component != null and component != ''">#{component},</if> <if test="component != null and component != ''">#{component},</if>
<if test="isFrame != null and isFrame != ''">#{isFrame},</if> <if test="isFrame != null and isFrame != ''">#{isFrame},</if>
<if test="isCache != null and isCache != ''">#{isCache},</if>
<if test="menuType != null and menuType != ''">#{menuType},</if> <if test="menuType != null and menuType != ''">#{menuType},</if>
<if test="visible != null">#{visible},</if> <if test="visible != null">#{visible},</if>
<if test="status != null">#{status},</if> <if test="status != null">#{status},</if>
@@ -18,7 +18,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectNoticeVo"> <sql id="selectNoticeVo">
select notice_id, notice_title, notice_type, notice_content, status, create_by, create_time, update_by, update_time, remark select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark
from sys_notice from sys_notice
</sql> </sql>
@@ -64,12 +64,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult"> <select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult">
<include refid="selectPostVo"/> <include refid="selectPostVo"/>
where post_name=#{postName} where post_name=#{postName} limit 1
</select> </select>
<select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult"> <select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult">
<include refid="selectPostVo"/> <include refid="selectPostVo"/>
where post_code=#{postCode} where post_code=#{postCode} limit 1
</select> </select>
<update id="updatePost" parameterType="SysPost"> <update id="updatePost" parameterType="SysPost">
@@ -5,22 +5,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.ruoyi.system.mapper.SysRoleMapper"> <mapper namespace="com.ruoyi.system.mapper.SysRoleMapper">
<resultMap type="SysRole" id="SysRoleResult"> <resultMap type="SysRole" id="SysRoleResult">
<id property="roleId" column="role_id" /> <id property="roleId" column="role_id" />
<result property="roleName" column="role_name" /> <result property="roleName" column="role_name" />
<result property="roleKey" column="role_key" /> <result property="roleKey" column="role_key" />
<result property="roleSort" column="role_sort" /> <result property="roleSort" column="role_sort" />
<result property="dataScope" column="data_scope" /> <result property="dataScope" column="data_scope" />
<result property="status" column="status" /> <result property="menuCheckStrictly" column="menu_check_strictly" />
<result property="delFlag" column="del_flag" /> <result property="deptCheckStrictly" column="dept_check_strictly" />
<result property="createBy" column="create_by" /> <result property="status" column="status" />
<result property="createTime" column="create_time" /> <result property="delFlag" column="del_flag" />
<result property="updateBy" column="update_by" /> <result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" /> <result property="createTime" column="create_time" />
<result property="remark" column="remark" /> <result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap> </resultMap>
<sql id="selectRoleVo"> <sql id="selectRoleVo">
select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
r.status, r.del_flag, r.create_time, r.remark r.status, r.del_flag, r.create_time, r.remark
from sys_role r from sys_role r
left join sys_user_role ur on ur.role_id = r.role_id left join sys_user_role ur on ur.role_id = r.role_id
@@ -80,12 +82,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult"> <select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/> <include refid="selectRoleVo"/>
where r.role_name=#{roleName} where r.role_name=#{roleName} limit 1
</select> </select>
<select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult"> <select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/> <include refid="selectRoleVo"/>
where r.role_key=#{roleKey} where r.role_key=#{roleKey} limit 1
</select> </select>
<insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId"> <insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId">
@@ -95,6 +97,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">role_key,</if> <if test="roleKey != null and roleKey != ''">role_key,</if>
<if test="roleSort != null and roleSort != ''">role_sort,</if> <if test="roleSort != null and roleSort != ''">role_sort,</if>
<if test="dataScope != null and dataScope != ''">data_scope,</if> <if test="dataScope != null and dataScope != ''">data_scope,</if>
<if test="menuCheckStrictly != null">menu_check_strictly,</if>
<if test="deptCheckStrictly != null">dept_check_strictly,</if>
<if test="status != null and status != ''">status,</if> <if test="status != null and status != ''">status,</if>
<if test="remark != null and remark != ''">remark,</if> <if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if> <if test="createBy != null and createBy != ''">create_by,</if>
@@ -105,6 +109,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">#{roleKey},</if> <if test="roleKey != null and roleKey != ''">#{roleKey},</if>
<if test="roleSort != null and roleSort != ''">#{roleSort},</if> <if test="roleSort != null and roleSort != ''">#{roleSort},</if>
<if test="dataScope != null and dataScope != ''">#{dataScope},</if> <if test="dataScope != null and dataScope != ''">#{dataScope},</if>
<if test="menuCheckStrictly != null">#{menuCheckStrictly},</if>
<if test="deptCheckStrictly != null">#{deptCheckStrictly},</if>
<if test="status != null and status != ''">#{status},</if> <if test="status != null and status != ''">#{status},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
@@ -119,6 +125,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">role_key = #{roleKey},</if> <if test="roleKey != null and roleKey != ''">role_key = #{roleKey},</if>
<if test="roleSort != null and roleSort != ''">role_sort = #{roleSort},</if> <if test="roleSort != null and roleSort != ''">role_sort = #{roleSort},</if>
<if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</if> <if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</if>
<if test="menuCheckStrictly != null">menu_check_strictly = #{menuCheckStrictly},</if>
<if test="deptCheckStrictly != null">dept_check_strictly = #{deptCheckStrictly},</if>
<if test="status != null and status != ''">status = #{status},</if> <if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if> <if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
@@ -10,7 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<select id="checkMenuExistRole" resultType="Integer"> <select id="checkMenuExistRole" resultType="Integer">
select count(1) from sys_role_menu where menu_id = #{menuId} select count(1) from sys_role_menu where menu_id = #{menuId}
</select> </select>
<delete id="deleteRoleMenuByRoleId" parameterType="Long"> <delete id="deleteRoleMenuByRoleId" parameterType="Long">
@@ -75,7 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d') AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
</if> </if>
<if test="deptId != null and deptId != 0"> <if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET (#{deptId},ancestors) )) AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
</if> </if>
<!-- 数据范围过滤 --> <!-- 数据范围过滤 -->
${params.dataScope} ${params.dataScope}
@@ -92,15 +92,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="checkUserNameUnique" parameterType="String" resultType="int"> <select id="checkUserNameUnique" parameterType="String" resultType="int">
select count(1) from sys_user where user_name = #{userName} select count(1) from sys_user where user_name = #{userName} limit 1
</select> </select>
<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult"> <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} limit 1
</select> </select>
<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
select user_id, email from sys_user where email = #{email} select user_id, email from sys_user where email = #{email} limit 1
</select> </select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId"> <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
+10 -2
View File
@@ -1,5 +1,13 @@
module.exports = { module.exports = {
presets: [ presets: [
'@vue/app' // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
] '@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
'plugins': ['dynamic-import-node']
}
}
} }
+18 -18
View File
@@ -1,11 +1,11 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.0.0", "version": "3.2.0",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve --open", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
@@ -43,10 +43,11 @@
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.18.1", "axios": "0.18.1",
"clipboard": "2.0.4", "clipboard": "2.0.4",
"core-js": "3.6.5",
"echarts": "4.2.1", "echarts": "4.2.1",
"element-ui": "2.13.2", "element-ui": "2.13.2",
"file-saver": "2.0.1", "file-saver": "2.0.1",
"js-beautify": "^1.10.2", "js-beautify": "1.10.2",
"fuse.js": "3.4.4", "fuse.js": "3.4.4",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
@@ -57,7 +58,7 @@
"sortablejs": "1.8.4", "sortablejs": "1.8.4",
"vue": "2.6.10", "vue": "2.6.10",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-quill-editor": "3.0.6", "quill": "1.3.7",
"vue-cropper": "0.4.9", "vue-cropper": "0.4.9",
"vue-router": "3.0.2", "vue-router": "3.0.2",
"vue-splitpane": "1.0.4", "vue-splitpane": "1.0.4",
@@ -65,32 +66,31 @@
"vuex": "3.1.0" "vuex": "3.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "3.5.3", "@vue/cli-plugin-babel": "4.4.4",
"@vue/cli-plugin-eslint": "^3.9.1", "@vue/cli-plugin-eslint": "4.4.4",
"@vue/cli-plugin-unit-jest": "3.5.3", "@vue/cli-plugin-unit-jest": "4.4.4",
"@vue/cli-service": "3.5.3", "@vue/cli-service": "4.4.4",
"@vue/test-utils": "1.0.0-beta.29", "@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "^9.5.1", "autoprefixer": "9.5.1",
"babel-core": "7.0.0-bridge.0", "babel-eslint": "10.1.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0", "babel-jest": "23.6.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "2.4.2", "chalk": "2.4.2",
"chokidar": "2.1.5", "chokidar": "2.1.5",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "5.15.3", "eslint": "6.7.2",
"eslint-plugin-vue": "5.2.2", "eslint-plugin-vue": "6.2.2",
"html-webpack-plugin": "3.2.0", "html-webpack-plugin": "3.2.0",
"http-proxy-middleware": "^0.19.1",
"husky": "1.3.1", "husky": "1.3.1",
"lint-staged": "8.1.5", "lint-staged": "8.1.5",
"mockjs": "1.0.1-beta3", "mockjs": "1.0.1-beta3",
"node-sass": "^4.9.0",
"plop": "2.3.0", "plop": "2.3.0",
"runjs": "^4.3.2", "runjs": "4.3.2",
"sass-loader": "^7.1.0", "node-sass": "4.14.1",
"sass-loader": "8.0.2",
"script-ext-html-webpack-plugin": "2.1.3", "script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2", "script-loader": "0.7.2",
"serve-static": "^1.13.2", "serve-static": "1.13.2",
"svg-sprite-loader": "4.1.3", "svg-sprite-loader": "4.1.3",
"svgo": "1.2.0", "svgo": "1.2.0",
"vue-template-compiler": "2.6.10" "vue-template-compiler": "2.6.10"
+17
View File
@@ -42,6 +42,7 @@ export function importTable(data) {
params: data params: data
}) })
} }
// 预览生成代码 // 预览生成代码
export function previewTable(tableId) { export function previewTable(tableId) {
return request({ return request({
@@ -49,6 +50,7 @@ export function previewTable(tableId) {
method: 'get' method: 'get'
}) })
} }
// 删除表数据 // 删除表数据
export function delTable(tableId) { export function delTable(tableId) {
return request({ return request({
@@ -57,3 +59,18 @@ export function delTable(tableId) {
}) })
} }
// 生成代码(自定义路径)
export function genCode(tableName) {
return request({
url: '/tool/gen/genCode/' + tableName,
method: 'get'
})
}
// 同步数据库
export function synchDb(tableName) {
return request({
url: '/tool/gen/synchDb/' + tableName,
method: 'get'
})
}
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

+40 -1
View File
@@ -67,6 +67,11 @@
font-size: 13px; font-size: 13px;
} }
} }
.el-table__body-wrapper {
.el-button [class*="el-icon-"] + span {
margin-left: 1px;
}
}
} }
/** 表单布局 **/ /** 表单布局 **/
@@ -87,6 +92,14 @@
padding: 10px 20px !important; padding: 10px 20px !important;
} }
/* tree border */
.tree-border {
margin-top: 5px;
border: 1px solid #e5e6e7;
background: #FFFFFF none;
border-radius:4px;
}
.pagination-container .el-pagination { .pagination-container .el-pagination {
right: 0; right: 0;
position: absolute; position: absolute;
@@ -142,7 +155,28 @@
padding-left: 15px; padding-left: 15px;
margin-bottom: 10px; margin-bottom: 10px;
} }
/* button color */
.el-button--cyan.is-active,
.el-button--cyan:active {
background: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
.el-button--cyan:focus,
.el-button--cyan:hover {
background: #48D1CC;
border-color: #48D1CC;
color: #FFFFFF;
}
.el-button--cyan {
background-color: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
/* text color */ /* text color */
.text-navy { .text-navy {
color: #1ab394; color: #1ab394;
@@ -198,4 +232,9 @@
opacity: .8; opacity: .8;
color: #fff!important; color: #fff!important;
background: #42b983!important; background: #42b983!important;
}
.top-right-btn {
position: relative;
float: right;
} }
+6
View File
@@ -63,6 +63,12 @@
width: 100% !important; width: 100% !important;
} }
.el-menu-item, .el-submenu__title {
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
// menu hover // menu hover
.submenu-title-noDropdown, .submenu-title-noDropdown,
.el-submenu__title { .el-submenu__title {
+90 -121
View File
@@ -1,153 +1,122 @@
<template> <template>
<div> <div class="editor" ref="editor" :style="styles"></div>
<!-- 图片上传组件辅助 -->
<el-upload
class="avatar-uploader quill-img"
:action="uploadImgUrl"
name="file"
:headers="headers"
:show-file-list="false"
:on-success="quillImgSuccess"
:on-error="uploadError"
:before-upload="quillImgBefore"
accept='.jpg,.jpeg,.png,.gif'
></el-upload>
<!-- 富文本组件 -->
<quill-editor
class="editor"
v-model="content"
ref="quillEditor"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@change="onEditorChange($event)"
></quill-editor>
</div>
</template> </template>
<script> <script>
import { getToken } from '@/utils/auth' import Quill from "quill";
// 工具栏配置
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ size: ["small", false, "large", "huge"] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
];
import { quillEditor } from "vue-quill-editor";
import "quill/dist/quill.core.css"; import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css"; import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css"; import "quill/dist/quill.bubble.css";
export default { export default {
name: "Editor",
props: { props: {
/* 编辑器的内容 */ /* 编辑器的内容 */
value: { value: {
type: String type: String,
default: "",
}, },
/* 图片大小 */ /* 高度 */
maxSize: { height: {
type: Number, type: Number,
default: 4000 //kb default: null,
} },
/* 最小高度 */
minHeight: {
type: Number,
default: null,
},
}, },
components: { quillEditor },
data() { data() {
return { return {
content: this.value, Quill: null,
uploadImgUrl: "", currentValue: "",
editorOption: { options: {
placeholder: "", theme: "snow",
theme: "snow", // or 'bubble' bounds: document.body,
placeholder: "请输入内容", debug: "warn",
modules: { modules: {
toolbar: { // 工具栏配置
container: toolbarOptions, toolbar: [
handlers: { ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
image: function(value) { ["blockquote", "code-block"], // 引用 代码块
if (value) { [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
// 触发input框选择图片文件 [{ indent: "-1" }, { indent: "+1" }], // 缩进
document.querySelector(".quill-img input").click(); [{ size: ["small", false, "large", "huge"] }], // 字体大小
} else { [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
this.quill.format("image", false); [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
} [{ align: [] }], // 对齐方式
} ["clean"], // 清除文本格式
} ["link", "image", "video"] // 链接、图片、视频
],
},
placeholder: "请输入内容",
readOnly: false,
},
};
},
computed: {
styles() {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
},
},
watch: {
value: {
handler(val) {
if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val;
if (this.Quill) {
this.Quill.pasteHTML(this.currentValue);
} }
} }
}, },
uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 immediate: true,
headers: { },
Authorization: 'Bearer ' + getToken()
}
};
}, },
watch: { mounted() {
value: function() { this.init();
this.content = this.value; },
} beforeDestroy() {
this.Quill = null;
}, },
methods: { methods: {
onEditorBlur() { init() {
//失去焦点事件 const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
this.Quill.pasteHTML(this.currentValue);
this.Quill.on("text-change", (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText();
const quill = this.Quill;
this.currentValue = html;
this.$emit("input", html);
this.$emit("on-change", { html, text, quill });
});
this.Quill.on("text-change", (delta, oldDelta, source) => {
this.$emit("on-text-change", delta, oldDelta, source);
});
this.Quill.on("selection-change", (range, oldRange, source) => {
this.$emit("on-selection-change", range, oldRange, source);
});
this.Quill.on("editor-change", (eventName, ...args) => {
this.$emit("on-editor-change", eventName, ...args);
});
}, },
onEditorFocus() { },
//获得焦点事件
},
onEditorChange() {
//内容改变事件
this.$emit("input", this.content);
},
// 富文本图片上传前
quillImgBefore(file) {
let fileType = file.type;
if(fileType === 'image/jpeg' || fileType === 'image/png'){
return true;
}else {
this.$message.error('请插入图片类型文件(jpg/jpeg/png)');
return false;
}
},
quillImgSuccess(res, file) {
// res为图片服务器返回的数据
// 获取富文本组件实例
let quill = this.$refs.quillEditor.quill;
// 如果上传成功
if (res.code == 200) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", res.url);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
},
// 富文本图片上传失败
uploadError() {
// loading动画消失
this.$message.error("图片插入失败");
}
}
}; };
</script> </script>
<style> <style>
.editor { .editor, .ql-toolbar {
white-space: pre-wrap!important;
line-height: normal !important; line-height: normal !important;
height: 192px;
} }
.quill-img { .quill-img {
display: none; display: none;
@@ -0,0 +1,38 @@
<!-- @author Shiyn/ huangmx 20200807优化-->
<template>
<div class="top-right-btn">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
</el-tooltip>
</el-row>
</div>
</template>
<script>
export default {
name: "RightToolbar",
data() {
return {};
},
props: {
showSearch: {
type: Boolean,
default: true,
},
},
methods: {
//搜索
toggleSearch() {
this.$emit("update:showSearch", !this.showSearch);
},
//刷新
refresh() {
this.$emit("queryTable");
},
},
};
</script>
@@ -160,7 +160,7 @@ export default {
}, },
closeAllTags(view) { closeAllTags(view) {
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => { this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
if (this.affixTags.some(tag => tag.path === view.path)) { if (this.affixTags.some(tag => tag.path === this.$route.path)) {
return return
} }
this.toLastView(visitedViews, view) this.toLastView(visitedViews, view)
+5 -1
View File
@@ -18,8 +18,10 @@ import './assets/icons' // icon
import './permission' // permission control import './permission' // permission control
import { getDicts } from "@/api/system/dict/data"; import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config"; import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, download, handleTree } from "@/utils/ruoyi"; import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree } from "@/utils/ruoyi";
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
//自定义表格工具扩展
import RightToolbar from "@/components/RightToolbar"
// 全局方法挂载 // 全局方法挂载
Vue.prototype.getDicts = getDicts Vue.prototype.getDicts = getDicts
@@ -28,6 +30,7 @@ Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download Vue.prototype.download = download
Vue.prototype.handleTree = handleTree Vue.prototype.handleTree = handleTree
@@ -45,6 +48,7 @@ Vue.prototype.msgInfo = function (msg) {
// 全局组件挂载 // 全局组件挂载
Vue.component('Pagination', Pagination) Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)
Vue.use(permission) Vue.use(permission)
+2 -2
View File
@@ -17,9 +17,9 @@ import Layout from '@/layout'
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
* name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题 * name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
* meta : { * meta : {
roles: ['admin','editor'] // 设置该路由进入的权限,支持多个权限叠加 noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
icon: 'svg-name' // 设置该路由的图标,对应路径src/icons/svg icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
} }
*/ */
+15
View File
@@ -406,6 +406,21 @@ export const layoutComponents = [
layoutTree: true, layoutTree: true,
children: [], children: [],
document: 'https://element.eleme.cn/#/zh-CN/component/layout' document: 'https://element.eleme.cn/#/zh-CN/component/layout'
},
{
layout: 'colFormItem',
label: '按钮',
changeTag: true,
labelWidth: null,
tag: 'el-button',
tagIcon: 'button',
span: 24,
default: '主要按钮',
type: 'primary',
icon: 'el-icon-search',
size: 'medium',
disabled: false,
document: 'https://element.eleme.cn/#/zh-CN/component/button'
} }
] ]
+21
View File
@@ -107,6 +107,18 @@ const layouts = {
} }
const tags = { const tags = {
'el-button': el => {
const {
tag, disabled
} = attrBuilder(el)
const type = el.type ? `type="${el.type}"` : ''
const icon = el.icon ? `icon="${el.icon}"` : ''
const size = el.size ? `size="${el.size}"` : ''
let child = buildElButtonChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>`
},
'el-input': el => { 'el-input': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
@@ -272,6 +284,15 @@ function attrBuilder(el) {
} }
} }
// el-buttin 子级
function buildElButtonChild(conf) {
const children = []
if (conf.default) {
children.push(conf.default)
}
return children.join('\n')
}
// el-input innerHTML // el-input innerHTML
function buildElInputChild(conf) { function buildElInputChild(conf) {
const children = [] const children = []
+5
View File
@@ -26,6 +26,11 @@ function vModel(self, dataObject, defaultValue) {
} }
const componentChild = { const componentChild = {
'el-button': {
default(h, conf, key) {
return conf[key]
},
},
'el-input': { 'el-input': {
prepend(h, conf, key) { prepend(h, conf, key) {
return <template slot="prepend">{conf[key]}</template> return <template slot="prepend">{conf[key]}</template>
+3 -1
View File
@@ -1,3 +1,5 @@
import { parseTime } from './ruoyi'
/** /**
* 表格时间格式化 * 表格时间格式化
*/ */
@@ -385,4 +387,4 @@ export function camelCase(str) {
export function isNumberStr(str) { export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
} }
+13 -13
View File
@@ -2,29 +2,29 @@ import JSEncrypt from 'jsencrypt/bin/jsencrypt'
// 密钥对生成 http://web.chacuo.net/netrsakeypair // 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' + const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ==' 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8\n' + const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9p\n' + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'B6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue\n' + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZ\n' + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'UBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6\n' + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha\n' + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3\n' + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'tTbklZkD2A==' 'UP8iWi1Qw0Y='
// 加密 // 加密
export function encrypt(txt) { export function encrypt(txt) {
const encryptor = new JSEncrypt() const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥 encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对需要加密的数据进行加密 return encryptor.encrypt(txt) // 对数据进行加密
} }
// 解密 // 解密
export function decrypt(txt) { export function decrypt(txt) {
const encryptor = new JSEncrypt() const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) return encryptor.decrypt(txt) // 对数据进行解密
} }
+17 -10
View File
@@ -30,30 +30,27 @@ service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200; const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
const message = errorCode[code] || res.data.msg || errorCode['default'] const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) { if (code === 401) {
MessageBox.confirm( MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
'登录状态已过期,您可以继续留在该页面,或者重新登录',
'系统提示',
{
confirmButtonText: '重新登录', confirmButtonText: '重新登录',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
} }
).then(() => { ).then(() => {
store.dispatch('LogOut').then(() => { store.dispatch('LogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug location.href = '/index';
}) })
}) })
} else if (code === 500) { } else if (code === 500) {
Message({ Message({
message: message, message: msg,
type: 'error' type: 'error'
}) })
return Promise.reject(new Error(message)) return Promise.reject(new Error(msg))
} else if (code !== 200) { } else if (code !== 200) {
Notification.error({ Notification.error({
title: message title: msg
}) })
return Promise.reject('error') return Promise.reject('error')
} else { } else {
@@ -62,8 +59,18 @@ service.interceptors.response.use(res => {
}, },
error => { error => {
console.log('err' + error) console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
}
else if (message.includes("timeout")) {
message = "系统接口请求超时";
}
else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({ Message({
message: error.message, message: message,
type: 'error', type: 'error',
duration: 5 * 1000 duration: 5 * 1000
}) })
+148 -134
View File
@@ -1,134 +1,148 @@
/** /**
* 通用js方法封装处理 * 通用js方法封装处理
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
const baseURL = process.env.VUE_APP_BASE_API const baseURL = process.env.VUE_APP_BASE_API
// 日期格式化 // 日期格式化
export function parseTime(time, pattern) { export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) { if (arguments.length === 0 || !time) {
return null return null
} }
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date let date
if (typeof time === 'object') { if (typeof time === 'object') {
date = time date = time
} else { } else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time) time = parseInt(time)
} else if (typeof time === 'string') { } else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/'); time = time.replace(new RegExp(/-/gm), '/');
} }
if ((typeof time === 'number') && (time.toString().length === 10)) { if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000 time = time * 1000
} }
date = new Date(time) date = new Date(time)
} }
const formatObj = { const formatObj = {
y: date.getFullYear(), y: date.getFullYear(),
m: date.getMonth() + 1, m: date.getMonth() + 1,
d: date.getDate(), d: date.getDate(),
h: date.getHours(), h: date.getHours(),
i: date.getMinutes(), i: date.getMinutes(),
s: date.getSeconds(), s: date.getSeconds(),
a: date.getDay() a: date.getDay()
} }
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key] let value = formatObj[key]
// Note: getDay() returns 0 on Sunday // Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) { if (result.length > 0 && value < 10) {
value = '0' + value value = '0' + value
} }
return value || 0 return value || 0
}) })
return time_str return time_str
} }
// 表单重置 // 表单重置
export function resetForm(refName) { export function resetForm(refName) {
if (this.$refs[refName]) { if (this.$refs[refName]) {
this.$refs[refName].resetFields(); this.$refs[refName].resetFields();
} }
} }
// 添加日期范围 // 添加日期范围
export function addDateRange(params, dateRange) { export function addDateRange(params, dateRange) {
var search = params; var search = params;
search.beginTime = ""; search.beginTime = "";
search.endTime = ""; search.endTime = "";
if (null != dateRange && '' != dateRange) { if (null != dateRange && '' != dateRange) {
search.beginTime = this.dateRange[0]; search.beginTime = dateRange[0];
search.endTime = this.dateRange[1]; search.endTime = dateRange[1];
} }
return search; return search;
} }
// 回显数据字典 // 回显数据字典
export function selectDictLabel(datas, value) { export function selectDictLabel(datas, value) {
var actions = []; var actions = [];
Object.keys(datas).map((key) => { Object.keys(datas).some((key) => {
if (datas[key].dictValue == ('' + value)) { if (datas[key].dictValue == ('' + value)) {
actions.push(datas[key].dictLabel); actions.push(datas[key].dictLabel);
return false; return true;
} }
}) })
return actions.join(''); return actions.join('');
} }
// 通用下载方法 // 回显数据字典(字符串数组)
export function download(fileName) { export function selectDictLabels(datas, value, separator) {
window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true; var actions = [];
} var currentSeparator = undefined === separator ? "," : separator;
var temp = value.split(currentSeparator);
// 字符串格式化(%s ) Object.keys(value.split(currentSeparator)).some((val) => {
export function sprintf(str) { Object.keys(datas).some((key) => {
var args = arguments, flag = true, i = 1; if (datas[key].dictValue == ('' + temp[val])) {
str = str.replace(/%s/g, function () { actions.push(datas[key].dictLabel + currentSeparator);
var arg = args[i++]; }
if (typeof arg === 'undefined') { })
flag = false; })
return ''; return actions.join('').substring(0, actions.join('').length - 1);
} }
return arg;
}); // 通用下载方法
return flag ? str : ''; export function download(fileName) {
} window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true;
}
// 转换字符串,undefined,null等转化为""
export function praseStrEmpty(str) { // 字符串格式化(%s )
if (!str || str == "undefined" || str == "null") { export function sprintf(str) {
return ""; var args = arguments, flag = true, i = 1;
} str = str.replace(/%s/g, function () {
return str; var arg = args[i++];
} if (typeof arg === 'undefined') {
flag = false;
/** return '';
* 构造树型结构数据 }
* @param {*} data 数据源 return arg;
* @param {*} id id字段 默认 'id' });
* @param {*} parentId 父节点字段 默认 'parentId' return flag ? str : '';
* @param {*} children 孩子节点字段 默认 'children' }
* @param {*} rootId 根Id 默认 0
*/ // 转换字符串,undefined,null等转化为""
export function handleTree(data, id, parentId, children, rootId) { export function praseStrEmpty(str) {
id = id || 'id' if (!str || str == "undefined" || str == "null") {
parentId = parentId || 'parentId' return "";
children = children || 'children' }
rootId = rootId || 0 return str;
//对源数据深度克隆 }
const cloneData = JSON.parse(JSON.stringify(data))
//循环所有项 /**
const treeData = cloneData.filter(father => { * 构造树型结构数据
let branchArr = cloneData.filter(child => { * @param {*} data 数据源
//返回每一项的子级数组 * @param {*} id id字段 默认 'id'
return father[id] === child[parentId] * @param {*} parentId 父节点字段 默认 'parentId'
}); * @param {*} children 孩子节点字段 默认 'children'
branchArr.length > 0 ? father.children = branchArr : ''; * @param {*} rootId 根Id 默认 0
//返回第一层 */
return father[parentId] === rootId; export function handleTree(data, id, parentId, children, rootId) {
}); id = id || 'id'
return treeData != '' ? treeData : data; parentId = parentId || 'parentId'
} children = children || 'children'
rootId = rootId || Math.min.apply(Math, data.map(item => { return item[parentId] })) || 0
//对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data))
//循环所有项
const treeData = cloneData.filter(father => {
let branchArr = cloneData.filter(child => {
//返回每一项的子级数组
return father[id] === child[parentId]
});
branchArr.length > 0 ? father.children = branchArr : '';
//返回第一层
return father[parentId] === rootId;
});
return treeData != '' ? treeData : data;
}
+4 -1
View File
@@ -29,7 +29,7 @@
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
</el-input> </el-input>
<div class="login-code"> <div class="login-code">
<img :src="codeUrl" @click="getCode" /> <img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div> </div>
</el-form-item> </el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
@@ -200,4 +200,7 @@ export default {
font-size: 12px; font-size: 12px;
letter-spacing: 1px; letter-spacing: 1px;
} }
.login-code-img {
height: 38px;
}
</style> </style>
+6 -3
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="任务名称" prop="jobName"> <el-form-item label="任务名称" prop="jobName">
<el-input <el-input
v-model="queryParams.jobName" v-model="queryParams.jobName"
@@ -31,7 +31,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -84,6 +84,7 @@
v-hasPermi="['monitor:job:query']" v-hasPermi="['monitor:job:query']"
>日志</el-button> >日志</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="jobList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="jobList" @selection-change="handleSelectionChange">
@@ -110,7 +111,7 @@
type="text" type="text"
icon="el-icon-caret-right" icon="el-icon-caret-right"
@click="handleRun(scope.row)" @click="handleRun(scope.row)"
v-hasPermi="['monitor:job:edit']" v-hasPermi="['monitor:job:changeStatus']"
>执行一次</el-button> >执行一次</el-button>
<el-button <el-button
size="mini" size="mini"
@@ -274,6 +275,8 @@ export default {
single: true, single: true,
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 定时任务表格数据 // 定时任务表格数据
+5 -2
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="任务名称" prop="jobName"> <el-form-item label="任务名称" prop="jobName">
<el-input <el-input
v-model="queryParams.jobName" v-model="queryParams.jobName"
@@ -56,7 +56,7 @@
></el-date-picker> ></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -90,6 +90,7 @@
v-hasPermi="['monitor:job:export']" v-hasPermi="['monitor:job:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="jobLogList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="jobLogList" @selection-change="handleSelectionChange">
@@ -175,6 +176,8 @@ export default {
ids: [], ids: [],
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 调度日志表格数据 // 调度日志表格数据
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="登录地址" prop="ipaddr"> <el-form-item label="登录地址" prop="ipaddr">
<el-input <el-input
v-model="queryParams.ipaddr" v-model="queryParams.ipaddr"
@@ -50,7 +50,7 @@
></el-date-picker> ></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -84,6 +84,7 @@
v-hasPermi="['system:logininfor:export']" v-hasPermi="['system:logininfor:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
@@ -126,6 +127,8 @@ export default {
ids: [], ids: [],
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 表格数据 // 表格数据
+3 -3
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true"> <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form-item label="登录地址" prop="ipaddr"> <el-form-item label="登录地址" prop="ipaddr">
<el-input <el-input
v-model="queryParams.ipaddr" v-model="queryParams.ipaddr"
@@ -20,11 +20,11 @@
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form>
</el-form>
<el-table <el-table
v-loading="loading" v-loading="loading"
:data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)" :data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)"
+5 -2
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="系统模块" prop="title"> <el-form-item label="系统模块" prop="title">
<el-input <el-input
v-model="queryParams.title" v-model="queryParams.title"
@@ -66,7 +66,7 @@
></el-date-picker> ></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -100,6 +100,7 @@
v-hasPermi="['system:config:export']" v-hasPermi="['system:config:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
@@ -195,6 +196,8 @@ export default {
ids: [], ids: [],
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 表格数据 // 表格数据
+5 -2
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="参数名称" prop="configName"> <el-form-item label="参数名称" prop="configName">
<el-input <el-input
v-model="queryParams.configName" v-model="queryParams.configName"
@@ -44,7 +44,7 @@
></el-date-picker> ></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -97,6 +97,7 @@
v-hasPermi="['system:config:remove']" v-hasPermi="['system:config:remove']"
>清理缓存</el-button> >清理缓存</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange">
@@ -188,6 +189,8 @@ export default {
single: true, single: true,
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 参数表格数据 // 参数表格数据
+20 -13
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :inline="true"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
<el-form-item label="部门名称"> <el-form-item label="部门名称" prop="deptName">
<el-input <el-input
v-model="queryParams.deptName" v-model="queryParams.deptName"
placeholder="请输入部门名称" placeholder="请输入部门名称"
@@ -10,7 +10,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable size="small"> <el-select v-model="queryParams.status" placeholder="部门状态" clearable size="small">
<el-option <el-option
v-for="dict in statusOptions" v-for="dict in statusOptions"
@@ -21,23 +21,23 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button <el-button
class="filter-item"
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button>
<el-button
class="filter-item"
type="primary" type="primary"
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['system:dept:add']" v-hasPermi="['system:dept:add']"
>新增</el-button> >新增</el-button>
</el-form-item> </el-col>
</el-form> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table <el-table
v-loading="loading" v-loading="loading"
@@ -149,6 +149,8 @@ export default {
return { return {
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 显示搜索条件
showSearch: true,
// 表格树数据 // 表格树数据
deptList: [], deptList: [],
// 部门树选项 // 部门树选项
@@ -247,6 +249,11 @@ export default {
handleQuery() { handleQuery() {
this.getList(); this.getList();
}, },
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd(row) { handleAdd(row) {
this.reset(); this.reset();

Some files were not shown because too many files have changed in this diff Show More