Compare commits

..

140 Commits

Author SHA1 Message Date
RuoYi c3a727b2fd 若依 3.8.5 2023-01-01 09:09:25 +08:00
RuoYi 19eaad0129 v3最新版本不需要render-after-expand 2022-12-23 16:08:23 +08:00
RuoYi 565cbb8c7a 升级pagehelper到最新版1.4.6 2022-12-13 19:42:39 +08:00
RuoYi b2cf949956 修改参数键名时移除前缓存配置 2022-12-13 19:40:48 +08:00
RuoYi 3fec133c69 升级oshi到最新版本6.4.0 2022-12-13 19:39:36 +08:00
RuoYi c9de6fcd82 优化代码 2022-12-13 19:39:19 +08:00
RuoYi 22ee2c2e94 删除fuse无效选项maxPatternLength 2022-12-08 10:21:48 +08:00
RuoYi f11db02ff8 修复代码生成图片/文件/单选时选择必填无法校验问题(I64IO2) 2022-12-08 10:19:38 +08:00
RuoYi d5f5c5d066 升级fastjson到最新版2.0.20 2022-12-08 10:13:39 +08:00
RuoYi 4536906b21 修复Vue3树形下拉不能默认选中(I64ESN) 2022-12-07 20:24:08 +08:00
RuoYi 9748e10339 升级druid到最新版本1.2.15 2022-12-07 11:41:44 +08:00
RuoYi b08a6ce3f6 升级kaptcha到最新版2.3.3 2022-12-07 10:45:50 +08:00
RuoYi 3039b745a9 升级echarts到最新版本5.4.0 2022-12-07 10:12:15 +08:00
RuoYi 39298d803c 添加新群号:170801498 2022-12-03 12:50:26 +08:00
RuoYi 09bb3e15c6 定时任务违规的字符 2022-12-03 12:48:51 +08:00
RuoYi 3b8a68c4cf 升级oshi到最新版本6.3.2 2022-12-03 12:43:37 +08:00
RuoYi 9aae863ce3 优化弹窗内容过多展示不全问题(I645RU) 2022-12-03 12:42:50 +08:00
若依 963247df43 !627 update ruoyi-ui/src/plugins/download.js.
Merge pull request !627 from Zeno/N/A
2022-12-01 08:21:29 +00:00
Zeno 7d874e31cf update ruoyi-ui/src/plugins/download.js.
修复文件名包含特殊字符(+、-、*...)的文件无法下载问题

Signed-off-by: Zeno <15270656234@163.com>
2022-11-28 10:29:38 +00:00
RuoYi 1bb6342bcb 修复Log注解GET请求记录不到参数问题 2022-11-22 10:41:40 +08:00
RuoYi 27acbe5b73 修复某些特性的环境生成代码变乱码TXT文件问题 2022-11-22 09:23:17 +08:00
RuoYi 6474a17100 消除Vue3控制台出现的警告信息 2022-11-21 19:10:25 +08:00
RuoYi 142f6ad6a0 兼容Excel下拉框内容过多无法显示的问题(I5XB6I) 2022-11-21 12:20:36 +08:00
RuoYi b4bdd4f306 开启TopNav没有子菜单隐藏侧边栏 2022-11-17 14:27:30 +08:00
RuoYi 74ba681fee 修复回显数据字典数组异常问题(I60UYQ) 2022-11-15 14:11:52 +08:00
若依 8f2b3ac465 !611 修复调度日志点击多次数据不变化的问题
Merge pull request !611 from 也曾为你像超人/N/A
2022-11-15 06:09:02 +00:00
RuoYi 7eee3b9f02 升级druid到最新版本1.2.14 2022-11-14 11:17:04 +08:00
RuoYi 27e34c2f0a 忽略不必要的属性数据返回 2022-11-12 11:26:48 +08:00
RuoYi 836180fe0e 优化导出对象的子列表为空会出现[]问题 2022-11-11 11:31:27 +08:00
RuoYi 06fbda5324 修复sheet超出最大行数异常问题 2022-11-07 11:20:02 +08:00
若依 bf313b17da !612 根据调度编号获取详细信息参数名改正
Merge pull request !612 from Rain/N/A
2022-10-31 05:51:48 +00:00
Rain a8b9485a29 根据调度编号获取详细信息参数名改正
Signed-off-by: Rain <938448486@qq.com>
2022-10-31 05:51:08 +00:00
也曾为你像超人 101e15d83f 修复调度日志点击多次数据不变化的问题
Signed-off-by: 也曾为你像超人 <1553592282@qq.com>
2022-10-31 05:45:21 +00:00
RuoYi ebb9f15a75 新增返回警告消息提示 2022-10-30 12:02:06 +08:00
RuoYi cd137bd9fc 升级fastjson到最新版2.0.16 2022-10-30 09:58:12 +08:00
若依 07bde5f88a !610 pagehelper-boot更新1.4.5
Merge pull request !610 from abbfun/N/A
2022-10-30 01:57:27 +00:00
abbfun 6fffa02acf pagehelper-boot更新1.4.5
Signed-off-by: abbfun <819589789@qq.com>
2022-10-29 14:45:55 +00:00
RuoYi dc48f9858b 修复table中更多按钮切换主题色未生效修复问题 2022-10-28 20:59:42 +08:00
RuoYi a6b2ac5dcd 升级oshi到最新版本6.3.0 2022-10-28 19:57:35 +08:00
若依 c0685b7f7f !608 编辑头像时生成为透明png图片
Merge pull request !608 from BlossomWave/N/A
2022-10-28 11:48:22 +00:00
若依 fb2d616c57 !609 优化代码
Merge pull request !609 from lihy2021/N/A
2022-10-28 11:44:27 +00:00
若依 6ff6853082 !606 重置时取消部门选中
Merge pull request !606 from 也曾为你像超人/N/A
2022-10-28 11:42:26 +00:00
若依 f8014ae969 !602 去除某些svg图标的fill="#bfbfbf"属性,避免菜单激活无法修改其填充颜色
Merge pull request !602 from 清溪先生/master
2022-10-28 11:39:13 +00:00
lihy2021 1de2b7a57e 优化代码 2022-10-27 01:25:39 +00:00
BlossomWave f01aa37394 update ruoyi-ui/src/views/system/user/profile/userAvatar.vue.
默认修改头像时如果上传的图片为png透明图片,生成的头像透明部分会变成黑色,修改了生成头像为png格式。可正常显示图片透明部分。

Signed-off-by: BlossomWave <316975215@qq.com>
2022-10-24 08:25:33 +00:00
也曾为你、像超人 4517dea98d 重置时取消部门选中
Signed-off-by: 也曾为你、像超人 <1553592282@qq.com>
2022-10-21 23:24:35 +00:00
RuoYi e21396870f 修正菜单状态注释信息 2022-10-21 11:56:15 +08:00
若依 b67f6a0fec !604 修复小屏幕上修改头像界面布局错位的问题
Merge pull request !604 from 也曾为你、像超人/master
2022-10-21 03:50:16 +00:00
若依 42d8104505 !603 update ruoyi-ui/src/views/system/user/index.vue.
Merge pull request !603 from kknd97/N/A
2022-10-21 03:46:49 +00:00
若依 f40a0eab23 !601 swagger-ui静态资源缓存
Merge pull request !601 from abbfun/N/A
2022-10-21 03:41:22 +00:00
刘元博 b6153d1aef 修正选择按钮宽度 2022-10-21 11:21:59 +08:00
若依 a2c585daa4 !605 升级fastjson到最新版2.0.15
Merge pull request !605 from Rain/N/A
2022-10-21 03:11:58 +00:00
Rain 5a60bf0b0a 升级fastjson到最新版2.0.15
Signed-off-by: Rain <938448486@qq.com>
2022-10-21 03:01:54 +00:00
刘元博 9dcddc7876 修复小屏幕上修改头像界面布局错位的问题 2022-10-20 19:18:10 +08:00
kknd97 b970185536 update ruoyi-ui/src/views/system/user/index.vue.
handleUpdate(row)方法中:this.form = response.data;语句
会导致【this.form.postIds = response.postIds;】和【this.form.roleIds = response.roleIds;】失效。
导致用户编辑对话框中,角色和部门多选框无法正常修改。
建议使用以下语句修改:
this.$set(this.form, "postIds", response.postIds);
this.$set(this.form, "roleIds", response.roleIds);

Signed-off-by: kknd97 <liujingwei@ln.chinamobile.com>
2022-10-20 06:27:02 +00:00
清溪先生 a64a029323 去除某些svg图标的fill="#bfbfbf"属性,避免菜单激活无法修改其填充颜色。
Signed-off-by: 清溪先生 <usfree2021@163.com>
2022-10-19 22:11:14 +08:00
abbfun 78f4d1c85b swagger-ui静态资源缓存
Signed-off-by: abbfun <819589789@qq.com>
2022-10-19 09:07:35 +00:00
RuoYi bf83fe568b 修复主题颜色在Drawer组件不会加载问题(I5VCF0) 2022-10-19 10:54:01 +08:00
RuoYi 6505432bf4 修复文件上传组件格式验证问题(I5V32H) 2022-10-12 19:33:58 +08:00
RuoYi a32a931d24 升级core-js到最新版本3.25.3 2022-10-10 09:22:47 +08:00
RuoYi 4d72fb4289 R isError and isSuccess static 2022-10-10 09:22:37 +08:00
若依 186c04d90a !595 解决导出时包含空子列表数据异常的问题
Merge pull request !595 from 也曾为你、像超人/N/A
2022-10-10 01:20:41 +00:00
也曾为你、像超人 c542b7ac32 解决导出时包含空子列表数据异常的问题
Signed-off-by: 也曾为你、像超人 <1553592282@qq.com>
2022-09-30 23:06:10 +00:00
RuoYi 3607e008a3 优化限流打印日志KEY(I5SQ09) 2022-09-28 19:32:55 +08:00
RuoYi 5b8edbf381 修复代码生成勾选属性无效问题 2022-09-28 19:31:52 +08:00
RuoYi 03f7bc0f3f 导入更新用户数据前校验数据权限 2022-09-28 19:26:16 +08:00
RuoYi e95a1245c5 若依 3.8.4 2022-09-26 08:29:03 +08:00
RuoYi d7441edae7 升级core-js到最新版本3.25.2 2022-09-22 11:13:49 +08:00
RuoYi 5053361a7f 升级fastjson到最新版2.0.14 2022-09-22 11:13:32 +08:00
若依 acbdd6365a !581 优化日志操作中重置按钮时重复查询的问题
Merge pull request !581 from 也曾为你、像超人/N/A
2022-09-19 06:41:36 +00:00
也曾为你、像超人 e781f88eca 优化日志操作中重置按钮时重复查询的问题
Signed-off-by: 也曾为你、像超人 <1553592282@qq.com>
2022-09-19 06:30:47 +00:00
RuoYi 86d16d070d 通用下载方法新增config配置选项(I5PNXE) 2022-09-19 13:09:21 +08:00
RuoYi 854b405d89 修改用户登录账号重复验证 2022-09-18 11:26:03 +08:00
RuoYi c3faa1a925 升级element-ui到最新版本2.15.10 2022-09-15 08:48:43 +08:00
RuoYi 37d6cc8146 优化代码生成同步后值NULL问题(I5OJDW) 2022-09-13 08:23:30 +08:00
RuoYi 2293822dc2 优化没有权限的用户编辑部门缺少数据(I5OF3O) 2022-09-12 17:22:23 +08:00
RuoYi f5bec70911 R add isError and isSuccess method 2022-09-12 17:22:07 +08:00
若依 87c53a049b !574 修复 issue#I5Q2ZO
Merge pull request !574 from 捏造的信仰/fix-I5Q2ZO
2022-09-09 01:45:12 +00:00
若依 5bcd2825b6 !568 style重复赋值
Merge pull request !568 from coverme/N/A
2022-09-09 01:25:22 +00:00
捏造的信仰 036144b9ea 插入 SysOperLog 时,限制 operUrl 属性的长度
Signed-off-by: 捏造的信仰 <yiding.he@gmail.com>
2022-09-07 03:00:51 +00:00
RuoYi 42d602b7a8 添加新群号:160110482 2022-08-28 20:09:25 +08:00
胡亚飞 d4b800036c style重复赋值
Signed-off-by: 胡亚飞 <huyafeily@aliyun.com>
2022-08-26 16:26:09 +00:00
若依 2f380f0c41 !564 修复执行任务时,若方法入口在任务的父类,则无法执行的问题
Merge pull request !564 from 捏造的信仰/fix-issue-I5NNXI
2022-08-26 00:42:03 +00:00
RuoYi 39efed1710 修复多文件上传报错出现的异常问题 2022-08-24 11:18:52 +08:00
RuoYi 9a895763d5 优化页面内嵌iframe切换tab不刷新数据 2022-08-23 20:59:26 +08:00
RuoYi 7347cbaedf 优化页面内嵌iframe切换tab不刷新数据 2022-08-23 17:29:09 +08:00
捏造的信仰 a78b5b7b2a 修复执行任务时,若方法入口在任务的父类,则无法执行的问题
实际项目开发中,可能会为所有定时任务类建一个共同的父类,任务的执行入口在父类定义,以便管理。此时使用 `getDeclaredMethod()` 是无法从子类找到要执行的方法的,而是要换用 `getMethod()` 方法。

Signed-off-by: 捏造的信仰 <yiding.he@gmail.com>
2022-08-23 05:36:29 +00:00
RuoYi 99d1760b98 优化代码 2022-08-22 15:27:58 +08:00
若依 4d71cfa90a !562 修复菜单管理已知问题
Merge pull request !562 from 稚屿/N/A
2022-08-22 06:20:18 +00:00
稚屿 e02f692359 修复菜单管理已知问题
问题描述:在菜单管理下,类型为菜单或者按钮的条目下点击修改按钮。
情况1,如果是类型为菜单,第一次点击修改按钮正常,则第二次点击另一个条目后面的修改按钮时报错!
情况2,如果是类型为按钮,第一次点击修改时正常,当点击取消按钮关闭弹窗时,浏览器报错!

报错代码:this.resetForm("form")

修复方案:添加遗漏的表单 prop 属性

Signed-off-by: 稚屿 <1491182878@qq.com>
2022-08-22 06:19:08 +00:00
RuoYi 77ec8d1c9a 修复代码生成权限父编号错误(I5NATP) 2022-08-22 12:21:07 +08:00
RuoYi 66ce21ec29 升级fastjson到最新版2.0.12 2022-08-22 12:04:01 +08:00
RuoYi 27e0937235 支持多权限字符匹配角色数据权限 2022-08-22 12:03:51 +08:00
RuoYi aadb7a41cb 优化Context信息,防止泄漏问题 2022-08-22 10:24:20 +08:00
RuoYi 9b3767a954 优化多角色数据权限匹配规则 2022-08-21 22:53:57 +08:00
RuoYi 851dc54b49 修复图片预览组件src属性为null值控制台报错问题(I5KBAS) 2022-08-15 12:07:24 +08:00
RuoYi cf2c4e02c6 字典管理操作类型新增其他 2022-08-14 09:40:36 +08:00
RuoYi 88b5715eae 升级oshi到最新版本6.2.2 2022-08-12 12:17:48 +08:00
RuoYi 5b05d4a123 个人中心修改密码去除多余的user传递 2022-08-12 12:17:28 +08:00
RuoYi 893ef39401 防止用户个人信息修改部门 2022-08-12 12:16:30 +08:00
RuoYi 890ad682d7 优化修改资料头像被覆盖的问题(I5LK04) 2022-08-11 13:22:55 +08:00
RuoYi b9f45057b8 操作日志记录支持排除敏感属性字段 2022-08-10 18:01:02 +08:00
RuoYi 89008c28df 升级fastjson到最新版2.0.11 2022-08-10 14:03:35 +08:00
RuoYi af7d0a3409 优化导出对象的子列表判断条件 2022-08-10 13:59:57 +08:00
RuoYi 1cd2eef899 优化excel/scale属性导出单元格数值类型 2022-08-09 08:02:24 +08:00
若依 8c7b93ec4f !547 fix: 账户解锁接口去掉多余的 /
Merge pull request !547 from iacker/N/A
2022-08-08 23:44:57 +00:00
iacker 3f7bf545b5 fix: 账户解锁接口去掉多余的 / 2022-08-08 13:55:08 +00:00
RuoYi cbedec7ca6 登录日志新增解锁账户功能 2022-08-08 09:23:52 +08:00
RuoYi fb1bac2114 新增删除Hash中的某条数据 2022-08-07 19:31:04 +08:00
RuoYi d0f399a66a 优化xss过滤后格式出现的异常 2022-08-07 19:30:54 +08:00
RuoYi e73dbd470a Excel注解支持导出对象的子列表方法 2022-08-07 18:33:04 +08:00
RuoYi e0cd5381e2 数据逻辑删除不进行唯一验证 2022-08-03 16:48:55 +08:00
RuoYi aee5d417ed 支持配置密码最大错误次数/锁定时间 2022-07-30 14:01:38 +08:00
RuoYi 250c5ba226 优化任务过期不执行调度 2022-07-29 20:28:59 +08:00
若依 b91c848962 !538 优化表格上右侧工具条(搜索按钮显隐&右侧样式凸出)
Merge pull request !538 from abbfun/N/A
2022-07-29 12:28:38 +00:00
abbfun d4475d0e8d 优化表格上右侧工具条(搜索按钮显隐&右侧样式凸出)
无搜索条件时可通过search隐藏搜索按钮,工具条组右侧样式超出5px(相对于底部表格),其父节点gutter代码生成默认10,此处也默认10,使工具组样式左右一致
2022-07-27 09:05:31 +00:00
RuoYi aff54ab5fe 自定义数据权限不排除重复 2022-07-26 20:02:17 +08:00
RuoYi 06177addf5 添加新群号:104748341 2022-07-25 18:45:51 +08:00
若依 9f3b91fe57 !535 所有的覆写方法,必须加@Override注解
Merge pull request !535 from 天才的逻辑/master
2022-07-25 10:32:48 +00:00
若依 80d25863db !536 防止主键字段名与'row'或'ids'一致导致报错的问题。
Merge pull request !536 from 张政/N/A
2022-07-25 10:32:42 +00:00
张政 cf8a7f8678 防止主键字段名与'row'或'ids'一致导致报错的问题。 2022-07-23 08:29:52 +00:00
RuoYi 86fc709b03 升级pagehelper到最新版1.4.3 2022-07-22 14:54:38 +08:00
b8b58cb202 所有的覆写方法,必须加@Override注解 2022-07-22 10:57:00 +08:00
96970ff951 所有的覆写方法,必须加@Override注解 2022-07-22 10:35:31 +08:00
RuoYi 7cc9d17424 支持自定义隐藏Excel属性列 2022-07-21 13:52:05 +08:00
RuoYi bc8b5f1079 优化布局设置使用el-drawer抽屉显示 2022-07-21 08:50:48 +08:00
RuoYi 5ec5e1a65d 优化字典数据使用store存取 2022-07-20 19:38:16 +08:00
RuoYi 1f0e742710 Excel注解支持backgroundColor属性设置背景色 2022-07-20 09:39:58 +08:00
RuoYi 28b9fbb4d2 优化多个相同角色数据导致权限SQL重复问题 2022-07-19 15:55:03 +08:00
RuoYi 2c79dc906e 升级oshi到最新版本6.2.1 2022-07-14 19:49:32 +08:00
RuoYi 1852017ecc 修改验证码开关变量名 2022-07-14 19:49:00 +08:00
若依 424d11896a !531 去除生成验证码多余的逻辑判断
Merge pull request !531 from 稚屿/N/A
2022-07-14 09:28:46 +00:00
稚屿 edefee46b2 去除生成验证码多余的逻辑判断 2022-07-13 01:00:44 +00:00
RuoYi c7c3da2038 升级fastjson到最新版2.0.9 2022-07-12 18:07:05 +08:00
RuoYi eb9f3d3772 修改验证码开关变量名 2022-07-12 18:04:49 +08:00
若依 1a61790407 !523 修改错误的变量名
Merge pull request !523 from SG/N/A
2022-07-12 10:02:50 +00:00
若依 fe98fba5b5 !527 调增数组格式声明,random随机转换修正
Merge pull request !527 from 靖少毅/jsy20220705
2022-07-12 10:01:56 +00:00
靖少毅 4eb8809a8a 调增数组格式声明,random随机转换修正 2022-07-05 16:43:55 +08:00
疯狂的狮子Li 0a893d196e update 优化魔法值 2022-07-05 02:06:31 +00:00
SG ec45cf04af 修改错误的变量名 2022-07-01 13:56:44 +00:00
156 changed files with 3047 additions and 1952 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.3</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.5</h1>
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.3-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.5-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
@@ -94,4 +94,4 @@
## 若依前后端分离交流群
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/139821253-blue.svg)](https://jq.qq.com/?_wv=1027&k=njiWDmkj) 点击按钮入群。
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) 点击按钮入群。
+8 -16
View File
@@ -6,26 +6,25 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.8.3</version>
<version>3.8.5</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>3.8.3</ruoyi.version>
<ruoyi.version>3.8.5</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<druid.version>1.2.11</druid.version>
<druid.version>1.2.15</druid.version>
<bitwalker.version>1.21</bitwalker.version>
<swagger.version>3.0.0</swagger.version>
<kaptcha.version>2.3.2</kaptcha.version>
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
<pagehelper.boot.version>1.4.1</pagehelper.boot.version>
<fastjson.version>2.0.8</fastjson.version>
<oshi.version>6.1.6</oshi.version>
<kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
<fastjson.version>2.0.20</fastjson.version>
<oshi.version>6.4.0</oshi.version>
<commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version>
<commons.collections.version>3.2.2</commons.collections.version>
@@ -61,13 +60,6 @@
<version>${bitwalker.version}</version>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
@@ -146,7 +138,7 @@
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
@@ -46,9 +46,9 @@ public class CaptchaController
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaOnOff = configService.selectCaptchaOnOff();
ajax.put("captchaOnOff", captchaOnOff);
if (!captchaOnOff)
boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled)
{
return ajax;
}
@@ -41,6 +41,7 @@ public class CacheController
caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@@ -78,8 +79,8 @@ public class CacheController
@GetMapping("/getKeys/{cacheName}")
public AjaxResult getCacheKeys(@PathVariable String cacheName)
{
Set<String> cacheKyes = redisTemplate.keys(cacheName + "*");
return AjaxResult.success(cacheKyes);
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
return AjaxResult.success(cacheKeys);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@@ -16,6 +16,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPasswordService;
import com.ruoyi.system.domain.SysLogininfor;
import com.ruoyi.system.service.ISysLogininforService;
@@ -31,6 +32,9 @@ public class SysLogininforController extends BaseController
@Autowired
private ISysLogininforService logininforService;
@Autowired
private SysPasswordService passwordService;
@PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
@GetMapping("/list")
public TableDataInfo list(SysLogininfor logininfor)
@@ -64,6 +68,15 @@ public class SysLogininforController extends BaseController
public AjaxResult clean()
{
logininforService.cleanLogininfor();
return AjaxResult.success();
return success();
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
@Log(title = "账户解锁", businessType = BusinessType.OTHER)
@GetMapping("/unlock/{userName}")
public AjaxResult unlock(@PathVariable("userName") String userName)
{
passwordService.clearLoginRecordCache(userName);
return success();
}
}
@@ -64,6 +64,6 @@ public class SysOperlogController extends BaseController
public AjaxResult clean()
{
operLogService.cleanOperLog();
return AjaxResult.success();
return success();
}
}
@@ -87,6 +87,6 @@ public class SysUserOnlineController extends BaseController
public AjaxResult forceLogout(@PathVariable String tokenId)
{
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
return AjaxResult.success();
return success();
}
}
@@ -64,7 +64,7 @@ public class SysConfigController extends BaseController
@GetMapping(value = "/{configId}")
public AjaxResult getInfo(@PathVariable Long configId)
{
return AjaxResult.success(configService.selectConfigById(configId));
return success(configService.selectConfigById(configId));
}
/**
@@ -73,7 +73,7 @@ public class SysConfigController extends BaseController
@GetMapping(value = "/configKey/{configKey}")
public AjaxResult getConfigKey(@PathVariable String configKey)
{
return AjaxResult.success(configService.selectConfigByKey(configKey));
return success(configService.selectConfigByKey(configKey));
}
/**
@@ -86,7 +86,7 @@ public class SysConfigController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
{
return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setCreateBy(getUsername());
return toAjax(configService.insertConfig(config));
@@ -102,7 +102,7 @@ public class SysConfigController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
{
return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setUpdateBy(getUsername());
return toAjax(configService.updateConfig(config));
@@ -129,6 +129,6 @@ public class SysConfigController extends BaseController
public AjaxResult refreshCache()
{
configService.resetConfigCache();
return AjaxResult.success();
return success();
}
}
@@ -1,6 +1,5 @@
package com.ruoyi.web.controller.system;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,7 +42,7 @@ public class SysDeptController extends BaseController
public AjaxResult list(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(depts);
return success(depts);
}
/**
@@ -54,17 +53,8 @@ public class SysDeptController extends BaseController
public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
Iterator<SysDept> it = depts.iterator();
while (it.hasNext())
{
SysDept d = (SysDept) it.next();
if (d.getDeptId().intValue() == deptId
|| ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""))
{
it.remove();
}
}
return AjaxResult.success(depts);
depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
return success(depts);
}
/**
@@ -75,30 +65,7 @@ public class SysDeptController extends BaseController
public AjaxResult getInfo(@PathVariable Long deptId)
{
deptService.checkDeptDataScope(deptId);
return AjaxResult.success(deptService.selectDeptById(deptId));
}
/**
* 获取部门下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
}
/**
* 加载对应角色部门列表树
*/
@GetMapping(value = "/roleDeptTreeselect/{roleId}")
public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.buildDeptTreeSelect(depts));
return ajax;
return success(deptService.selectDeptById(deptId));
}
/**
@@ -111,7 +78,7 @@ public class SysDeptController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
{
return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
dept.setCreateBy(getUsername());
return toAjax(deptService.insertDept(dept));
@@ -129,15 +96,15 @@ public class SysDeptController extends BaseController
deptService.checkDeptDataScope(deptId);
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
{
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
else if (dept.getParentId().equals(deptId))
{
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
}
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
{
return AjaxResult.error("该部门包含未停用的子部门!");
return error("该部门包含未停用的子部门!");
}
dept.setUpdateBy(getUsername());
return toAjax(deptService.updateDept(dept));
@@ -153,11 +120,11 @@ public class SysDeptController extends BaseController
{
if (deptService.hasChildByDeptId(deptId))
{
return AjaxResult.error("存在下级部门,不允许删除");
return warn("存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
return AjaxResult.error("部门存在用户,不允许删除");
return warn("部门存在用户,不允许删除");
}
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId));
@@ -66,7 +66,7 @@ public class SysDictDataController extends BaseController
@GetMapping(value = "/{dictCode}")
public AjaxResult getInfo(@PathVariable Long dictCode)
{
return AjaxResult.success(dictDataService.selectDictDataById(dictCode));
return success(dictDataService.selectDictDataById(dictCode));
}
/**
@@ -80,7 +80,7 @@ public class SysDictDataController extends BaseController
{
data = new ArrayList<SysDictData>();
}
return AjaxResult.success(data);
return success(data);
}
/**
@@ -61,7 +61,7 @@ public class SysDictTypeController extends BaseController
@GetMapping(value = "/{dictId}")
public AjaxResult getInfo(@PathVariable Long dictId)
{
return AjaxResult.success(dictTypeService.selectDictTypeById(dictId));
return success(dictTypeService.selectDictTypeById(dictId));
}
/**
@@ -74,7 +74,7 @@ public class SysDictTypeController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
{
return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setCreateBy(getUsername());
return toAjax(dictTypeService.insertDictType(dict));
@@ -90,7 +90,7 @@ public class SysDictTypeController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
{
return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setUpdateBy(getUsername());
return toAjax(dictTypeService.updateDictType(dict));
@@ -117,7 +117,7 @@ public class SysDictTypeController extends BaseController
public AjaxResult refreshCache()
{
dictTypeService.resetDictCache();
return AjaxResult.success();
return success();
}
/**
@@ -127,6 +127,6 @@ public class SysDictTypeController extends BaseController
public AjaxResult optionselect()
{
List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
return AjaxResult.success(dictTypes);
return success(dictTypes);
}
}
@@ -41,7 +41,7 @@ public class SysMenuController extends BaseController
public AjaxResult list(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menus);
return success(menus);
}
/**
@@ -51,7 +51,7 @@ public class SysMenuController extends BaseController
@GetMapping(value = "/{menuId}")
public AjaxResult getInfo(@PathVariable Long menuId)
{
return AjaxResult.success(menuService.selectMenuById(menuId));
return success(menuService.selectMenuById(menuId));
}
/**
@@ -61,7 +61,7 @@ public class SysMenuController extends BaseController
public AjaxResult treeselect(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
return success(menuService.buildMenuTreeSelect(menus));
}
/**
@@ -87,11 +87,11 @@ public class SysMenuController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
}
menu.setCreateBy(getUsername());
return toAjax(menuService.insertMenu(menu));
@@ -107,15 +107,15 @@ public class SysMenuController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
menu.setUpdateBy(getUsername());
return toAjax(menuService.updateMenu(menu));
@@ -131,11 +131,11 @@ public class SysMenuController extends BaseController
{
if (menuService.hasChildByMenuId(menuId))
{
return AjaxResult.error("存在子菜单,不允许删除");
return warn("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId))
{
return AjaxResult.error("菜单已分配,不允许删除");
return warn("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
}
@@ -51,7 +51,7 @@ public class SysNoticeController extends BaseController
@GetMapping(value = "/{noticeId}")
public AjaxResult getInfo(@PathVariable Long noticeId)
{
return AjaxResult.success(noticeService.selectNoticeById(noticeId));
return success(noticeService.selectNoticeById(noticeId));
}
/**
@@ -64,7 +64,7 @@ public class SysPostController extends BaseController
@GetMapping(value = "/{postId}")
public AjaxResult getInfo(@PathVariable Long postId)
{
return AjaxResult.success(postService.selectPostById(postId));
return success(postService.selectPostById(postId));
}
/**
@@ -77,11 +77,11 @@ public class SysPostController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
{
return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
{
return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setCreateBy(getUsername());
return toAjax(postService.insertPost(post));
@@ -97,11 +97,11 @@ public class SysPostController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
{
return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
{
return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setUpdateBy(getUsername());
return toAjax(postService.updatePost(post));
@@ -125,6 +125,6 @@ public class SysPostController extends BaseController
public AjaxResult optionselect()
{
List<SysPost> posts = postService.selectPostAll();
return AjaxResult.success(posts);
return success(posts);
}
}
@@ -66,15 +66,17 @@ public class SysProfileController extends BaseController
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setUserId(sysUser.getUserId());
user.setPassword(null);
user.setAvatar(null);
user.setDeptId(null);
if (userService.updateUserProfile(user) > 0)
{
// 更新缓存用户信息
@@ -83,9 +85,9 @@ public class SysProfileController extends BaseController
sysUser.setEmail(user.getEmail());
sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
return success();
}
return AjaxResult.error("修改个人信息异常,请联系管理员");
return error("修改个人信息异常,请联系管理员");
}
/**
@@ -100,20 +102,20 @@ public class SysProfileController extends BaseController
String password = loginUser.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password))
{
return AjaxResult.error("修改密码失败,旧密码错误");
return error("修改密码失败,旧密码错误");
}
if (SecurityUtils.matchesPassword(newPassword, password))
{
return AjaxResult.error("新密码不能与旧密码相同");
return error("新密码不能与旧密码相同");
}
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
{
// 更新缓存用户密码
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
return success();
}
return AjaxResult.error("修改密码异常,请联系管理员");
return error("修改密码异常,请联系管理员");
}
/**
@@ -137,6 +139,6 @@ public class SysProfileController extends BaseController
return ajax;
}
}
return AjaxResult.error("上传图片异常,请联系管理员");
return error("上传图片异常,请联系管理员");
}
}
@@ -17,6 +17,7 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
@@ -27,6 +28,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@@ -44,13 +46,16 @@ public class SysRoleController extends BaseController
@Autowired
private TokenService tokenService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private ISysUserService userService;
@Autowired
private ISysDeptService deptService;
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role)
@@ -78,7 +83,7 @@ public class SysRoleController extends BaseController
public AjaxResult getInfo(@PathVariable Long roleId)
{
roleService.checkRoleDataScope(roleId);
return AjaxResult.success(roleService.selectRoleById(roleId));
return success(roleService.selectRoleById(roleId));
}
/**
@@ -91,11 +96,11 @@ public class SysRoleController extends BaseController
{
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
{
return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
{
return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setCreateBy(getUsername());
return toAjax(roleService.insertRole(role));
@@ -114,11 +119,11 @@ public class SysRoleController extends BaseController
roleService.checkRoleDataScope(role.getRoleId());
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
{
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
{
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setUpdateBy(getUsername());
@@ -132,9 +137,9 @@ public class SysRoleController extends BaseController
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
tokenService.setLoginUser(loginUser);
}
return AjaxResult.success();
return success();
}
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
}
/**
@@ -182,7 +187,7 @@ public class SysRoleController extends BaseController
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
return AjaxResult.success(roleService.selectRoleAll());
return success(roleService.selectRoleAll());
}
/**
@@ -242,4 +247,17 @@ public class SysRoleController extends BaseController
roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds));
}
/**
* 获取对应角色部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax;
}
}
@@ -20,6 +20,7 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -27,6 +28,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@@ -46,6 +48,9 @@ public class SysUserController extends BaseController
@Autowired
private ISysRoleService roleService;
@Autowired
private ISysDeptService deptService;
@Autowired
private ISysPostService postService;
@@ -80,7 +85,7 @@ public class SysUserController extends BaseController
List<SysUser> userList = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return AjaxResult.success(message);
return success(message);
}
@PostMapping("/importTemplate")
@@ -120,19 +125,19 @@ public class SysUserController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysUser user)
{
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName())))
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setCreateBy(getUsername());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
@@ -149,15 +154,19 @@ public class SysUserController extends BaseController
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
if (StringUtils.isNotEmpty(user.getPhonenumber())
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
{
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setUpdateBy(getUsername());
return toAjax(userService.updateUser(user));
@@ -234,4 +243,14 @@ public class SysUserController extends BaseController
userService.insertUserAuth(userId, roleIds);
return success();
}
/**
* 获取部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
return success(deptService.selectDeptTreeList(dept));
}
}
@@ -1,24 +0,0 @@
package com.ruoyi.web.controller.tool;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ruoyi.common.core.controller.BaseController;
/**
* swagger 接口
*
* @author ruoyi
*/
@Controller
@RequestMapping("/tool/swagger")
public class SwaggerController extends BaseController
{
@PreAuthorize("@ss.hasPermi('tool:swagger:view')")
@GetMapping()
public String index()
{
return redirect("/swagger-ui.html");
}
}
+10 -2
View File
@@ -3,9 +3,9 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.8.3
version: 3.8.5
# 版权年份
copyrightYear: 2022
copyrightYear: 2023
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
@@ -39,6 +39,14 @@ logging:
com.ruoyi: debug
org.springframework: warn
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间(默认10分钟)
lockTime: 10
# Spring配置
spring:
# 资源信息
@@ -5,7 +5,7 @@ user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
+8 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -58,6 +58,13 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
@@ -25,4 +25,9 @@ public @interface DataScope
* 用户表的别名
*/
public String userAlias() default "";
/**
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
*/
public String permission() default "";
}
@@ -88,6 +88,11 @@ public @interface Excel
*/
public String[] combo() default {};
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
public boolean needMerge() default false;
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
@@ -104,12 +109,27 @@ public @interface Excel
public boolean isStatistics() default false;
/**
* 导出类型(0数字 1字符串)
* 导出类型(0数字 1字符串 2图片
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出字体颜
* 导出列头背景
*/
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
/**
* 导出列头字体颜色
*/
public IndexedColors headerColor() default IndexedColors.WHITE;
/**
* 导出单元格背景色
*/
public IndexedColors backgroundColor() default IndexedColors.WHITE;
/**
* 导出单元格字体颜色
*/
public IndexedColors color() default IndexedColors.BLACK;
@@ -128,22 +148,6 @@ public @interface Excel
*/
public String[] args() default {};
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
@@ -36,4 +36,9 @@ public class CacheConstants
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
}
@@ -19,6 +19,11 @@ public class Constants
*/
public static final String GBK = "GBK";
/**
* www主域
*/
public static final String WWW = "www.";
/**
* http请求
*/
@@ -133,5 +138,5 @@ public class Constants
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file" };
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
}
@@ -86,4 +86,9 @@ public class HttpStatus
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
public static final int WARN = 601;
}
@@ -113,6 +113,14 @@ public class BaseController
{
return AjaxResult.success(message);
}
/**
* 返回成功消息
*/
public AjaxResult success(Object data)
{
return AjaxResult.success(data);
}
/**
* 返回失败消息
@@ -122,6 +130,14 @@ public class BaseController
return AjaxResult.error(message);
}
/**
* 返回警告消息
*/
public AjaxResult warn(String message)
{
return AjaxResult.warn(message);
}
/**
* 响应返回结果
*
@@ -101,10 +101,33 @@ public class AjaxResult extends HashMap<String, Object>
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult warn(String msg)
{
return AjaxResult.warn(msg, null);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult warn(String msg, Object data)
{
return new AjaxResult(HttpStatus.WARN, msg, data);
}
/**
* 返回错误消息
*
* @return
* @return 错误消息
*/
public static AjaxResult error()
{
@@ -115,7 +138,7 @@ public class AjaxResult extends HashMap<String, Object>
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
* @return 错误消息
*/
public static AjaxResult error(String msg)
{
@@ -127,7 +150,7 @@ public class AjaxResult extends HashMap<String, Object>
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
* @return 错误消息
*/
public static AjaxResult error(String msg, Object data)
{
@@ -139,7 +162,7 @@ public class AjaxResult extends HashMap<String, Object>
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
* @return 错误消息
*/
public static AjaxResult error(int code, String msg)
{
@@ -5,6 +5,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* Entity基类
@@ -16,6 +18,7 @@ public class BaseEntity implements Serializable
private static final long serialVersionUID = 1L;
/** 搜索值 */
@JsonIgnore
private String searchValue;
/** 创建者 */
@@ -36,6 +39,7 @@ public class BaseEntity implements Serializable
private String remark;
/** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params;
public String getSearchValue()
@@ -102,4 +102,14 @@ public class R<T> implements Serializable
{
this.data = data;
}
public static <T> Boolean isError(R<T> ret)
{
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret)
{
return R.SUCCESS == ret.getCode();
}
}
@@ -131,7 +131,7 @@ public class SysDictData extends BaseEntity
public boolean getDefault()
{
return UserConstants.YES.equals(this.isDefault) ? true : false;
return UserConstants.YES.equals(this.isDefault);
}
public String getIsDefault()
@@ -54,7 +54,7 @@ public class SysMenu extends BaseEntity
/** 显示状态(0显示 1隐藏) */
private String visible;
/** 菜单状态(0显示 1隐藏 */
/** 菜单状态(0正常 1停用 */
private String status;
/** 权限字符串 */
@@ -1,6 +1,8 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Set;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -31,7 +33,7 @@ public class SysRole extends BaseEntity
/** 角色排序 */
@Excel(name = "角色排序")
private String roleSort;
private Integer roleSort;
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
@@ -59,6 +61,9 @@ public class SysRole extends BaseEntity
/** 部门组(数据权限) */
private Long[] deptIds;
/** 角色菜单权限 */
private Set<String> permissions;
public SysRole()
{
@@ -113,13 +118,13 @@ public class SysRole extends BaseEntity
this.roleKey = roleKey;
}
@NotBlank(message = "显示顺序不能为空")
public String getRoleSort()
@NotNull(message = "显示顺序不能为空")
public Integer getRoleSort()
{
return roleSort;
}
public void setRoleSort(String roleSort)
public void setRoleSort(Integer roleSort)
{
this.roleSort = roleSort;
}
@@ -203,7 +208,17 @@ public class SysRole extends BaseEntity
{
this.deptIds = deptIds;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -74,6 +74,28 @@ public class RedisCache
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获取有效时间
*
* @param key Redis键
* @return 有效时间
*/
public long getExpire(final String key)
{
return redisTemplate.getExpire(key);
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public Boolean hasKey(String key)
{
return redisTemplate.hasKey(key);
}
/**
* 获得缓存的基本对象。
*
@@ -102,9 +124,9 @@ public class RedisCache
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection)
public boolean deleteObject(final Collection collection)
{
return redisTemplate.delete(collection);
return redisTemplate.delete(collection) > 0;
}
/**
@@ -209,18 +231,6 @@ public class RedisCache
return opsForHash.get(key, hKey);
}
/**
* 删除Hash中的数据
*
* @param key
* @param hKey
*/
public void delCacheMapValue(final String key, final String hKey)
{
HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.delete(key, hKey);
}
/**
* 获取多个Hash中的数据
*
@@ -233,6 +243,18 @@ public class RedisCache
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean deleteCacheMapValue(final String key, final String hKey)
{
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 获得缓存的基本对象列表
*
@@ -713,7 +713,7 @@ public class Convert
}
if (value instanceof Double)
{
return new BigDecimal((Double) value);
return BigDecimal.valueOf((Double) value);
}
if (value instanceof Integer)
{
@@ -894,7 +894,7 @@ public class Convert
*/
public static String toSBC(String input, Set<Character> notConvertSet)
{
char c[] = input.toCharArray();
char[] c = input.toCharArray();
for (int i = 0; i < c.length; i++)
{
if (null != notConvertSet && notConvertSet.contains(c[i]))
@@ -936,7 +936,7 @@ public class Convert
*/
public static String toDBC(String text, Set<Character> notConvertSet)
{
char c[] = text.toCharArray();
char[] c = text.toCharArray();
for (int i = 0; i < c.length; i++)
{
if (null != notConvertSet && notConvertSet.contains(c[i]))
@@ -7,7 +7,6 @@ package com.ruoyi.common.exception;
*/
public class GlobalException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
@@ -45,6 +44,7 @@ public class GlobalException extends RuntimeException
return this;
}
@Override
public String getMessage()
{
return message;
@@ -49,6 +49,7 @@ public final class ServiceException extends RuntimeException
return detailMessage;
}
@Override
public String getMessage()
{
return message;
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
* 用户错误最大次数异常类
*
* @author ruoyi
*/
public class UserPasswordRetryLimitExceedException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
{
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
}
}
@@ -0,0 +1,24 @@
package com.ruoyi.common.filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
/**
* 排除JSON敏感属性
*
* @author ruoyi
*/
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{
public PropertyPreExcludeFilter()
{
}
public PropertyPreExcludeFilter addExcludes(String... filters)
{
for (int i = 0; i < filters.length; i++)
{
this.getExcludes().add(filters[i]);
}
return this;
}
}
@@ -10,6 +10,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.ruoyi.common.utils.http.HttpHelper;
import com.ruoyi.common.constant.Constants;
/**
* 构建可重复读取inputStream的request
@@ -23,10 +24,10 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
{
super(request);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding(Constants.UTF8);
response.setCharacterEncoding(Constants.UTF8);
body = HttpHelper.getBodyString(request).getBytes("UTF-8");
body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
}
@Override
@@ -12,6 +12,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.enums.HttpMethod;
/**
* 防止XSS攻击的过滤器
@@ -59,7 +60,7 @@ public class XssFilter implements Filter
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches("GET") || method.matches("DELETE"))
if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
{
return true;
}
@@ -34,13 +34,13 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
if (values != null)
{
int length = values.length;
String[] escapseValues = new String[length];
String[] escapesValues = new String[length];
for (int i = 0; i < length; i++)
{
// 防xss攻击和过滤前后空格
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
escapesValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapseValues;
return escapesValues;
}
return super.getParameterValues(name);
}
@@ -4,6 +4,10 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -68,6 +72,34 @@ public class ServletUtils
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获得所有请求参数
*
* @param request 请求对象{@link ServletRequest}
* @return Map
*/
public static Map<String, String[]> getParams(ServletRequest request)
{
final Map<String, String[]> map = request.getParameterMap();
return Collections.unmodifiableMap(map);
}
/**
* 获得所有请求参数
*
* @param request 请求对象{@link ServletRequest}
* @return Map
*/
public static Map<String, String> getParamMap(ServletRequest request)
{
Map<String, String> params = new HashMap<>();
for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
{
params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
}
return params;
}
/**
* 获取request
*/
@@ -324,6 +324,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return list;
}
/**
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
*
* @param set 给定的集合
* @param array 给定的数组
* @return boolean 结果
*/
public static boolean containsAny(Collection<String> collection, String... array)
{
if (isEmpty(collection) || isEmpty(array))
{
return false;
}
else
{
for (String str : array)
{
if (collection.contains(str))
{
return true;
}
}
return false;
}
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
@@ -116,8 +116,7 @@ public class FileUtils
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists())
{
file.delete();
flag = true;
flag = file.delete();
}
return flag;
}
@@ -289,5 +288,4 @@ public class FileUtils
String baseName = FilenameUtils.getBaseName(fileName);
return baseName;
}
}
@@ -387,7 +387,7 @@ public final class HTMLFilter
{
paramValue = processParamProtocol(paramValue);
}
params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\"");
params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
}
}
@@ -7,12 +7,14 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@@ -22,7 +24,9 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
@@ -44,6 +48,7 @@ import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
@@ -148,6 +153,26 @@ public class ExcelUtil<T>
*/
private short maxHeight;
/**
* 合并后最后行数
*/
private int subMergedLastRowNum = 0;
/**
* 合并后开始行数
*/
private int subMergedFirstRowNum = 1;
/**
* 对象的子列表方法
*/
private Method subMethod;
/**
* 对象的子列表属性
*/
private List<Field> subFields;
/**
* 统计列表
*/
@@ -163,11 +188,27 @@ public class ExcelUtil<T>
*/
public Class<T> clazz;
/**
* 需要排除列属性
*/
public String[] excludeFields;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
/**
* 隐藏Excel中列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
* @throws Exception
*/
public void hideColumn(String... fields)
{
this.excludeFields = fields;
}
public void init(List<T> list, String sheetName, String title, Type type)
{
if (list == null)
@@ -181,6 +222,7 @@ public class ExcelUtil<T>
createExcelField();
createWorkbook();
createTitle();
createSubHead();
}
/**
@@ -190,13 +232,48 @@ public class ExcelUtil<T>
{
if (StringUtils.isNotEmpty(title))
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
titleLastCol = titleLastCol + subFields.size() - 1;
}
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(),
this.fields.size() - 1));
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
}
}
/**
* 创建对象的子列表名称
*/
public void createSubHead()
{
if (isSubList())
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum);
int excelNum = 0;
for (Object[] objects : fields)
{
Excel attr = (Excel) objects[1];
Cell headCell1 = subRow.createCell(excelNum);
headCell1.setCellValue(attr.name());
headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
excelNum++;
}
int headFirstRow = excelNum - 1;
int headLastRow = headFirstRow + subFields.size() - 1;
if (headLastRow > headFirstRow)
{
sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
}
rownum++;
}
}
@@ -576,8 +653,20 @@ public class ExcelUtil<T>
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
if (Collection.class.isAssignableFrom(field.getType()))
{
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++);
}
}
else
{
this.createHeadCell(excel, row, column++);
}
}
if (Type.EXPORT.equals(type))
{
@@ -593,21 +682,67 @@ public class ExcelUtil<T>
* @param index 序号
* @param row 单元格行
*/
@SuppressWarnings("unchecked")
public void fillExcelData(int index, Row row)
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
int rowNo = (1 + rownum) - startNo;
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 + rownum - startNo);
rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0;
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.addCell(excel, row, vo, field, column++);
if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
{
boolean subFirst = false;
for (Object obj : subList)
{
if (subFirst)
{
rowNo++;
row = sheet.createRow(rowNo);
}
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
}
subIndex++;
}
subFirst = true;
}
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
}
else
{
this.addCell(excel, row, vo, field, column++);
}
}
}
}
@@ -649,20 +784,6 @@ public class ExcelUtil<T>
style.setFont(dataFont);
styles.put("data", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
@@ -672,28 +793,62 @@ public class ExcelUtil<T>
style.setFont(totalFont);
styles.put("total", style);
styles.putAll(annotationStyles(wb));
styles.putAll(annotationHeaderStyles(wb, styles));
styles.putAll(annotationDataStyles(wb));
return styles;
}
/**
* 根据Excel注解创建表格样式
* 根据Excel注解创建表格样式
*
* @param wb 工作薄对象
* @return 自定义样式列表
*/
private Map<String, CellStyle> annotationStyles(Workbook wb)
private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
{
Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
if (!headerStyles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setFillForegroundColor(excel.headerBackgroundColor().index);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(excel.headerColor().index);
style.setFont(headerFont);
headerStyles.put(key, style);
}
}
return headerStyles;
}
/**
* 根据Excel注解创建表格列样式
*
* @param wb 工作薄对象
* @return 自定义样式列表
*/
private Map<String, CellStyle> annotationDataStyles(Workbook wb)
{
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
String key = "data_" + excel.align() + "_" + excel.color();
String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style = wb.createCellStyle();
style.setAlignment(excel.align());
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
@@ -704,6 +859,8 @@ public class ExcelUtil<T>
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
@@ -718,14 +875,23 @@ public class ExcelUtil<T>
/**
* 创建单元格
*/
public Cell createCell(Excel attr, Row row, int column)
public Cell createHeadCell(Excel attr, Row row, int column)
{
// 创建列
Cell cell = row.createCell(column);
// 写入列信息
cell.setCellValue(attr.name());
setDataValidation(attr, row, column);
cell.setCellStyle(styles.get("header"));
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
}
}
return cell;
}
@@ -746,6 +912,10 @@ public class ExcelUtil<T>
{
cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
}
if (value instanceof Collection && StringUtils.equals("[]", cellValue))
{
cellValue = StringUtils.EMPTY;
}
cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
}
else if (ColumnType.NUMERIC == attr.cellType())
@@ -813,8 +983,16 @@ public class ExcelUtil<T>
}
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
{
// 提示信息或只能选择不能输入的列内容.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
{
// 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
}
else
{
// 提示信息或只能选择不能输入的列内容.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
}
}
}
@@ -833,7 +1011,12 @@ public class ExcelUtil<T>
{
// 创建cell
cell = row.createCell(column);
cell.setCellStyle(styles.get("data_" + attr.align() + "_" + attr.color()));
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
}
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
@@ -855,7 +1038,7 @@ public class ExcelUtil<T>
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
@@ -913,6 +1096,58 @@ public class ExcelUtil<T>
sheet.addValidationData(dataValidation);
}
/**
* 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框).
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
*/
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
{
String hideSheetName = "combo_" + firstCol + "_" + endCol;
Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
Name name = wb.createName();
name.setNameName(hideSheetName + "_data");
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, regions);
if (StringUtils.isNotEmpty(promptContent))
{
// 如果设置了提示信息则鼠标放上去提示
dataValidation.createPromptBox("", promptContent);
dataValidation.setShowPromptBox(true);
}
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation)
{
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
}
else
{
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
// 设置hiddenSheet隐藏
wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
}
/**
* 解析导出值 0=男,1=女,2=未知
*
@@ -928,7 +1163,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@@ -965,7 +1200,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@@ -1178,29 +1413,39 @@ public class ExcelUtil<T>
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
}
}
}
@@ -1429,4 +1674,61 @@ public class ExcelUtil<T>
}
return str;
}
/**
* 是否有对象的子列表
*/
public boolean isSubList()
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0;
}
/**
* 是否有对象的子列表,集合不为空
*/
public boolean isSubListValue(T vo)
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
}
/**
* 获取集合的值
*/
public Collection<?> getListCellValue(Object obj)
{
Object value;
try
{
value = subMethod.invoke(obj, new Object[] {});
}
catch (Exception e)
{
return new ArrayList<Object>();
}
return (Collection<?>) value;
}
/**
* 获取对象的子列表方法
*
* @param name 名称
* @param pojoClass 类对象
* @return 子列表方法
*/
public Method getSubMethod(String name, Class<?> pojoClass)
{
StringBuffer getMethodName = new StringBuffer("get");
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
Method method = null;
try
{
method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
}
catch (Exception e)
{
log.error("获取对象异常{}", e.getMessage());
}
return method;
}
}
@@ -13,7 +13,7 @@ public class SqlUtil
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -37,7 +37,7 @@
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<exclusions>
<exclusion>
@@ -1,5 +1,7 @@
package com.ruoyi.framework.aspectj;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -9,8 +11,10 @@ import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.context.PermissionContextHolder;
/**
* 数据过滤处理
@@ -68,8 +72,9 @@ public class DataScopeAspect
// 如果是超级管理员,则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias());
controllerDataScope.userAlias(), permission);
}
}
}
@@ -79,15 +84,27 @@ public class DataScopeAspect
*
* @param joinPoint 切点
* @param user 用户
* @param userAlias 别名
* @param deptAlias 部门别名
* @param userAlias 用户别名
* @param permission 权限字符
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
{
StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<String>();
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
{
continue;
}
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
@@ -121,6 +138,7 @@ public class DataScopeAspect
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
}
}
conditions.add(dataScope);
}
if (StringUtils.isNotBlank(sqlString.toString()))
@@ -13,16 +13,16 @@ import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.enums.HttpMethod;
import com.ruoyi.common.filter.PropertyPreExcludeFilter;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.domain.SysOperLog;
@@ -38,6 +38,9 @@ public class LogAspect
{
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/** 排除敏感属性字段 */
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
/**
* 处理完请求后执行
*
@@ -74,7 +77,7 @@ public class LogAspect
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
operLog.setOperIp(ip);
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
if (loginUser != null)
{
operLog.setOperName(loginUser.getUsername());
@@ -99,7 +102,6 @@ public class LogAspect
catch (Exception exp)
{
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
@@ -149,8 +151,8 @@ public class LogAspect
}
else
{
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000));
}
}
@@ -168,7 +170,7 @@ public class LogAspect
{
try
{
Object jsonObj = JSON.toJSON(o);
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter());
params += jsonObj.toString() + " ";
}
catch (Exception e)
@@ -180,6 +182,14 @@ public class LogAspect
return params.trim();
}
/**
* 忽略敏感属性
*/
public PropertyPreExcludeFilter excludePropertyPreFilter()
{
return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES);
}
/**
* 判断是否需要过滤的对象。
*
@@ -50,7 +50,6 @@ public class RateLimiterAspect
@Before("@annotation(rateLimiter)")
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
{
String key = rateLimiter.key();
int time = rateLimiter.time();
int count = rateLimiter.count();
@@ -63,7 +62,7 @@ public class RateLimiterAspect
{
throw new ServiceException("访问过于频繁,请稍候再试");
}
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key);
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);
}
catch (ServiceException e)
{
@@ -5,7 +5,7 @@ import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
* 验证码文本生成器
*
*
* @author ruoyi
*/
public class KaptchaTextCreator extends DefaultTextCreator
@@ -20,7 +20,7 @@ public class KaptchaTextCreator extends DefaultTextCreator
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
int randomoperands = random.nextInt(3);
if (randomoperands == 0)
{
result = x * y;
@@ -30,7 +30,7 @@ public class KaptchaTextCreator extends DefaultTextCreator
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
if ((x != 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
@@ -45,7 +45,7 @@ public class KaptchaTextCreator extends DefaultTextCreator
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
else
{
if (x >= y)
{
@@ -62,13 +62,6 @@ public class KaptchaTextCreator extends DefaultTextCreator
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,8 +1,10 @@
package com.ruoyi.framework.config;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@@ -33,7 +35,8 @@ public class ResourcesConfig implements WebMvcConfigurer
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
}
/**
@@ -102,6 +102,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 禁用HTTP响应标头
.headers().cacheControl().disable().and()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
@@ -109,7 +111,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 过滤请求
.authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").anonymous()
.antMatchers("/login", "/register", "/captchaImage").permitAll()
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
@@ -0,0 +1,28 @@
package com.ruoyi.framework.security.context;
import org.springframework.security.core.Authentication;
/**
* 身份验证信息
*
* @author ruoyi
*/
public class AuthenticationContextHolder
{
private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
public static Authentication getContext()
{
return contextHolder.get();
}
public static void setContext(Authentication context)
{
contextHolder.set(context);
}
public static void clearContext()
{
contextHolder.remove();
}
}
@@ -0,0 +1,27 @@
package com.ruoyi.framework.security.context;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.ruoyi.common.core.text.Convert;
/**
* 权限信息
*
* @author ruoyi
*/
public class PermissionContextHolder
{
private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
public static void setContext(String permission)
{
RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
RequestAttributes.SCOPE_REQUEST);
}
public static String getContext()
{
return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
RequestAttributes.SCOPE_REQUEST));
}
}
@@ -10,7 +10,6 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
@@ -48,6 +47,6 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
// 记录用户退出日志
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
}
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功")));
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功")));
}
}
@@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.context.PermissionContextHolder;
/**
* RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
@@ -43,6 +44,7 @@ public class PermissionService
{
return false;
}
PermissionContextHolder.setContext(permission);
return hasPermissions(loginUser.getPermissions(), permission);
}
@@ -74,6 +76,7 @@ public class PermissionService
{
return false;
}
PermissionContextHolder.setContext(permissions);
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER))
{
@@ -23,6 +23,7 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
@@ -60,9 +61,9 @@ public class SysLoginService
*/
public String login(String username, String password, String code, String uuid)
{
boolean captchaOnOff = configService.selectCaptchaOnOff();
boolean captchaEnabled = configService.selectCaptchaEnabled();
// 验证码开关
if (captchaOnOff)
if (captchaEnabled)
{
validateCaptcha(username, code, uuid);
}
@@ -70,9 +71,10 @@ public class SysLoginService
Authentication authentication = null;
try
{
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(authenticationToken);
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
authentication = authenticationManager.authenticate(authenticationToken);
}
catch (Exception e)
{
@@ -87,6 +89,10 @@ public class SysLoginService
throw new ServiceException(e.getMessage());
}
}
finally
{
AuthenticationContextHolder.clearContext();
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
@@ -0,0 +1,94 @@
package com.ruoyi.framework.web.service;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
/**
* 登录密码方法
*
* @author ruoyi
*/
@Component
public class SysPasswordService
{
@Autowired
private RedisCache redisCache;
@Value(value = "${user.password.maxRetryCount}")
private int maxRetryCount;
@Value(value = "${user.password.lockTime}")
private int lockTime;
/**
* 登录账户密码错误次数缓存键名
*
* @param username 用户名
* @return 缓存键key
*/
private String getCacheKey(String username)
{
return CacheConstants.PWD_ERR_CNT_KEY + username;
}
public void validate(SysUser user)
{
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
String username = usernamePasswordAuthenticationToken.getName();
String password = usernamePasswordAuthenticationToken.getCredentials().toString();
Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
if (retryCount == null)
{
retryCount = 0;
}
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
}
if (!matches(user, password))
{
retryCount = retryCount + 1;
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
MessageUtils.message("user.password.retry.limit.count", retryCount)));
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
throw new UserPasswordNotMatchException();
}
else
{
clearLoginRecordCache(username);
}
}
public boolean matches(SysUser user, String rawPassword)
{
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
}
public void clearLoginRecordCache(String loginName)
{
if (redisCache.hasKey(getCacheKey(loginName)))
{
redisCache.deleteObject(getCacheKey(loginName));
}
}
}
@@ -1,9 +1,11 @@
package com.ruoyi.framework.web.service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRoleService;
@@ -59,7 +61,21 @@ public class SysPermissionService
}
else
{
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
List<SysRole> roles = user.getRoles();
if (!roles.isEmpty() && roles.size() > 1)
{
// 多角色设置permissions属性,以便数据权限匹配权限
for (SysRole role : roles)
{
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
perms.addAll(rolePerms);
}
}
else
{
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
}
}
return perms;
}
@@ -41,10 +41,12 @@ public class SysRegisterService
public String register(RegisterBody registerBody)
{
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
boolean captchaEnabled = configService.selectCaptchaEnabled();
if (captchaEnabled)
{
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
}
@@ -67,16 +69,14 @@ public class SysRegisterService
{
msg = "密码长度必须在5到20个字符之间";
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser)))
{
msg = "保存用户'" + username + "'失败,注册账号已存在";
}
else
{
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
sysUser.setPassword(SecurityUtils.encryptPassword(password));
boolean regFlag = userService.registerUser(sysUser);
if (!regFlag)
{
@@ -84,8 +84,7 @@ public class SysRegisterService
}
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER,
MessageUtils.message("user.register.success")));
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
}
}
return msg;
@@ -26,6 +26,9 @@ public class UserDetailsServiceImpl implements UserDetailsService
@Autowired
private ISysUserService userService;
@Autowired
private SysPasswordService passwordService;
@Autowired
private SysPermissionService permissionService;
@@ -50,6 +53,8 @@ public class UserDetailsServiceImpl implements UserDetailsService
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
passwordService.validate(user);
return createLoginUser(user);
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -69,7 +69,7 @@ public class GenController extends BaseController
map.put("info", table);
map.put("rows", list);
map.put("tables", tables);
return AjaxResult.success(map);
return success(map);
}
/**
@@ -110,7 +110,7 @@ public class GenController extends BaseController
// 查询表信息
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
genTableService.importGenTable(tableList);
return AjaxResult.success();
return success();
}
/**
@@ -123,7 +123,7 @@ public class GenController extends BaseController
{
genTableService.validateEdit(genTable);
genTableService.updateGenTable(genTable);
return AjaxResult.success();
return success();
}
/**
@@ -135,7 +135,7 @@ public class GenController extends BaseController
public AjaxResult remove(@PathVariable Long[] tableIds)
{
genTableService.deleteGenTableByIds(tableIds);
return AjaxResult.success();
return success();
}
/**
@@ -146,7 +146,7 @@ public class GenController extends BaseController
public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
{
Map<String, String> dataMap = genTableService.previewCode(tableId);
return AjaxResult.success(dataMap);
return success(dataMap);
}
/**
@@ -170,7 +170,7 @@ public class GenController extends BaseController
public AjaxResult genCode(@PathVariable("tableName") String tableName)
{
genTableService.generatorCode(tableName);
return AjaxResult.success();
return success();
}
/**
@@ -182,7 +182,7 @@ public class GenController extends BaseController
public AjaxResult synchDb(@PathVariable("tableName") String tableName)
{
genTableService.synchDb(tableName);
return AjaxResult.success();
return success();
}
/**
@@ -92,19 +92,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="updateGenTableColumn" parameterType="GenTableColumn">
update gen_table_column
<set>
column_comment = #{columnComment},
java_type = #{javaType},
java_field = #{javaField},
is_insert = #{isInsert},
is_edit = #{isEdit},
is_list = #{isList},
is_query = #{isQuery},
is_required = #{isRequired},
query_type = #{queryType},
html_type = #{htmlType},
dict_type = #{dictType},
sort = #{sort},
update_by = #{updateBy},
<if test="columnComment != null">column_comment = #{columnComment},</if>
<if test="javaType != null">java_type = #{javaType},</if>
<if test="javaField != null">java_field = #{javaField},</if>
<if test="isInsert != null">is_insert = #{isInsert},</if>
<if test="isEdit != null">is_edit = #{isEdit},</if>
<if test="isList != null">is_list = #{isList},</if>
<if test="isQuery != null">is_query = #{isQuery},</if>
<if test="isRequired != null">is_required = #{isRequired},</if>
<if test="queryType != null">query_type = #{queryType},</if>
<if test="htmlType != null">html_type = #{htmlType},</if>
<if test="dictType != null">dict_type = #{dictType},</if>
<if test="sort != null">sort = #{sort},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
update_time = sysdate()
</set>
where column_id = #{columnId}
@@ -53,7 +53,7 @@ public class ${ClassName}Controller extends BaseController
public AjaxResult list(${ClassName} ${className})
{
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
return AjaxResult.success(list);
return success(list);
}
#end
@@ -77,7 +77,7 @@ public class ${ClassName}Controller extends BaseController
@GetMapping(value = "/{${pkColumn.javaField}}")
public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
{
return AjaxResult.success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
}
/**
@@ -187,11 +187,11 @@
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
@@ -205,8 +205,11 @@
v-for="dict in dict.type.${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:value="parseInt(dict.value)"
#else
:value="dict.value"
#end
></el-option>
</el-select>
</el-form-item>
@@ -217,7 +220,7 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in dict.type.${dictType}"
@@ -228,24 +231,27 @@
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in dict.type.${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:label="parseInt(dict.value)"
#else
:label="dict.value"
#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
@@ -335,7 +341,7 @@ export default {
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
@@ -398,10 +404,7 @@ export default {
reset() {
this.form = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
#if($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
@@ -198,11 +198,11 @@
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
@@ -216,8 +216,11 @@
v-for="dict in dict.type.${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:value="parseInt(dict.value)"
#else
:value="dict.value"
#end
></el-option>
</el-select>
</el-form-item>
@@ -228,7 +231,7 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in dict.type.${dictType}"
@@ -239,24 +242,27 @@
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in dict.type.${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:label="parseInt(dict.value)"
#else
:label="dict.value"
#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
@@ -412,7 +418,7 @@ export default {
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
@@ -456,9 +462,7 @@ export default {
reset() {
this.form = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
#if($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
@@ -136,24 +136,9 @@
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
type="text"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button>
<el-button
type="text"
icon="Plus"
@click="handleAdd(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -188,11 +173,11 @@
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
@@ -206,8 +191,11 @@
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:value="parseInt(dict.value)"
#else
:value="dict.value"
#end
></el-option>
</el-select>
</el-form-item>
@@ -218,7 +206,7 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${dictType}"
@@ -229,24 +217,27 @@
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in ${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:label="parseInt(dict.value)"
#else
:label="dict.value"
#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
@@ -322,7 +313,7 @@ const data = reactive({
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
@@ -375,10 +366,7 @@ function cancel() {
function reset() {
form.value = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
#if($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
@@ -148,18 +148,8 @@
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
type="text"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button>
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -191,11 +181,11 @@
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
@@ -209,8 +199,11 @@
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:value="parseInt(dict.value)"
#else
:value="dict.value"
#end
></el-option>
</el-select>
</el-form-item>
@@ -221,7 +214,7 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${dictType}"
@@ -232,24 +225,27 @@
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in ${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
#if($column.javaType == "Integer" || $column.javaType == "Long")
:label="parseInt(dict.value)"
#else
:label="dict.value"
#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
@@ -398,7 +394,7 @@ const data = reactive({
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
@@ -442,9 +438,7 @@ function cancel() {
function reset() {
form.value = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
#if($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
@@ -492,8 +486,8 @@ function handleAdd() {
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const ${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(${pkColumn.javaField}).then(response => {
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(_${pkColumn.javaField}).then(response => {
form.value = response.data;
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
@@ -539,9 +533,9 @@ function submitForm() {
/** 删除按钮操作 */
function handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s);
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(_${pkColumn.javaField}s);
}).then(() => {
getList();
proxy.#[[$modal]]#.msgSuccess("删除成功");
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -71,7 +71,7 @@ public class SysJobController extends BaseController
@GetMapping(value = "/{jobId}")
public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
{
return AjaxResult.success(jobService.selectJobById(jobId));
return success(jobService.selectJobById(jobId));
}
/**
@@ -167,8 +167,8 @@ public class SysJobController extends BaseController
@PutMapping("/run")
public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
{
jobService.run(job);
return AjaxResult.success();
boolean result = jobService.run(job);
return result ? success() : error("任务不存在或已过期!");
}
/**
@@ -180,6 +180,6 @@ public class SysJobController extends BaseController
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
{
jobService.deleteJobByIds(jobIds);
return AjaxResult.success();
return success();
}
}
@@ -60,10 +60,10 @@ public class SysJobLogController extends BaseController
* 根据调度编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('monitor:job:query')")
@GetMapping(value = "/{configId}")
@GetMapping(value = "/{jobLogId}")
public AjaxResult getInfo(@PathVariable Long jobLogId)
{
return AjaxResult.success(jobLogService.selectJobLogById(jobLogId));
return success(jobLogService.selectJobLogById(jobLogId));
}
@@ -87,6 +87,6 @@ public class SysJobLogController extends BaseController
public AjaxResult clean()
{
jobLogService.cleanJobLog();
return AjaxResult.success();
return success();
}
}
@@ -74,7 +74,7 @@ public interface ISysJobService
* @param job 调度信息
* @return 结果
*/
public void run(SysJob job) throws SchedulerException;
public boolean run(SysJob job) throws SchedulerException;
/**
* 新增任务
@@ -174,15 +174,22 @@ public class SysJobServiceImpl implements ISysJobService
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void run(SysJob job) throws SchedulerException
public boolean run(SysJob job) throws SchedulerException
{
boolean result = false;
Long jobId = job.getJobId();
String jobGroup = job.getJobGroup();
SysJob properties = selectJobById(job.getJobId());
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap);
JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
if (scheduler.checkExists(jobKey))
{
result = true;
scheduler.triggerJob(jobKey, dataMap);
}
return result;
}
/**
@@ -52,12 +52,12 @@ public class JobInvokeUtil
{
if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0)
{
Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams));
method.invoke(bean, getMethodParamsValue(methodParams));
}
else
{
Method method = bean.getClass().getDeclaredMethod(methodName);
Method method = bean.getClass().getMethod(methodName);
method.invoke(bean);
}
}
@@ -83,7 +83,12 @@ public class ScheduleUtils
scheduler.deleteJob(getJobKey(jobId, jobGroup));
}
scheduler.scheduleJob(jobDetail, trigger);
// 判断任务是否过期
if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression())))
{
// 执行调度任务
scheduler.scheduleJob(jobDetail, trigger);
}
// 暂停任务
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.3</version>
<version>3.8.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,6 +1,7 @@
package com.ruoyi.system.domain;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -31,7 +32,7 @@ public class SysPost extends BaseEntity
/** 岗位排序 */
@Excel(name = "岗位排序")
private String postSort;
private Integer postSort;
/** 状态(0正常 1停用) */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
@@ -74,13 +75,13 @@ public class SysPost extends BaseEntity
this.postName = postName;
}
@NotBlank(message = "显示顺序不能为空")
public String getPostSort()
@NotNull(message = "显示顺序不能为空")
public Integer getPostSort()
{
return postSort;
}
public void setPostSort(String postSort)
public void setPostSort(Integer postSort)
{
this.postSort = postSort;
}
@@ -18,6 +18,14 @@ public interface SysConfigMapper
*/
public SysConfig selectConfig(SysConfig config);
/**
* 通过ID查询配置
*
* @param configId 参数ID
* @return 参数配置信息
*/
public SysConfig selectConfigById(Long configId);
/**
* 查询参数配置列表
*
@@ -34,6 +34,14 @@ public interface SysMenuMapper
*/
public List<SysMenu> selectMenuListByUserId(SysMenu menu);
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
public List<String> selectMenuPermsByRoleId(Long roleId);
/**
* 根据用户ID查询权限
*
@@ -107,7 +107,7 @@ public interface SysUserMapper
* @param userName 用户名称
* @return 结果
*/
public int checkUserNameUnique(String userName);
public SysUser checkUserNameUnique(String userName);
/**
* 校验手机号码是否唯一
@@ -31,7 +31,7 @@ public interface ISysConfigService
*
* @return true开启,false关闭
*/
public boolean selectCaptchaOnOff();
public boolean selectCaptchaEnabled();
/**
* 查询参数配置列表
@@ -19,6 +19,14 @@ public interface ISysDeptService
*/
public List<SysDept> selectDeptList(SysDept dept);
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
public List<TreeSelect> selectDeptTreeList(SysDept dept);
/**
* 构建前端所需要树结构
*
@@ -38,6 +38,14 @@ public interface ISysMenuService
*/
public Set<String> selectMenuPermsByUserId(Long userId);
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
public Set<String> selectMenuPermsByRoleId(Long roleId);
/**
* 根据用户ID查询菜单树信息
*
@@ -69,10 +69,10 @@ public interface ISysUserService
/**
* 校验用户名称是否唯一
*
* @param userName 用户名称
* @param user 用户信息
* @return 结果
*/
public String checkUserNameUnique(String userName);
public String checkUserNameUnique(SysUser user);
/**
* 校验手机号码是否唯一
@@ -86,14 +86,14 @@ public class SysConfigServiceImpl implements ISysConfigService
* @return true开启,false关闭
*/
@Override
public boolean selectCaptchaOnOff()
public boolean selectCaptchaEnabled()
{
String captchaOnOff = selectConfigByKey("sys.account.captchaOnOff");
if (StringUtils.isEmpty(captchaOnOff))
String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
if (StringUtils.isEmpty(captchaEnabled))
{
return true;
}
return Convert.toBool(captchaOnOff);
return Convert.toBool(captchaEnabled);
}
/**
@@ -134,6 +134,12 @@ public class SysConfigServiceImpl implements ISysConfigService
@Override
public int updateConfig(SysConfig config)
{
SysConfig temp = configMapper.selectConfigById(config.getConfigId());
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
{
redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
}
int row = configMapper.updateConfig(config);
if (row > 0)
{
@@ -48,6 +48,19 @@ public class SysDeptServiceImpl implements ISysDeptService
return deptMapper.selectDeptList(dept);
}
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
@Override
public List<TreeSelect> selectDeptTreeList(SysDept dept)
{
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
return buildDeptTreeSelect(depts);
}
/**
* 构建前端所需要树结构
*
@@ -58,11 +71,7 @@ public class SysDeptServiceImpl implements ISysDeptService
public List<SysDept> buildDeptTree(List<SysDept> depts)
{
List<SysDept> returnList = new ArrayList<SysDept>();
List<Long> tempList = new ArrayList<Long>();
for (SysDept dept : depts)
{
tempList.add(dept.getDeptId());
}
List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
for (SysDept dept : depts)
{
// 如果是顶级节点, 遍历该父节点的所有子节点
@@ -100,6 +100,27 @@ public class SysMenuServiceImpl implements ISysMenuService
return permsSet;
}
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
@Override
public Set<String> selectMenuPermsByRoleId(Long roleId)
{
List<String> perms = menuMapper.selectMenuPermsByRoleId(roleId);
Set<String> permsSet = new HashSet<>();
for (String perm : perms)
{
if (StringUtils.isNotEmpty(perm))
{
permsSet.addAll(Arrays.asList(perm.trim().split(",")));
}
}
return permsSet;
}
/**
* 根据用户ID查询菜单
*
@@ -202,11 +223,7 @@ public class SysMenuServiceImpl implements ISysMenuService
public List<SysMenu> buildMenuTree(List<SysMenu> menus)
{
List<SysMenu> returnList = new ArrayList<SysMenu>();
List<Long> tempList = new ArrayList<Long>();
for (SysMenu dept : menus)
{
tempList.add(dept.getMenuId());
}
List<Long> tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
{
SysMenu menu = (SysMenu) iterator.next();
@@ -458,8 +475,8 @@ public class SysMenuServiceImpl implements ISysMenuService
/**
* 递归列表
*
* @param list
* @param t
* @param list 分类表
* @param t 子节点
*/
private void recursionFn(List<SysMenu> list, SysMenu t)
{
@@ -504,11 +521,11 @@ public class SysMenuServiceImpl implements ISysMenuService
/**
* 内链域名特殊字符替换
*
* @return
* @return 替换后的内链域名
*/
public String innerLinkReplaceEach(String path)
{
return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS },
new String[] { "", "" });
return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." },
new String[] { "", "", "", "/" });
}
}
@@ -161,14 +161,15 @@ public class SysUserServiceImpl implements ISysUserService
/**
* 校验用户名称是否唯一
*
* @param userName 用户名称
* @param user 用户信息
* @return 结果
*/
@Override
public String checkUserNameUnique(String userName)
public String checkUserNameUnique(SysUser user)
{
int count = userMapper.checkUserNameUnique(userName);
if (count > 0)
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = userMapper.checkUserNameUnique(user.getUserName());
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
{
return UserConstants.NOT_UNIQUE;
}
@@ -507,6 +508,8 @@ public class SysUserServiceImpl implements ISysUserService
else if (isUpdateSupport)
{
BeanValidators.validateWithException(validator, user);
checkUserAllowed(user);
checkUserDataScope(user.getUserId());
user.setUpdateBy(operName);
this.updateUser(user);
successNum++;
@@ -59,6 +59,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</select>
<select id="selectConfigById" parameterType="Long" resultMap="SysConfigResult">
<include refid="selectConfigVo"/>
where config_id = #{configId}
</select>
<select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
<include refid="selectConfigVo"/>
where config_key = #{configKey} limit 1
@@ -59,8 +59,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
<include refid="selectDeptVo"/>
where dept_id = #{deptId}
select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status,
(select dept_name from sys_dept where dept_id = d.parent_id) parent_name
from sys_dept d
where d.dept_id = #{deptId}
</select>
<select id="checkDeptExistUser" parameterType="Long" resultType="int">
@@ -82,7 +84,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkDeptNameUnique" resultMap="SysDeptResult">
<include refid="selectDeptVo"/>
where dept_name=#{deptName} and parent_id = #{parentId} limit 1
where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1
</select>
<insert id="insertDept" parameterType="SysDept">
@@ -111,6 +111,13 @@
where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
</select>
<select id="selectMenuPermsByRoleId" parameterType="Long" resultType="String">
select distinct m.perms
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
where m.status = '0' and rm.role_id = #{roleId}
</select>
<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
where menu_id = #{menuId}
@@ -77,7 +77,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<set>
<if test="postCode != null and postCode != ''">post_code = #{postCode},</if>
<if test="postName != null and postName != ''">post_name = #{postName},</if>
<if test="postSort != null and postSort != ''">post_sort = #{postSort},</if>
<if test="postSort != null">post_sort = #{postSort},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
@@ -91,7 +91,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="postId != null and postId != 0">post_id,</if>
<if test="postCode != null and postCode != ''">post_code,</if>
<if test="postName != null and postName != ''">post_name,</if>
<if test="postSort != null and postSort != ''">post_sort,</if>
<if test="postSort != null">post_sort,</if>
<if test="status != null and status != ''">status,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
@@ -100,7 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="postId != null and postId != 0">#{postId},</if>
<if test="postCode != null and postCode != ''">#{postCode},</if>
<if test="postName != null and postName != ''">#{postName},</if>
<if test="postSort != null and postSort != ''">#{postSort},</if>
<if test="postSort != null">#{postSort},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
@@ -85,12 +85,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
where r.role_name=#{roleName} limit 1
where r.role_name=#{roleName} and r.del_flag = '0' limit 1
</select>
<select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
where r.role_key=#{roleKey} limit 1
where r.role_key=#{roleKey} and r.del_flag = '0' limit 1
</select>
<insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId">
@@ -98,7 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleId != null and roleId != 0">role_id,</if>
<if test="roleName != null and roleName != ''">role_name,</if>
<if test="roleKey != null and roleKey != ''">role_key,</if>
<if test="roleSort != null and roleSort != ''">role_sort,</if>
<if test="roleSort != null">role_sort,</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>
@@ -110,7 +110,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleId != null and roleId != 0">#{roleId},</if>
<if test="roleName != null and roleName != ''">#{roleName},</if>
<if test="roleKey != null and roleKey != ''">#{roleKey},</if>
<if test="roleSort != null and roleSort != ''">#{roleSort},</if>
<if test="roleSort != null">#{roleSort},</if>
<if test="dataScope != null and dataScope != ''">#{dataScope},</if>
<if test="menuCheckStrictly != null">#{menuCheckStrictly},</if>
<if test="deptCheckStrictly != null">#{deptCheckStrictly},</if>
@@ -126,7 +126,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<set>
<if test="roleName != null and roleName != ''">role_name = #{roleName},</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">role_sort = #{roleSort},</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>
@@ -139,7 +139,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update>
<delete id="deleteRoleById" parameterType="Long">
update sys_role set del_flag = '2' where role_id = #{roleId}
update sys_role set del_flag = '2' where role_id = #{roleId}
</delete>
<delete id="deleteRoleByIds" parameterType="Long">
@@ -122,7 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_name = #{userName}
where u.user_name = #{userName} and u.del_flag = '0'
</select>
<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
@@ -130,16 +130,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where u.user_id = #{userId}
</select>
<select id="checkUserNameUnique" parameterType="String" resultType="int">
select count(1) from sys_user where user_name = #{userName} limit 1
<select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
select user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0' limit 1
</select>
<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} limit 1
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} and del_flag = '0' limit 1
</select>
<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
select user_id, email from sys_user where email = #{email} limit 1
select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1
</select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
@@ -208,7 +208,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update>
<delete id="deleteUserById" parameterType="Long">
update sys_user set del_flag = '2' where user_id = #{userId}
update sys_user set del_flag = '2' where user_id = #{userId}
</delete>
<delete id="deleteUserByIds" parameterType="Long">
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "ruoyi",
"version": "3.8.3",
"version": "3.8.5",
"description": "若依管理系统",
"author": "若依",
"license": "MIT",
@@ -39,9 +39,9 @@
"@riophae/vue-treeselect": "0.4.0",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "3.19.1",
"echarts": "4.9.0",
"element-ui": "2.15.8",
"core-js": "3.25.3",
"echarts": "5.4.0",
"element-ui": "2.15.10",
"file-saver": "2.0.5",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",

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