Compare commits

...

473 Commits

Author SHA1 Message Date
RuoYi d488b79c2d 优化用户序列化忽略密码字段 2025-12-05 15:09:48 +08:00
RuoYi f53b783049 优化数据权限控制逻辑,放开permission限制 2025-12-04 17:35:47 +08:00
RuoYi 97f30a5415 支持Excel导出对象的多个子列表 2025-12-04 16:48:19 +08:00
RuoYi ad1d009165 升级tomcat到最新版本9.0.112 2025-12-04 16:43:11 +08:00
RuoYi 90cbabb7a7 优化代码 2025-12-04 16:42:55 +08:00
RuoYi 1c4dbb1e46 优化表单构建关闭页签销毁复制插件 2025-12-04 13:15:50 +08:00
RuoYi a3eefb6bad 优化生成代码下载的zip文件名 2025-12-03 10:27:23 +08:00
RuoYi 09e8e9995a 网页标题设置新增SET_TITLE方法 2025-12-02 19:31:23 +08:00
RuoYi 381151bc50 支持Excel导出对象的多个子列表 2025-12-02 19:14:04 +08:00
RuoYi 66e502727a 登录/注册页面底部版权信息修改为读取配置 2025-12-02 15:34:27 +08:00
RuoYi 4265f8ecb7 修复v3时间控件between选择后清空报错问题 2025-12-02 15:00:36 +08:00
RuoYi 2c82079d04 修复表单构建移除所有控件后切换路由回来空白问题 2025-12-02 13:12:55 +08:00
RuoYi 6aecd35a4f 修复combo属性过多sheet出现的异常问题 2025-11-13 11:58:03 +08:00
RuoYi ac92ae3ae6 修复固定头部时出现的导航栏偏移问题 2025-09-04 20:06:26 +08:00
RuoYi 1d2c8378f7 文件支持防盗链配置 2025-09-02 13:26:33 +08:00
RuoYi 50a9337ee8 优化代码 2025-08-28 13:51:15 +08:00
RuoYi e6a3415a71 优化代码 2025-08-27 16:01:28 +08:00
RuoYi 7919af54da 用户导入添加验证提示 2025-08-23 11:46:49 +08:00
RuoYi 3503005f9d 优化布局设置显示 2025-08-23 11:46:39 +08:00
RuoYi b304a41194 修复用户归属部门无法修改为空问题 2025-08-21 14:59:10 +08:00
RuoYi a39ae33c82 columns default value 2025-08-09 16:13:49 +08:00
RuoYi b9a27657c5 显示列信息支持对象格式 2025-08-09 15:19:13 +08:00
RuoYi 2e009841ca 自动识别json对象白名单配置范围缩小 2025-08-09 15:18:29 +08:00
RuoYi 2cbe4a8234 升级tomcat到最新版本9.0.108 2025-08-09 15:17:10 +08:00
RuoYi 4b37049713 添加新群号:112869560 2025-07-19 19:28:44 +08:00
RuoYi e549210ad6 优化定时任务包名白名单匹配方式 2025-06-20 11:56:03 +08:00
RuoYi ad988d54bb 优化Excel统计行数值的单元格样式显示 2025-06-19 14:54:00 +08:00
RuoYi 51a6fce0a5 升级tomcat到最新版本9.0.106 2025-06-18 13:41:37 +08:00
RuoYi c86bfa9243 用户头像更换后移除旧头像文件 2025-06-06 19:36:36 +08:00
RuoYi 8aca11c2a2 若依 3.6.6 2025-05-30 08:03:00 +08:00
RuoYi 725033e361 升级fastjson到最新版2.0.57 2025-05-26 11:14:45 +08:00
RuoYi d29e49e23b 注册账号设置默认密码最后更新时间 2025-05-26 11:14:06 +08:00
RuoYi 706c3bb69b 添加底部版权信息及开关 2025-05-24 14:33:51 +08:00
RuoYi cd0ee95b9c 添加页签图标显示开关功能 2025-05-23 14:57:49 +08:00
RuoYi 3293e2fb56 账号密码支持自定义更新周期 2025-05-23 10:19:47 +08:00
RuoYi 924ec0eb6e 初始密码支持自定义修改策略 2025-05-23 09:58:23 +08:00
RuoYi 135b1204a9 升级tomcat到最新版本9.0.105 2025-05-15 10:55:18 +08:00
RuoYi cb566a704b 升级commons.io到最新版本2.19.0 2025-05-15 10:23:50 +08:00
RuoYi aadba0382e delete vue-meta 2025-05-15 10:23:34 +08:00
RuoYi a0ce1cf33b delete eslint 2025-05-15 10:22:46 +08:00
RuoYi 3915c77391 优化导航栏显示昵称&设置 2025-05-09 14:02:09 +08:00
RuoYi b80932ceb4 菜单搜索支持键盘选择&悬浮主题背景 2025-05-07 13:27:13 +08:00
RuoYi 056cf94082 图片上传组件新增disabled属性 2025-05-06 19:14:54 +08:00
RuoYi 0dcd3e6183 add columnName Drag 2025-05-06 14:54:44 +08:00
RuoYi 07be5ceb26 修复上传组件被多次引用拖动仅对第一个有效的问题 2025-05-06 13:46:21 +08:00
RuoYi cc59502d7c update icon 2025-05-05 11:22:35 +08:00
RuoYi 98738f23ad 上传组件新增拖动排序属性 2025-04-30 10:31:03 +08:00
RuoYi 57fe1c663e 优化Excel匹配数值型.0结尾 2025-04-28 11:20:48 +08:00
RuoYi 7b6fdb3a89 remove all semicolons 2025-04-27 11:56:21 +08:00
RuoYi 79c885decb 使用Gateway CacheRequestBody代替CacheRequestFilter 2025-04-25 15:11:17 +08:00
RuoYi 1a0f37a2dc 富文本复制粘贴图片上传至url 2025-04-24 18:19:16 +08:00
RuoYi 02de344d8c update package.json 2025-04-24 18:18:44 +08:00
RuoYi 189100f74e 优化低版本node无法启动的问题 2025-04-22 12:07:07 +08:00
RuoYi e29284e687 优化代码 2025-04-22 12:06:59 +08:00
RuoYi d4af286f41 显隐列组件支持全选/全不选 2025-04-21 15:30:32 +08:00
RuoYi 60e2d55a23 优化菜单搜索查询页 2025-04-21 13:28:32 +08:00
RuoYi bbd112d5a3 支持文件&图片组件自定义地址&参数 2025-04-18 13:25:28 +08:00
RuoYi 90922844ea 优化角色禁用不允许分配 2025-04-17 15:36:18 +08:00
RuoYi 3a9f56f04b update status name 2025-04-17 15:35:58 +08:00
RuoYi a1ec1d57d4 remove dev runjs 2025-03-18 16:01:46 +08:00
RuoYi 060959a7c5 登录页和注册页表头使用VUE_APP_TITLE配置值 2025-03-18 16:01:20 +08:00
RuoYi 43e1d8d573 升级tomcat到最新版本9.0.102 2025-03-14 16:12:40 +08:00
RuoYi 67cf51ba77 update handleTree 2025-03-14 16:12:29 +08:00
RuoYi a256618d5d 优化代码 2025-03-11 12:52:17 +08:00
若依 a6bcebb62b
!397 修复actuator暴漏问题
Merge pull request !397 from 威士忌的纯度/N/A
2025-03-10 03:45:34 +00:00
威士忌的纯度 1cb262daa3
修复actuator暴漏问题
Signed-off-by: 威士忌的纯度 <whr888888@vip.qq.com>
2025-03-07 10:22:52 +00:00
RuoYi 8c096cba8d 优化isAdmin方法,避免脱敏模块security依赖 2025-03-07 12:56:31 +08:00
RuoYi 088cec8adf 菜单管理新增路由名称 2025-03-06 11:09:34 +08:00
RuoYi 85ff6a9910 优化顶部菜单搜索栏为多层级显示 2025-03-05 18:14:13 +08:00
RuoYi cab5beaca7 文件上传组件新增disabled属性&类型 2025-03-05 18:13:40 +08:00
RuoYi fc8069a250 优化导出Excel日期格式双击离开后与设定的格式不一致问题 2025-03-05 18:13:12 +08:00
RuoYi 924e705dca 代码生成列表支持按时间排序 2025-03-05 18:12:52 +08:00
RuoYi 049ba453d1 优化空指针异常时无法获取错误信息问题 2025-03-05 18:10:56 +08:00
RuoYi 4aa261e8f7 优化定时任务字符包含多个括号导致数据错误 2025-03-05 18:10:12 +08:00
RuoYi 914a6620f5 升级tomcat到最新版本9.0.98 2025-03-05 18:08:29 +08:00
RuoYi 3dcee7057d 优化代码 2025-03-05 18:01:33 +08:00
RuoYi 0467631319 update ry_config.sql 2025-02-24 16:24:36 +08:00
若依 a11df90255
!393 config(nacos):增加nacos2.5.0配置文件sql
Merge pull request !393 from 牟雷/master
2025-02-18 00:33:39 +00:00
牟雷 596e4fe756 config(nacos):增加nacos2.5.0配置文件sql 2025-02-17 20:19:22 +08:00
RuoYi 37219e4ae6 copyright 2025 2025-01-07 10:55:58 +08:00
RuoYi adaa3e1db8 代码生成新增配置是否允许文件覆盖到本地 2024-12-25 16:30:44 +08:00
RuoYi 88ad5a2c19 优化导入带标题文件关闭清理 2024-12-25 16:24:38 +08:00
RuoYi b45dc2ec25 update sqlkeyword 2024-12-25 16:24:02 +08:00
RuoYi 67b17da06f 优化特殊字符密码修改失败问题 2024-12-17 14:28:17 +08:00
RuoYi b25a280ebb 优化TopNav内链菜单点击没有高亮(IB8WHJ) 2024-12-17 11:57:05 +08:00
RuoYi cc026e75a3 优化菜单管理切换Mini布局错乱问题 2024-12-17 11:25:03 +08:00
RuoYi 7216b56a56 用户管理过滤掉已禁用部门 2024-12-11 11:43:00 +08:00
RuoYi a326e880a1 修改主题样式本地读取 2024-12-07 17:08:53 +08:00
RuoYi 92c6d21855 优化文件异常输入流未关闭的问题 2024-12-05 14:27:54 +08:00
RuoYi 2335157f6e 白名单支持对通配符路径匹配 2024-12-04 08:52:13 +08:00
RuoYi 6c3b01c3c5 Excel注解支持wrapText是否允许内容换行 2024-12-03 09:07:04 +08:00
RuoYi 8faea60191 修复导出子列表对象只能在最后的问题 2024-12-02 20:37:12 +08:00
RuoYi 28a16d9878 修复默认关闭Tags-Views时,内链页面打不开 2024-11-27 19:49:12 +08:00
RuoYi dd3cf18e27 修复TopNav无法正确获取active的问题 2024-11-27 09:02:26 +08:00
RuoYi 65d03dc014 优化代码 2024-11-25 22:30:03 +08:00
RuoYi 7912fd81bd 面板兼容移动端显示 2024-11-25 15:41:00 +08:00
RuoYi e2175e5b9d 参数键值更换为多行文本 2024-11-25 12:15:49 +08:00
RuoYi c0e119f8e0 菜单面包屑导航支持多层级显示 2024-11-22 20:45:08 +08:00
RuoYi fa77b2a08c 分栏参数微调 2024-11-22 14:46:59 +08:00
RuoYi a222c24796 用户管理支持分栏拖动 2024-11-22 13:58:37 +08:00
RuoYi 08f4b877ce 优化代码 2024-11-20 11:13:24 +08:00
RuoYi aa607d135c update .env.staging 2024-11-20 10:43:07 +08:00
RuoYi 6d34cdb8a3 若依 3.6.5 2024-11-13 08:38:24 +08:00
RuoYi d47352253e 升级spring-cloud相关组件到最新版 2024-11-12 15:12:01 +08:00
RuoYi 61cbd470e1 update datascope 2024-11-12 15:10:47 +08:00
RuoYi b3ef4adfed 支持自定义显示Excel属性列 2024-11-07 22:25:48 +08:00
RuoYi 856c471472 优化代码 2024-11-06 10:20:18 +08:00
RuoYi bec5600f16 优化无用户编号不校验数据权限 2024-11-05 16:30:15 +08:00
RuoYi 5b485e7934 校检文件名是否包含特殊字符 2024-11-05 12:50:12 +08:00
RuoYi 73a752d3ab 优化身份证脱敏正则 2024-10-21 17:16:01 +08:00
RuoYi 1899a832b9 优化权限更新后同步缓存 2024-10-21 17:15:30 +08:00
RuoYi e6796c0954 操作日志记录DELETE请求参数 2024-10-17 13:17:25 +08:00
RuoYi 4987289a98 升级quill到最新版本2.0.2 2024-10-15 16:21:20 +08:00
RuoYi 18409922a5 修改代码生成上级菜单字段类型 2024-09-27 16:23:36 +08:00
RuoYi 3dca02b306 修复角色禁用权限不失效问题 2024-09-21 12:08:41 +08:00
RuoYi 75f3275e15 修复角色禁用权限不失效问题 2024-09-21 12:01:48 +08:00
RuoYi b2e4a7046b update ry_config 2024-09-02 20:21:30 +08:00
RuoYi 60618c1da9 优化提示 2024-09-02 20:21:15 +08:00
RuoYi 3b499b1344 使用SpringDoc代替Swagger 2024-08-30 11:26:57 +08:00
RuoYi 8984ecba86 记录用户登录IP地址和登录时间 2024-07-09 12:12:01 +08:00
RuoYi 0953a9c0b2 记录用户登录IP地址和登录时间 2024-07-09 12:06:40 +08:00
RuoYi fcff9dfdea 修改时间范围日期格式 2024-07-08 16:57:25 +08:00
RuoYi d1cb4e1f71 remove sub resultType 2024-07-08 16:57:04 +08:00
RuoYi 68ef1297cb avatar add headers 2024-07-02 16:10:58 +08:00
RuoYi b79f01e051 升级axios到最新版本0.28.1 2024-07-02 12:58:10 +08:00
RuoYi 095f3a126f 菜单管理新增路由名称 2024-06-29 22:46:54 +08:00
RuoYi ce94a9d620 升级core-js到最新版本3.37.1 2024-06-29 22:46:18 +08:00
RuoYi 2a73de34f0 优化代码 2024-06-29 22:45:51 +08:00
RuoYi 8694501a7e 升级druid到最新版本1.2.23 2024-06-25 13:55:12 +08:00
RuoYi 4dfc3d766e 优化代码 2024-06-25 13:53:58 +08:00
RuoYi 0680d1ed1f 优化数据权限代码 2024-06-05 12:48:37 +08:00
RuoYi 493dee03c8 优化代码生成主子表关联查询方式 2024-06-05 12:48:18 +08:00
RuoYi 3992b1e666 添加新群号:158753145 2024-05-29 15:18:57 +08:00
RuoYi c855884ebd update sql 2024-05-29 15:18:36 +08:00
RuoYi 19c457ae5f 限制用户操作数据权限范围 2024-05-29 15:18:20 +08:00
若依 1a3751ab71
!368 未合理判断验证码失效
Merge pull request !368 from PowderSnow/N/A
2024-05-29 07:00:02 +00:00
PowderSnow af8d62e5e2
update ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java.
目前报”验证码已失效“的场景是uuid为空,应通过判断captcha是否为null得出验证码是否已过期的结果。

Signed-off-by: PowderSnow <1109835296@qq.com>
2024-05-12 19:21:59 +00:00
RuoYi cf03781bd7 升级spring-framework到安全版本,防止漏洞风险 2024-04-11 17:01:16 +08:00
RuoYi fa2a28e877 新增数据脱敏过滤注解 2024-04-08 13:16:52 +08:00
RuoYi e2f1b31735 若依 3.6.4 2024-04-01 09:28:45 +08:00
RuoYi 488aafb683 升级spring-boot-admin到最新版2.7.15 2024-03-29 11:08:23 +08:00
RuoYi 735273d69f Excel注解ColumnType类型新增文本 2024-03-22 16:44:18 +08:00
RuoYi f2a587c2f9 更新compressionPlugin到6.1.2以兼容node18+ 2024-03-18 14:30:11 +08:00
RuoYi 4f7bcef44c 定时任务白名单配置范围缩小 2024-03-11 11:23:38 +08:00
RuoYi 393a9326c8 update copyright 2024 2024-03-11 10:48:30 +08:00
若依 33a52c8166
!360 update ruoyi-modules/ruoyi-job/src/main/resources/mapper/job/SysJobLogMapper.xml.
Merge pull request !360 from 刘继东/N/A
2024-03-04 01:48:41 +00:00
刘继东 b44e0e4de6
update ruoyi-modules/ruoyi-job/src/main/resources/mapper/job/SysJobLogMapper.xml.
任务运行日志列表增加按创建日期倒叙排序

Signed-off-by: 刘继东 <wwwliujidong@163.com>
2024-03-02 03:52:29 +00:00
RuoYi 3fa4901d57 用户密码新增非法字符验证 2024-03-01 21:55:38 +08:00
RuoYi 2dca6f0a12 优化匹配方式 2024-03-01 21:55:28 +08:00
RuoYi 78e61d89ba 添加新群号:179219821 2024-01-11 15:47:14 +08:00
RuoYi 4908b6230b update vue.config.js 2024-01-11 15:47:05 +08:00
RuoYi f6d4f5c6e3 升级element-ui到最新版本2.15.14 2023-12-07 11:19:06 +08:00
RuoYi 1580c1e672 删除无用的代码 2023-12-07 11:18:32 +08:00
RuoYi 6ff45b2644 升级spring-cloud相关组件到最新版 2023-12-04 16:46:42 +08:00
RuoYi ae77c82304 update ry_config.sql 2023-12-04 16:45:53 +08:00
RuoYi 41c2d6fc2a 显隐列组件支持复选框弹出类型 2023-12-01 11:20:51 +08:00
RuoYi d0e9e07e9c 代码生成支持选择前端模板类型 2023-11-30 09:46:27 +08:00
RuoYi 210626b21f 修复头像上传成功图片不显示问题 2023-11-30 09:46:06 +08:00
RuoYi 85ab6236e7 优化代码 2023-11-30 09:45:07 +08:00
RuoYi 0037e65ca0 优化头像上传参数新增文件名称 2023-11-29 13:00:45 +08:00
RuoYi adec3f0608 优化字典标签支持自定义分隔符 2023-11-29 12:59:55 +08:00
RuoYi e7adf59b88 优化下载zip方法新增遮罩层 2023-11-29 12:59:42 +08:00
RuoYi 21a17945fa 优化代码 2023-11-29 12:59:22 +08:00
RuoYi b7abcd8374 优化个人中心/基本资料修改时数据显示问题 2023-11-28 13:07:42 +08:00
RuoYi 2eeb642f07 优化白名单页面放行逻辑 2023-11-28 13:06:20 +08:00
RuoYi 4512af436d 防止高频率定时任务不执行问题 2023-11-28 13:06:06 +08:00
若依 6a8964f086
!347 update ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java.
Merge pull request !347 from 刚刚好/N/A
2023-11-28 05:04:55 +00:00
刚刚好 75b2eb067d
update ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java.
提交错别字

Signed-off-by: 刚刚好 <380862139@qq.com>
2023-11-12 02:40:27 +00:00
RuoYi 2eaabefeac 修改权限字符匹配方式 2023-11-10 16:18:24 +08:00
RuoYi c3ab80967c 修复五级路由缓存无效问题 2023-11-10 15:31:43 +08:00
RuoYi 892e3ac822 修复内链iframe没有传递参数问题 2023-11-10 11:19:31 +08:00
RuoYi e2b4bb0420 修复外链带端口出现的异常 2023-11-07 11:41:50 +08:00
RuoYi d6b4806e43 修复数据字典列表页重置后标签值无法输入问题 2023-11-01 10:01:47 +08:00
RuoYi 7df1b02476 优化数字金额大写转换精度丢失问题 2023-11-01 10:00:21 +08:00
RuoYi 6d9cbe218c 升级fastjson到最新版2.0.41 2023-10-21 15:16:38 +08:00
RuoYi 302299bbb0 登录不做数据重复提交验证 2023-10-21 14:32:50 +08:00
RuoYi 437301d5d9 去掉多余的参数 2023-10-21 14:32:43 +08:00
RuoYi dc121ff4aa 富文本Editor组件检验图片格式 2023-10-02 12:46:35 +08:00
RuoYi c4cda3f4ad 修复HeaderSearch组件跳转query参数丢失问题 2023-09-28 22:21:50 +08:00
RuoYi e067c04464 操作日志列表新增IP地址查询 2023-09-27 15:27:29 +08:00
RuoYi af03fefc83 全局数据存储用户编号 2023-09-27 15:27:07 +08:00
RuoYi 2d49f2a56e 优化菜单管理类型为按钮状态可选 2023-09-18 15:05:23 +08:00
RuoYi 2af351f898 修复自定义字典样式不生效的问题 2023-09-14 17:27:13 +08:00
wind a709c8f06e
update docker/copy.sh.
Signed-off-by: wind <zhangmrit@126.com>
2023-09-05 08:50:40 +00:00
RuoYi b00775f988 删除无用的传参 2023-09-01 09:40:02 +08:00
RuoYi 48711178ec 优化TopNav菜单没有图标svg不显示 2023-08-31 10:21:59 +08:00
RuoYi 07bb636109 修改未登录访问需要登录的资源,在登录后重定向丢失请求参数问题 2023-08-31 10:21:08 +08:00
RuoYi 24e0fa863e 优化代码 2023-08-25 09:45:44 +08:00
RuoYi fb6d93fbab 修复字典缓存删除方法参数错误问题 2023-08-23 14:56:07 +08:00
RuoYi db18477786 修复Excels导入时无法获取到readConverterExp内容转表达式问题 2023-08-21 16:01:55 +08:00
RuoYi 91575613a8 防重复提交数据大小限制 2023-08-21 11:57:58 +08:00
RuoYi a5354083b9 Excel导入数据临时文件无法删除问题 2023-08-19 16:24:04 +08:00
RuoYi 1665fa2793 升级fastjson到最新版2.0.39 2023-08-15 12:24:16 +08:00
RuoYi df8d6bcd33 升级commons.io到最新版本2.13.0 2023-08-15 12:20:37 +08:00
若依 2fecc6273b
!340 修改个人信息:防止用户有目的性的修改其他属性
Merge pull request !340 from 码上秃Hello/N/A
2023-08-15 04:17:49 +00:00
码上秃Hello 8b252709a4
修改个人信息:防止用户有目的性的修改其他属性
Signed-off-by: 码上秃Hello <19973252123@163.com>
2023-08-15 03:25:00 +00:00
RuoYi b2cb085f21 Excel自定义数据处理器增加单元格/工作簿对象 2023-08-14 19:20:04 +08:00
RuoYi 1b1bc96bd5 优化定时任务状态页面显示 2023-08-14 19:19:55 +08:00
RuoYi a416d55780 优化代码 2023-08-14 19:19:35 +08:00
RuoYi 1994aff544 添加新群号:128355254 2023-07-28 11:22:41 +08:00
RuoYi b18eced03d 若依 3.6.3 2023-07-07 08:30:21 +08:00
RuoYi ee2fef02f8 排序属性orderBy参数限制长度 2023-07-06 22:29:30 +08:00
RuoYi ad954dacb7 屏蔽定时任务bean违规的字符 2023-07-06 22:29:09 +08:00
RuoYi 10de4eb96d 升级spring-cloud相关组件到最新版 2023-07-06 20:01:30 +08:00
RuoYi a5b612c8e4 update sql 2023-07-06 20:00:45 +08:00
RuoYi ebc848b5b5 优化页签在Firefox浏览器被遮挡的问题(I7BVAJ) 2023-07-06 09:27:48 +08:00
若依 f31c207551
!333 注释名称与参数名不一致
Merge pull request !333 from mxy/master
2023-07-06 01:26:09 +00:00
若依 dd338b56da
!332 在全局异常拦截器中增加两类异常处理
Merge pull request !332 from OTTO/master
2023-07-06 01:26:05 +00:00
BearXuan 7c3d7b384c 注释名称与参数名不一致 2023-07-03 15:18:33 +08:00
otto 0647ca8b66 style(在全局异常拦截器中增加两类异常处理): 格式化代码 2023-07-03 11:52:23 +08:00
otto f3477f75e6 Merge branch 'master' of gitee.com:OTTTTO/RuoYi-Cloud 2023-07-03 11:04:55 +08:00
otto 22fa7ac6f6 feat(在全局异常拦截器中增加两类异常处理): 1、请求路径中缺少必需的路径变量;2、请求参数类型不匹配; 2023-07-03 11:04:22 +08:00
otto 924aafae86 feat(在全局异常拦截器中增加两类异常处理): 1、请求路径中缺少必需的路径变量;2、请求参数类型不匹配 2023-07-03 11:02:12 +08:00
RuoYi 5280fb5a0d 升级element-ui到最新版本2.15.13 2023-06-30 14:05:22 +08:00
RuoYi d3c6ba2598 升级fastjson到最新版2.0.34 2023-06-30 14:05:13 +08:00
RuoYi 08308d61c7 优化侧边栏的平台标题与VUE_APP_TITLE保持同步 2023-06-30 14:04:52 +08:00
RuoYi 356b451b2a optimized code 2023-06-30 14:03:52 +08:00
RuoYi a606973cbe 恢复翻页/切换路由滚动功能 2023-04-23 16:59:22 +08:00
RuoYi 19fb27502b 修复代码生成表字段注释不全问题 2023-04-23 16:58:43 +08:00
RuoYi d7b309afd9 修复路由跳转被阻止时vue-router内部产生报错信息问题 2023-04-23 16:58:19 +08:00
RuoYi d9bfc3e322 DictTag组件,当value没有匹配的值时,展示value 2023-04-23 16:57:54 +08:00
RuoYi 74045776d6 优化文件输入流可能为空的问题 2023-04-18 16:14:08 +08:00
若依 5fcec99e6c
!321 解决文件输入流为可能为空的问题
Merge pull request !321 from maochd/master
2023-04-18 08:07:22 +00:00
maochd 102a5ac575 简化允许下载的文件规则判断 2023-04-18 13:56:59 +08:00
maochd 3786f3671d 解决文件输入流为可能为空的问题 2023-04-18 13:55:07 +08:00
RuoYi 49e6fbf2ff 修复开启TopNav后一级菜单路由参数设置无效问题(I6T1DK) 2023-04-11 16:52:35 +08:00
RuoYi 81a8192de7 修复导入用户时无法更新存在用户数据的问题 2023-04-10 18:17:12 +08:00
RuoYi a366d09659 优化已选择下拉图标高亮回显 2023-04-10 18:17:00 +08:00
RuoYi 2fe7341fa7 优化避免鼠标移出时无法隐藏滚动条的问题 2023-04-10 18:15:36 +08:00
RuoYi a3615e5c6c 优化代码 2023-04-10 18:14:54 +08:00
RuoYi 68eac98acf 优化代码 2023-04-05 19:16:25 +08:00
RuoYi d4bae9745c 修复tab栏”关闭其他“异常的问题 2023-04-05 19:03:18 +08:00
RuoYi 23ae0eb43b 修复tab栏”关闭其他“异常的问题 2023-04-05 19:02:44 +08:00
RuoYi 308d497d74 优化生成表字段comment过长问题 2023-04-05 19:00:27 +08:00
RuoYi 7af254ee51 delete vue-multiselect style 2023-04-05 18:59:31 +08:00
RuoYi 2ad13c9f72 优化固定头部页签滚动条被隐藏的问题(I6ORT1) 2023-04-05 16:19:47 +08:00
RuoYi 56d50d10e9 update docker 2023-04-05 16:04:07 +08:00
RuoYi 0b21d15f26 优化代码 2023-03-29 10:45:46 +08:00
若依 7421d7ccce
!313 异步保存日志的时候,报错被吞 ,导致没跑进RemoteLogFallbackFactory中
Merge pull request !313 from Llorando/master
2023-03-29 02:44:23 +00:00
若依 84ba2dbd93
!310 完善ruoyi-file模块的upload接口在文件过大和文件名过长的情况下的返回值中的msg提示信息
Merge pull request !310 from pigwantacat/master
2023-03-29 02:39:08 +00:00
若依 55447c72e9
!306 注释 @EnableCustomSwagger2 注解后,项目启动失败
Merge pull request !306 from Gelis/master
2023-03-29 02:30:18 +00:00
若依 26c63520f2
!302 【轻量级 PR】 文件上传服务获取InputStream未关闭
Merge pull request !302 from 程序凡/master
2023-03-29 02:02:48 +00:00
Llorando 8b52b90670 异步保存日志的时候,报错被吞,导致没跑进RemoteLogFallbackFactory中 2023-03-21 17:24:33 +08:00
RuoYi 05ca78e82f 添加新群号:101038945 2023-03-18 10:51:46 +08:00
RuoYi b155059d66 升级fastjson到最新版2.0.25 2023-03-18 10:45:57 +08:00
RuoYi f8ad7ea3ce 支持自定义隐藏属性列过滤子对象 2023-03-18 10:45:29 +08:00
RuoYi feff419641 关闭页签后存在其他页签时不应该跳转首页 2023-03-18 10:44:37 +08:00
RuoYi 33a0806cbe 优化弹窗后导航栏偏移的问题 2023-03-18 10:43:52 +08:00
RuoYi 230e2bb3f4 delete build style 2023-03-18 10:42:44 +08:00
RuoYi 24d9ccba40 修复页面切换时布局错乱的问题 2023-03-18 10:42:31 +08:00
RuoYi dc24ed81b8 修复用户多角色数据权限可能出现权限抬升的情况 2023-03-18 10:41:33 +08:00
pigwantacat 504a4e8e66 完善ruoyi-file模块的upload接口在文件过大和文件名过长的情况下的返回值中的msg提示信息 2023-03-16 23:48:40 +08:00
RuoYi 775234dabe 优化修改密码日志存储明文问题(I6ESO9) 2023-03-05 13:07:22 +08:00
RuoYi 7fdd20c054 优化文件下载出现的异常(I6DLNU) 2023-02-28 15:02:20 +08:00
Gelis 1eeed86b65
修复注释 @EnableCustomSwagger2 后,项目启动失败
Signed-off-by: Gelis <806938079@qq.com>
2023-02-24 08:56:26 +00:00
RuoYi 7c9903e057 日志管理使用索引提升查询性能 2023-02-23 12:32:02 +08:00
若依 20dd6d37ea
!305 修复新增参数时判断错误的问题
Merge pull request !305 from Rain/N/A
2023-02-22 02:54:42 +00:00
Rain 89a04423cd
修复新增参数管理时判断错误的问题
Signed-off-by: Rain <938448486@qq.com>
2023-02-22 02:53:40 +00:00
若依 c42b4cad02
!304 修复isMatchedIp的参数判断产生NullPointerException的问题
Merge pull request !304 from wangfeiyu/dev20230222
2023-02-22 02:23:46 +00:00
wangfeiyu 4b21a3bc48 在方法isMatchedIp的参数中,当filter为null而ip非null/空时,报filter为null异常。把判断条件由&&改为||解决此bug。 2023-02-22 08:54:10 +08:00
RuoYi 1ef82d75b1 移除apache/commons-fileupload依赖 2023-02-21 22:55:51 +08:00
RuoYi c10a3b6dbb 升级druid到最新版本1.2.16 2023-02-21 22:50:54 +08:00
RuoYi b93c9bfc5d 优化代码 2023-02-21 22:50:27 +08:00
RuoYi cd5556d188 支持登录IP黑名单限制 2023-02-21 10:31:54 +08:00
RuoYi 1126e2234f 日志注解支持排除指定的请求参数 2023-02-21 09:14:37 +08:00
CQG dce91a03ef 文件上传服务获取InputStream未关闭,导致删除临时文件删除失败 2023-02-17 14:19:16 +08:00
RuoYi 8dff14a6cc 操作日志新增消耗时间属性 2023-02-16 11:10:00 +08:00
RuoYi 3462c58ce4 升级fastjson到最新版2.0.23 2023-02-16 11:07:41 +08:00
RuoYi 6c3e88ee6d 首页页签右键选择时不显示关闭左侧 2023-02-04 22:45:01 +08:00
RuoYi da2e5a2d93 update copyright 2023 2023-02-04 22:44:29 +08:00
RuoYi 12c51fc8e3 若依 3.6.2 2023-01-16 11:42:23 +08:00
RuoYi 736b6348bc 移除commons-collections依赖 2023-01-13 16:26:18 +08:00
RuoYi 6317e902e3 升级element-ui到最新版本2.15.12 2023-01-13 11:45:09 +08:00
RuoYi 94590a008d 升级spring-boot-admin到最新版2.7.10 2023-01-13 11:44:39 +08:00
RuoYi 8b5acaf341 升级spring-cloud相关组件到最新版 2023-01-12 11:44:49 +08:00
RuoYi 8eb22e86e0 字符未使用下划线不进行驼峰式处理 2023-01-12 11:44:12 +08:00
RuoYi 853040cd42 修复gateway流控规则生效但不显示问题 2023-01-12 11:42:39 +08:00
RuoYi 17364e2699 v3最新版本不需要render-after-expand 2022-12-23 16:11:57 +08:00
RuoYi 9f48ff40d2 升级pagehelper到最新版1.4.6 2022-12-14 11:32:25 +08:00
RuoYi f93fc98b4f 修改参数键名时移除前缓存配置 2022-12-14 11:31:58 +08:00
RuoYi c03a671de8 修复代码生成图片/文件/单选时选择必填无法校验问题 2022-12-08 10:29:01 +08:00
RuoYi 6d6d5140fe 升级fastjson到最新版2.0.20 2022-12-08 10:27:36 +08:00
RuoYi f016006224 删除fuse无效选项maxPatternLength 2022-12-08 10:27:12 +08:00
RuoYi abcc045cad 修复Vue3树形下拉不能默认选中 2022-12-07 20:37:52 +08:00
RuoYi d76fab1d0c 升级druid到最新版本1.2.15 2022-12-07 12:46:39 +08:00
RuoYi a0d2b383ef 升级kaptcha到最新版2.3.3 2022-12-07 12:46:32 +08:00
RuoYi af33456ca8 升级echarts到最新版本5.4.0 2022-12-07 12:43:12 +08:00
RuoYi 3d2f9aa9c6 优化弹窗内容过多展示不全问题 2022-12-03 13:21:07 +08:00
RuoYi a8be0ccb35 修复Log注解GET请求记录不到参数问题 2022-12-03 13:20:48 +08:00
若依 f646bfc0f5
!286 此处修改曾导致 nacos修改xss开关时,spring容器未重启,filter仍起效。故增加参数判断,参数刷新后,xss开关正常关闭。
Merge pull request !286 from ylwang/N/A
2022-12-03 05:14:59 +00:00
若依 6efd427f79
!290 修复没有指定 spring-boot-maven-plugin 的版本号默认去拉取基于 JDK17 编译的 3.0 版本导致打包失败的问题
Merge pull request !290 from hjk2008/N/A
2022-12-03 05:14:11 +00:00
hjk2008 04a042c585
修复没有指定 spring-boot-maven-plugin 的版本号默认去拉取基于 JDK17 编译的 3.0 版本导致打包失败的问题
Signed-off-by: hjk2008 <hjk2008ext@163.com>
2022-11-25 09:32:35 +00:00
RuoYi ee3f03f1f1 修复某些特性的环境生成代码变乱码TXT文件问题 2022-11-22 09:25:59 +08:00
RuoYi b1a67a113e 消除Vue3控制台出现的警告信息 2022-11-21 19:46:47 +08:00
ylwang bc1c1dbfa7
此处修改曾导致 nacos修改xss开关时,spring容器未重启,filter仍起效。故增加参数判断,参数刷新后,xss开关正常关闭。
此处修改曾导致 nacos修改xss开关时,spring容器未重启,filter仍起效。故增加参数判断,参数刷新后,xss开关正常关闭。

Signed-off-by: ylwang <ylwang@makwing.com>
2022-11-21 08:58:44 +00:00
RuoYi 7a112c7317 兼容Excel下拉框内容过多无法显示的问题 2022-11-21 12:32:09 +08:00
RuoYi d2bd73b4dc 开启TopNav没有子菜单隐藏侧边栏 2022-11-17 14:26:43 +08:00
RuoYi a211d93092 修复回显数据字典数组异常问题(I60UYQ) 2022-11-15 14:31:23 +08:00
RuoYi a9938302f0 修复调度日志点击多次数据不变化的问题 2022-11-15 14:31:04 +08:00
RuoYi 6e5d7a6dab 升级druid到最新版本1.2.14 2022-11-14 11:34:59 +08:00
RuoYi 7a3892a77a 忽略不必要的属性数据返回 2022-11-12 11:47:20 +08:00
RuoYi e0a5e704b0 优化导出对象的子列表为空会出现[]问题 2022-11-11 11:36:02 +08:00
RuoYi d936ce76b1 修复sheet超出最大行数异常问题(I5YQ7Z) 2022-11-04 16:08:45 +08:00
RuoYi f2320d356d 添加新群号:118752664 2022-11-02 10:44:43 +08:00
若依 b50e79bbde
!278 根据调度编号获取详细信息参数名改正
Merge pull request !278 from Rain/N/A
2022-10-31 05:47:43 +00:00
Rain 295b5d5cfd
修复根据调度编号获取详细信息参数名错误
Signed-off-by: Rain <938448486@qq.com>
2022-10-31 02:10:10 +00:00
RuoYi 8f4ac612c8 新增返回警告消息提示 2022-10-30 13:04:31 +08:00
RuoYi b3f9e1f2de 升级fastjson到最新版2.0.16 2022-10-30 13:04:10 +08:00
RuoYi bcbc9d7adc 修复table中更多按钮切换主题色未生效修复问题 2022-10-28 21:01:57 +08:00
RuoYi 6421f68964 修复使用透明底png图片时,自动填充黑色背景 2022-10-28 20:40:41 +08:00
RuoYi 652f4372c0 重置时取消部门选中 2022-10-28 20:39:26 +08:00
RuoYi cff5fe93a5 去除某些svg图标的fill属性,避免菜单激活无法填充颜色 2022-10-28 20:38:56 +08:00
RuoYi c759728269 优化修改头像在小屏幕上页面布局错位的问题 2022-10-21 12:02:25 +08:00
RuoYi 58e07ba142 修复用户编辑时角色和部门存在无法修改情况 2022-10-21 12:01:42 +08:00
若依 43b336d26b
!266 升级fastjson到最新版2.0.15
Merge pull request !266 from Rain/N/A
2022-10-21 03:13:18 +00:00
若依 8eeb73eabb
!267 修改注释文案
Merge pull request !267 from runphp/N/A
2022-10-21 03:12:04 +00:00
runphp 98c3e4b48a
修改注释文案
Signed-off-by: runphp <runphp@qq.com>
2022-10-21 03:04:00 +00:00
Rain 839366f2b0
升级fastjson到最新版2.0.15
Signed-off-by: Rain <938448486@qq.com>
2022-10-21 01:53:32 +00:00
RuoYi 65cf05fddb 修复主题颜色在Drawer组件不会加载问题(I5VCF0) 2022-10-19 10:55:34 +08:00
RuoYi a9a8f94ae2 修复文件上传组件格式验证问题(I5V32H) 2022-10-12 19:34:45 +08:00
RuoYi 1617c74d4d 升级core-js到最新版本3.25.3 2022-10-10 09:32:39 +08:00
RuoYi 01c1505340 修复导出包含空子列表数据异常的问题 2022-10-10 09:31:10 +08:00
RuoYi c2708f2ba4 若依 3.6.1 2022-09-30 11:48:39 +08:00
若依 48a0d5bc9d
!258 fix: 改为静态方法, isError和isSuccess方法会被json序列化
Merge pull request !258 from runphp/N/A
2022-09-30 01:24:09 +00:00
runphp a057b7a4b9
fix: 改为静态方法, isError和isSuccess方法会被json序列化
isError和isSuccess会被json序列化
`{"error":false,"success":true}`

Signed-off-by: runphp <runphp@qq.com>
2022-09-29 10:16:11 +00:00
RuoYi 0e4a1c872c update ry_config.sql 2022-09-29 12:14:06 +08:00
RuoYi 5faa1af464 升级spring-cloud相关组件到最新版 2022-09-29 11:45:05 +08:00
RuoYi 0dfbb5fbf3 seata单独依赖模块 2022-09-29 11:29:41 +08:00
RuoYi 3b4f1d7937 优化代码生成同步后字典值NULL问题 2022-09-28 21:15:45 +08:00
RuoYi 07c2e08e4a 导入更新用户数据前校验数据权限 2022-09-28 21:15:34 +08:00
RuoYi e03cebac57 升级core-js到最新版本3.25.2 2022-09-22 13:24:24 +08:00
RuoYi 0c36921587 升级fastjson到最新版2.0.14 2022-09-22 13:23:25 +08:00
若依 53b84261f8
!253 AjaxResult中isError方法逻辑修改
Merge pull request !253 from taest/N/A
2022-09-22 01:59:28 +00:00
taest 11de8aa17b
AjaxResult中isError方法错误修改
Signed-off-by: taest <876239615@qq.com>
2022-09-22 01:21:17 +00:00
RuoYi f250c6ee93 优化日志操作中重置按钮时重复查询的问题 2022-09-19 14:47:28 +08:00
RuoYi fd89356ed7 通用下载方法新增config配置选项 2022-09-19 13:22:35 +08:00
RuoYi ad54d36385 修改用户登录账号重复验证 2022-09-18 11:26:44 +08:00
RuoYi 3cf088a0d8 升级element-ui到最新版本2.15.10 2022-09-15 08:39:59 +08:00
若依 22fac34b82
!248 【轻量级 PR】:优化注释
Merge pull request !248 from CHY/dev
2022-09-15 00:26:17 +00:00
CHY 7f0f842651 【轻量级 PR】:简化return 2022-09-13 15:29:46 +08:00
CHY 1124c27f06 【轻量级 PR】:优化注释 2022-09-13 15:18:25 +08:00
RuoYi adbba02cb8 定时任务支持执行父类方法 2022-09-09 10:27:42 +08:00
RuoYi 5b6dc85b62 日志注解限制operUrl属性的长度 2022-09-09 10:27:15 +08:00
RuoYi 62eec4df51 删除多余的style重复赋值 2022-09-09 10:26:55 +08:00
若依 11d8274462
!246 feat: add isError and isSuccess method
Merge pull request !246 from runphp/N/A
2022-09-09 02:10:24 +00:00
runphp 732071ef58
feat: add isError and isSuccess method
Signed-off-by: runphp <runphp@qq.com>
2022-09-07 08:52:23 +00:00
若依 afa23c2111
!240 update ruoyi-ui/src/components/FileUpload/index.vue.
Merge pull request !240 from exiace/N/A
2022-08-24 07:31:31 +00:00
exiace 4bf9f3cff5
update ruoyi-ui/src/components/FileUpload/index.vue.
文件上传组件提示信息错误

Signed-off-by: exiace <exiace@qq.com>
2022-08-24 06:18:18 +00:00
RuoYi 8c7986acdb 修复多文件上传报错出现的异常问题 2022-08-24 14:08:38 +08:00
RuoYi 52d50e4e47 优化页面内嵌iframe切换tab不刷新数据 2022-08-23 21:19:45 +08:00
RuoYi f0bfff1ff3 优化页面内嵌iframe切换tab不刷新数据 2022-08-23 17:38:00 +08:00
若依 a37315d513
!238 https://github.com/alibaba/nacos/issues/8960
Merge pull request !238 from 云飞扬/N/A
2022-08-23 01:20:32 +00:00
云飞扬 479755650c
https://github.com/alibaba/nacos/issues/8960
Signed-off-by: 云飞扬 <15678871232@qq.com>
2022-08-22 16:52:14 +00:00
RuoYi 73256dfeaf 升级fastjson到最新版2.0.12 2022-08-22 15:02:58 +08:00
RuoYi 767f7c8621 优化多角色数据权限匹配规则 2022-08-22 15:02:29 +08:00
RuoYi 12d335b9ac 添加菜单管理遗漏的prop属性 2022-08-22 14:45:51 +08:00
若依 bc7a743998
!237 fix: user_key 头信息未传递
Merge pull request !237 from runphp/N/A
2022-08-22 06:40:57 +00:00
若依 ca36f9fc6e
!236 代码小整理
Merge pull request !236 from taest/N/A
2022-08-22 06:39:30 +00:00
若依 8345eed709
!235 RedisService 删除Hash中的某条数据 方法返回值必为false问题修复
Merge pull request !235 from taest/N/A
2022-08-22 06:38:34 +00:00
若依 2af8e817bd
!233 密码变量命名风格统一
Merge pull request !233 from taest/N/A
2022-08-22 06:32:49 +00:00
runphp fcb58876e7
fix: user_key 头信息未传递
Signed-off-by: runphp <runphp@qq.com>
2022-08-22 03:13:56 +00:00
taest d4c61daf9b
代码小整理
Signed-off-by: taest <876239615@qq.com>
2022-08-19 08:32:42 +00:00
taest 31523867e7
RedisService 删除Hash中的某条数据 方法返回值必为false问题修复
Signed-off-by: taest <876239615@qq.com>
2022-08-19 08:26:05 +00:00
taest a8daa1f044
密码变量命名风格统一
Signed-off-by: taest <876239615@qq.com>
2022-08-19 08:17:45 +00:00
RuoYi 858f576fa3 修复图片预览组件src属性为null值控制台报错问题(I5KBAS) 2022-08-15 12:08:00 +08:00
RuoYi c960108b12 字典管理操作类型新增其他 2022-08-14 09:42:25 +08:00
RuoYi 59b867dcca 限制用户个人信息修改部门 2022-08-12 12:19:42 +08:00
若依 b9fdc4de87
!229 修复个人中心卡死或鼠标点击和键盘输入无效
Merge pull request !229 from Dincat/master
2022-08-12 04:05:10 +00:00
Dincat d504a7df2f 修复个人中心卡死或鼠标点击和键盘输入无效 2022-08-11 14:12:10 +08:00
RuoYi 2a675aa304 优化修改资料头像被覆盖的问题(I5LK04) 2022-08-11 13:21:45 +08:00
RuoYi d6df1fe7b3 操作日志记录支持排除敏感属性字段 2022-08-10 18:46:21 +08:00
RuoYi 428255ddcf 升级fastjson到最新版2.0.11 2022-08-10 18:46:08 +08:00
RuoYi a92ca233aa 优化导出对象的子列表判断条件 2022-08-10 18:45:55 +08:00
若依 537105b2a9
!228 修复账户解锁接口请求路径错误的问题
Merge pull request !228 from Rain/N/A
2022-08-08 23:39:15 +00:00
若依 d56ef651e3
!227 update ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java.
Merge pull request !227 from 颜奕强/N/A
2022-08-08 23:38:58 +00:00
Rain 9d21b1627b
修复账户解锁接口请求路径错误的问题 2022-08-08 15:00:41 +00:00
颜奕强 467557fef3
update ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java.
* update:  数字类型应该转为double输出。若使用string输出,会导致生成的单元格变成文本类型。
2022-08-08 12:29:03 +00:00
RuoYi c8a108b93a 登录日志新增解锁账户功能 2022-08-08 09:26:29 +08:00
RuoYi 5408af9d1f Excel支持导出对象的子列表方法 2022-08-07 18:49:09 +08:00
若依 e7b9e12d15
!225 新增删除Hash中的某条数据
Merge pull request !225 from runphp/N/A
2022-08-07 10:47:53 +00:00
若依 a4b714b95a
!224 处理XSS攻击问题
Merge pull request !224 from Pcat/hotfix-3.6.1.pcat#I5IRC8
2022-08-07 10:47:16 +00:00
runphp 4ae26c2f86
新增删除Hash中的某条数据 2022-08-04 01:39:58 +00:00
RuoYi b51c127eb7 数据逻辑删除不进行唯一验证 2022-08-03 16:53:11 +08:00
huyupeng c5eb7458c8 fix: 处理XSS攻击问题(#I5IRC8) 2022-08-01 14:52:18 +08:00
RuoYi 347a717d5c 升级spring-boot到最新版本2.7.2 2022-08-01 13:35:52 +08:00
RuoYi 0484c63d9b 升级spring-boot-admin到最新版2.7.3 2022-08-01 13:35:41 +08:00
RuoYi 4d21c11acd 修复密码输入错误次数变量 2022-08-01 13:35:19 +08:00
RuoYi 8fdb3c4d14 修复使用FastDFS上传头像失败提示文件名没有后缀问题 2022-07-30 22:53:44 +08:00
RuoYi 0ef63207f4 新增密码错误次数限制 2022-07-30 13:56:46 +08:00
RuoYi 1295177393 优化任务过期不执行调度 2022-07-30 13:49:36 +08:00
RuoYi 67a6841043 优化表格上右侧工具条(搜索按钮显隐&右侧样式凸出) 2022-07-29 20:43:36 +08:00
RuoYi d4930f6a88 自定义数据权限不排除重复 2022-07-26 20:06:14 +08:00
RuoYi c98f452431 防止vue3主键字段名与row或ids一致导致报错的问题 2022-07-26 20:05:56 +08:00
RuoYi fb35360f81 支持自定义隐藏Excel属性列 2022-07-21 13:52:33 +08:00
RuoYi 5e20f99a99 优化布局设置使用el-drawer抽屉显示 2022-07-21 08:51:47 +08:00
RuoYi 9f90b4eba7 优化字典数据使用store存取 2022-07-20 19:39:15 +08:00
RuoYi ce82095f04 防止date-picker组件报错,降级element-ui版本 2022-07-20 19:14:47 +08:00
RuoYi 9ebd484f46 Excel注解支持backgroundColor属性设置背景色 2022-07-20 09:40:42 +08:00
RuoYi cc0e184314 优化多个相同角色数据导致权限SQL重复问题 2022-07-19 16:08:11 +08:00
RuoYi 87009e72bf 若依 3.6.0 2022-07-16 10:34:02 +08:00
RuoYi d6a2028ec3 升级transmittable-thread-local到最新版本2.13.2 2022-07-15 15:19:22 +08:00
RuoYi ef28473992 升级Spring Cloud相关组件到最新版 2022-07-15 14:32:58 +08:00
RuoYi 1543fb801b 升级element-ui到最新版本2.15.9 2022-07-15 10:03:48 +08:00
RuoYi e753cea03e 修改验证码开关变量名 2022-07-15 10:02:59 +08:00
RuoYi 78332c2786 升级fastjson到最新版2.0.9 2022-07-12 18:20:46 +08:00
RuoYi 4b1351ef21 修改验证码开关变量名 2022-07-12 18:19:35 +08:00
RuoYi f12baad00c 优化代码 2022-07-12 18:19:10 +08:00
RuoYi 81d3c90bbc 添加新群号:148794840 2022-07-09 16:47:52 +08:00
疯狂的狮子Li 0d58ecb09c
删除重复注释 2022-07-03 04:22:19 +00:00
RuoYi 1e16852a3c 升级spring-boot到最新版本2.6.8 2022-06-26 13:47:58 +08:00
RuoYi 57e63a184d 升级fastjson到最新版2.0.8 2022-06-26 13:15:38 +08:00
RuoYi 20476e9dd1 默认不启用压缩文件缓存防止node_modules过大 2022-06-26 13:15:28 +08:00
RuoYi 95aa343805 优化字典数据回显样式下拉框显示值 2022-06-26 13:15:17 +08:00
RuoYi a573c4b10d 字典类型删除多余的mapper注解 2022-06-26 13:13:20 +08:00
疯狂的狮子Li 5964dc81ab
remove 删除无用 admin-client 依赖声明 避免造成误解 2022-06-24 04:54:54 +00:00
RuoYi 721701274b 升级seata到最新版1.5.1 2022-06-17 21:41:23 +08:00
RuoYi 78c356a9f3 升级fastjson到最新版2.0.7 2022-06-17 20:52:41 +08:00
若依 b622675522
使用Lazy,AutoConfigureBefore注解解决循环引用及Bean重复问题
Merge pull request !205 from 淡然逝去/N/A
2022-06-17 12:51:22 +00:00
若依 912f607062
!203 WebSecurityConfigurerAdapter 在Spring Security 5.7过时
Merge pull request !203 from 板砖/master
2022-06-17 12:37:36 +00:00
淡然逝去 1297d094cb
使用 @Lazy,@AutoConfigureBefore注解解决循环引用及Bean重复问题,删除allow-bean-definition-overriding: true, allow-circular-references: true配置信息 2022-06-16 04:56:12 +00:00
RuoYi ccfc4f7ad7 升级druid到最新版本1.2.11 2022-06-14 21:35:47 +08:00
RuoYi 8ee702e4a2 reset babel 2022-06-14 21:26:24 +08:00
wuzh 5945537ade WebSecurityConfigurerAdapter 过时更新 2022-06-13 21:34:59 +08:00
RuoYi 2051819d2d 删除多余的工具类 2022-06-13 21:07:11 +08:00
RuoYi 570d468814 optimized code 2022-06-13 20:57:03 +08:00
若依 5fd16ff806
!202 update ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java.
Merge pull request !202 from 光速蜗牛/N/A
2022-06-13 12:49:34 +00:00
若依 17246d8a27
!199 简化逻辑判断
Merge pull request !199 from 光速蜗牛/master
2022-06-13 12:48:42 +00:00
若依 6d404a1f3b
!198 去除多余的逗号
Merge pull request !198 from runphp/N/A
2022-06-13 12:48:18 +00:00
若依 7417c1d473
!197 update 优化新增用户与角色信息、用户与岗位信息逻辑
Merge pull request !197 from 疯狂的狮子Li/N/A
2022-06-13 12:48:11 +00:00
若依 9b35679ba6
!196 修正OpenFeign部分情况下传递header中Authorization参数值为空导致获取用户信息失败问题
Merge pull request !196 from JellyBins/N/A
2022-06-13 12:45:30 +00:00
若依 7af84cb923
!195 修复【增加对空字符串参数的过滤】提交的参数判断问题
Merge pull request !195 from 清溪先生/master
2022-06-13 12:42:23 +00:00
若依 8242cec9ac
!194 update 使用 gateway 自带工具 优化缓存Request与body
Merge pull request !194 from 疯狂的狮子Li/N/A
2022-06-13 12:41:24 +00:00
光速蜗牛 5b8cf9701f
update ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java.
update 优化 XssFilter 使用枚举替换字符串
2022-06-13 10:12:38 +00:00
cgl a52d455032 简化逻辑判断 2022-06-13 17:05:23 +08:00
runphp d28f81dc68
去除多余的逗号 2022-06-11 01:13:30 +00:00
疯狂的狮子Li 7475cff47d
update 优化新增用户与角色信息、用户与岗位信息逻辑 2022-06-08 13:55:25 +00:00
我以为 d6e6b99316
修正OpenFeign部分情况下传递header认证信息为空问题 #https://gitee.com/y_project/RuoYi-Cloud/issues/I5AGRR 2022-06-02 03:00:16 +00:00
清溪先生 5a48c5dba7 修复【增加对空字符串参数的过滤】提交的参数判断问题;
Signed-off-by: 清溪先生 <usfree2021@163.com>
2022-06-02 08:53:31 +08:00
疯狂的狮子Li ad7133f39d
update 使用 gateway 自带工具 优化缓存Request与body 2022-05-31 05:03:34 +00:00
疯狂的狮子Li fca189fa73
update 优化 CacheRequestFilter 使用枚举替换字符串 2022-05-31 02:55:17 +00:00
RuoYi 6cda8cb28f 表单构建按钮不显示正则校验 2022-05-29 09:49:54 +08:00
RuoYi 9c29907d57 增加对空字符串参数的过滤 2022-05-29 09:49:43 +08:00
RuoYi b3d462e873 用户列表查询不显示密码字段 2022-05-29 09:49:29 +08:00
RuoYi cdcc466300 升级fastjson到最新版2.0.4 2022-05-26 10:04:13 +08:00
RuoYi 12ca164c44 升级fastjson到最新版1.2.83 2022-05-24 10:14:31 +08:00
RuoYi 1d1b9501b7 用户头像上传限制只能为图片格式 2022-05-22 19:16:52 +08:00
RuoYi 24376681b8 优化switch case条件 2022-05-22 19:14:27 +08:00
RuoYi 386f3eb016 修复操作日志查询类型条件为0时会查到所有数据 2022-05-22 19:14:12 +08:00
疯狂的狮子Li 2a6a74ead5
fix 修复编辑报错 去除 NOT NULL 判断 兼容 nacos 低版本 2022-05-16 02:22:17 +00:00
若依 01e4e619e6
!188 【轻量级 PR】代码异味。项目review时发现多了逗号。
Merge pull request !188 from Tigger_hyk/master
2022-05-13 08:21:36 +00:00
若依 f6f07f255a
!187 【轻量级 PR】:体验优化。用户管理左侧树型组件增加选中高亮保持。
Merge pull request !187 from Tigger_hyk/dev
2022-05-13 07:00:33 +00:00
huyikai 2eaa52c7aa Unexpected use of comma operator 2022-05-13 14:54:40 +08:00
huyikai 86b9e675b5 体验优化-用户管理左侧树型组件增加选中高亮保持。 2022-05-12 10:55:34 +08:00
RuoYi b76cd4d0e2 update ry_config.sql 2022-05-10 17:23:33 +08:00
RuoYi a4ad2b8b3c 升级spring-boot-admin到最新版2.6.7 2022-05-10 10:17:36 +08:00
RuoYi 103bf66f77 修复字典数据显示不全问题 2022-05-10 10:17:17 +08:00
RuoYi 5dbed46552 优化excel创建表格样式 2022-05-09 17:48:20 +08:00
若依 97500fbccb
!182 简化返回值
Merge pull request !182 from shawn/dev
2022-05-09 09:44:49 +00:00
RuoYi 70f306418f 修改代码生成树形选择器组件 2022-04-25 10:30:02 +08:00
RuoYi 6bc77169fe 修改显示顺序orderNum类型为整型 2022-04-25 10:29:46 +08:00
RuoYi 742f3106a2 修复长主键溢出问题 将查询返回类型改为 Long 2022-04-24 19:10:41 +08:00
RuoYi 9ec4d19384 update ry_config.sql 2022-04-24 19:10:13 +08:00
RuoYi 68040827e2 最新alibaba/seata版本无需处理循环引用问题 2022-04-24 19:09:44 +08:00
若依 75d91c7d1d
!185 spring-cloud.version 2021.0.1 官方推荐对应 spring-cloud-alibaba 2021.0.1.0
Merge pull request !185 from abbfun/N/A
2022-04-24 10:18:47 +00:00
若依 95c1286f06
!184 spring-boot 最新版本 2.6.7
Merge pull request !184 from abbfun/N/A
2022-04-24 10:18:40 +00:00
abbfun f63a76f661
spring-cloud.version 2021.0.1 官方推荐对应 spring-cloud-alibaba 2021.0.1.0
spring-cloud.version 2021.0.1 对应 spring-cloud-alibaba 2021.0.1.0,
官方说明
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E#%E6%AF%95%E4%B8%9A%E7%89%88%E6%9C%AC%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8
2022-04-23 14:36:48 +00:00
abbfun 6644d3077d
spring-boot 最新版本 2.6.7 2022-04-23 13:44:57 +00:00
RuoYi 54d1c58338 Excel注解支持color字体颜色 2022-04-23 21:07:52 +08:00
shawn 9da3b34b9c 简化返回值逻辑判断 2022-04-20 21:37:59 +08:00
RuoYi 1ec806ae80 设置分页参数默认值 2022-04-17 10:35:15 +08:00
RuoYi 4df2b72b30 检查定时任务bean所在包名是否为白名单配置 2022-04-17 10:35:00 +08:00
RuoYi a0ce434163 升级element-ui到最新版本2.15.8 2022-04-15 09:39:15 +08:00
RuoYi 5053510236 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线) 2022-04-15 09:38:39 +08:00
356 changed files with 9352 additions and 7259 deletions

View File

@ -1,11 +1,11 @@
<p align="center"> <p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
</p> </p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.5.0</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.6</h1>
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
<p align="center"> <p align="center">
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.5.0-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.6-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p> </p>
@ -17,12 +17,9 @@
* 后端采用Spring Boot、Spring Cloud & Alibaba。 * 后端采用Spring Boot、Spring Cloud & Alibaba。
* 注册中心、配置中心选型Nacos权限认证使用Redis。 * 注册中心、配置中心选型Nacos权限认证使用Redis。
* 流量控制框架选型Sentinel分布式事务选型Seata。 * 流量控制框架选型Sentinel分布式事务选型Seata。
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。 * 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。
* 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) * 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp; * 阿里云优惠券:[点我进入](http://aly.ruoyi.vip),腾讯云优惠券:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
## 系统模块 ## 系统模块
@ -39,7 +36,9 @@ com.ruoyi
│ └── ruoyi-common-datasource // 多数据源 │ └── ruoyi-common-datasource // 多数据源
│ └── ruoyi-common-log // 日志记录 │ └── ruoyi-common-log // 日志记录
│ └── ruoyi-common-redis // 缓存服务 │ └── ruoyi-common-redis // 缓存服务
│ └── ruoyi-common-seata // 分布式事务
│ └── ruoyi-common-security // 安全模块 │ └── ruoyi-common-security // 安全模块
│ └── ruoyi-common-sensitive // 数据脱敏
│ └── ruoyi-common-swagger // 系统接口 │ └── ruoyi-common-swagger // 系统接口
├── ruoyi-modules // 业务模块 ├── ruoyi-modules // 业务模块
│ └── ruoyi-system // 系统模块 [9201] │ └── ruoyi-system // 系统模块 [9201]
@ -127,4 +126,4 @@ com.ruoyi
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。

View File

@ -9,8 +9,8 @@ usage() {
# copy sql # copy sql
echo "begin copy sql " echo "begin copy sql "
cp ../sql/ry_20210908.sql ./mysql/db cp ../sql/ry_20250523.sql ./mysql/db
cp ../sql/ry_config_20220114.sql ./mysql/db cp ../sql/ry_config_20250224.sql ./mysql/db
# copy html # copy html
echo "begin copy html " echo "begin copy html "

View File

@ -16,7 +16,7 @@ management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir= server.tomcat.basedir=/home/ruoyi/nacos/tomcat/logs
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/** nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**

View File

@ -28,9 +28,14 @@ http {
proxy_pass http://ruoyi-gateway:8080/; proxy_pass http://ruoyi-gateway:8080/;
} }
# 避免actuator暴露
if ($uri ~ "/actuator") {
return 403;
}
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;
location = /50x.html { location = /50x.html {
root html; root html;
} }
} }
}# requirepass 123456 }

181
pom.xml
View File

@ -6,45 +6,53 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>3.5.0</ruoyi.version> <ruoyi.version>3.6.6</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring-boot.version>2.6.6</spring-boot.version> <spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.0.1</spring-cloud.version> <spring-cloud.version>2021.0.9</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version>
<alibaba.nacos.version>2.0.4</alibaba.nacos.version> <spring-boot-admin.version>2.7.16</spring-boot-admin.version>
<spring-boot-admin.version>2.6.6</spring-boot-admin.version>
<spring-boot.mybatis>2.2.2</spring-boot.mybatis>
<swagger.fox.version>3.0.0</swagger.fox.version>
<swagger.core.version>1.6.2</swagger.core.version>
<tobato.version>1.27.2</tobato.version> <tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>1.4.1</pagehelper.boot.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<druid.version>1.2.8</druid.version> <druid.version>1.2.23</druid.version>
<dynamic-ds.version>3.5.0</dynamic-ds.version> <dynamic-ds.version>4.3.1</dynamic-ds.version>
<commons.io.version>2.11.0</commons.io.version> <commons.io.version>2.19.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>1.2.80</fastjson.version> <fastjson.version>2.0.57</fastjson.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version> <minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<commons-collections.version>3.2.2</commons-collections.version> <springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version -->
<tomcat.version>9.0.112</tomcat.version>
<logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- 覆盖SpringFramework的依赖配置-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring-framework.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 微服务 --> <!-- SpringCloud 微服务 -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
@ -63,13 +71,6 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- Alibaba Nacos 配置 -->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${alibaba.nacos.version}</version>
</dependency>
<!-- SpringBoot 依赖配置 --> <!-- SpringBoot 依赖配置 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -79,11 +80,36 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- SpringBoot 监控客户端 --> <!-- 覆盖logback的依赖配置-->
<dependency> <dependency>
<groupId>de.codecentric</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId> <artifactId>logback-core</artifactId>
<version>${spring-boot-admin.version}</version> <version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- 覆盖tomcat的依赖配置-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency> </dependency>
<!-- FastDFS 分布式文件系统 --> <!-- FastDFS 分布式文件系统 -->
@ -93,28 +119,16 @@
<version>${tobato.version}</version> <version>${tobato.version}</version>
</dependency> </dependency>
<!-- Mybatis 依赖配置 --> <!-- Springdoc webmvc 依赖配置 -->
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>org.springdoc</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId> <artifactId>springdoc-openapi-ui</artifactId>
<version>${spring-boot.mybatis}</version> <version>${springdoc.version}</version>
</dependency>
<!-- Swagger 依赖配置 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger.core.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.core.version}</version>
</dependency> </dependency>
<!-- 验证码 --> <!-- 验证码 -->
<dependency> <dependency>
<groupId>com.github.penggle</groupId> <groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId> <artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version> <version>${kaptcha.version}</version>
</dependency> </dependency>
@ -140,13 +154,6 @@
<version>${poi.version}</version> <version>${poi.version}</version>
</dependency> </dependency>
<!-- 文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<!-- 代码生成使用模板 --> <!-- 代码生成使用模板 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>
@ -154,17 +161,10 @@
<version>${velocity.version}</version> <version>${velocity.version}</version>
</dependency> </dependency>
<!-- Collection 增强Java集合框架 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections.version}</version>
</dependency>
<!-- JSON 解析器和生成器 --> <!-- JSON 解析器和生成器 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version> <version>${fastjson.version}</version>
</dependency> </dependency>
@ -203,6 +203,13 @@
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 数据脱敏 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-sensitive</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 权限范围 --> <!-- 权限范围 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@ -217,6 +224,13 @@
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 分布式事务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-seata</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 日志记录 --> <!-- 日志记录 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@ -271,6 +285,47 @@
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build> </build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project> </project>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,9 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
@ -26,4 +28,13 @@ public interface RemoteFileService
*/ */
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file); public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
/**
*
*
* @param fileUrl
* @return
*/
@DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<Boolean> delete(@RequestParam("fileUrl") String fileUrl);
} }

View File

@ -27,7 +27,7 @@ public interface RemoteLogService
* @return * @return
*/ */
@PostMapping("/operlog") @PostMapping("/operlog")
public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) throws Exception;
/** /**
* 访 * 访

View File

@ -4,6 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
@ -40,4 +41,14 @@ public interface RemoteUserService
*/ */
@PostMapping("/user/register") @PostMapping("/user/register")
public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* IP
*
* @param sysUser
* @param source
* @return
*/
@PutMapping("/user/recordlogin")
public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
} }

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.constraints.Email; import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -31,7 +32,7 @@ public class SysDept extends BaseEntity
private String deptName; private String deptName;
/** 显示顺序 */ /** 显示顺序 */
private String orderNum; private Integer orderNum;
/** 负责人 */ /** 负责人 */
private String leader; private String leader;
@ -96,13 +97,13 @@ public class SysDept extends BaseEntity
this.deptName = deptName; this.deptName = deptName;
} }
@NotBlank(message = "显示顺序不能为空") @NotNull(message = "显示顺序不能为空")
public String getOrderNum() public Integer getOrderNum()
{ {
return orderNum; return orderNum;
} }
public void setOrderNum(String orderNum) public void setOrderNum(Integer orderNum)
{ {
this.orderNum = orderNum; this.orderNum = orderNum;
} }

View File

@ -131,7 +131,7 @@ public class SysDictData extends BaseEntity
public boolean getDefault() public boolean getDefault()
{ {
return UserConstants.YES.equals(this.isDefault) ? true : false; return UserConstants.YES.equals(this.isDefault);
} }
public String getIsDefault() public String getIsDefault()

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.api.domain; package com.ruoyi.system.api.domain;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -57,6 +58,7 @@ public class SysDictType extends BaseEntity
@NotBlank(message = "字典类型不能为空") @NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
public String getDictType() public String getDictType()
{ {
return dictType; return dictType;

View File

@ -79,6 +79,10 @@ public class SysOperLog extends BaseEntity
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date operTime; private Date operTime;
/** 消耗时间 */
@Excel(name = "消耗时间", suffix = "毫秒")
private Long costTime;
public Long getOperId() public Long getOperId()
{ {
return operId; return operId;
@ -238,4 +242,14 @@ public class SysOperLog extends BaseEntity
{ {
this.operTime = operTime; this.operTime = operTime;
} }
public Long getCostTime()
{
return costTime;
}
public void setCostTime(Long costTime)
{
this.costTime = costTime;
}
} }

View File

@ -1,6 +1,8 @@
package com.ruoyi.system.api.domain; package com.ruoyi.system.api.domain;
import java.util.Set;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -31,7 +33,7 @@ public class SysRole extends BaseEntity
/** 角色排序 */ /** 角色排序 */
@Excel(name = "角色排序") @Excel(name = "角色排序")
private String roleSort; private Integer roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */ /** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "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 Long[] deptIds;
/** 角色菜单权限 */
private Set<String> permissions;
public SysRole() public SysRole()
{ {
@ -113,13 +118,13 @@ public class SysRole extends BaseEntity
this.roleKey = roleKey; this.roleKey = roleKey;
} }
@NotBlank(message = "显示顺序不能为空") @NotNull(message = "显示顺序不能为空")
public String getRoleSort() public Integer getRoleSort()
{ {
return roleSort; return roleSort;
} }
public void setRoleSort(String roleSort) public void setRoleSort(Integer roleSort)
{ {
this.roleSort = roleSort; this.roleSort = roleSort;
} }
@ -204,6 +209,16 @@ public class SysRole extends BaseEntity
this.deptIds = deptIds; this.deptIds = deptIds;
} }
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.core.xss.Xss; import com.ruoyi.common.core.xss.Xss;
@ -23,7 +24,7 @@ public class SysUser extends BaseEntity
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 用户ID */ /** 用户ID */
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId; private Long userId;
/** 部门ID */ /** 部门ID */
@ -43,7 +44,7 @@ public class SysUser extends BaseEntity
private String email; private String email;
/** 手机号码 */ /** 手机号码 */
@Excel(name = "手机号码") @Excel(name = "手机号码", cellType = ColumnType.TEXT)
private String phonenumber; private String phonenumber;
/** 用户性别 */ /** 用户性别 */
@ -56,8 +57,8 @@ public class SysUser extends BaseEntity
/** 密码 */ /** 密码 */
private String password; private String password;
/** 号状态0正常 1停用 */ /** 号状态0正常 1停用 */
@Excel(name = "号状态", readConverterExp = "0=正常,1=停用") @Excel(name = "号状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
@ -71,6 +72,9 @@ public class SysUser extends BaseEntity
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 密码最后更新时间 */
private Date pwdUpdateDate;
/** 部门对象 */ /** 部门对象 */
@Excels({ @Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@ -117,7 +121,7 @@ public class SysUser extends BaseEntity
public static boolean isAdmin(Long userId) public static boolean isAdmin(Long userId)
{ {
return userId != null && 1L == userId; return UserConstants.isAdmin(userId);
} }
public Long getDeptId() public Long getDeptId()
@ -198,7 +202,7 @@ public class SysUser extends BaseEntity
this.avatar = avatar; this.avatar = avatar;
} }
@JsonProperty @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public String getPassword() public String getPassword()
{ {
return password; return password;
@ -249,6 +253,16 @@ public class SysUser extends BaseEntity
this.loginDate = loginDate; this.loginDate = loginDate;
} }
public Date getPwdUpdateDate()
{
return pwdUpdateDate;
}
public void setPwdUpdateDate(Date pwdUpdateDate)
{
this.pwdUpdateDate = pwdUpdateDate;
}
public SysDept getDept() public SysDept getDept()
{ {
return dept; return dept;
@ -298,6 +312,7 @@ public class SysUser extends BaseEntity
{ {
this.roleId = roleId; this.roleId = roleId;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -314,6 +329,7 @@ public class SysUser extends BaseEntity
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("loginIp", getLoginIp()) .append("loginIp", getLoginIp())
.append("loginDate", getLoginDate()) .append("loginDate", getLoginDate())
.append("pwdUpdateDate", getPwdUpdateDate())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@ -30,6 +30,12 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
{ {
return R.fail("上传文件失败:" + throwable.getMessage()); return R.fail("上传文件失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> delete(String fileUrl)
{
return R.fail("删除文件失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@ -28,13 +28,13 @@ public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogServic
@Override @Override
public R<Boolean> saveLog(SysOperLog sysOperLog, String source) public R<Boolean> saveLog(SysOperLog sysOperLog, String source)
{ {
return null; return R.fail("保存操作日志失败:" + throwable.getMessage());
} }
@Override @Override
public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source) public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source)
{ {
return null; return R.fail("保存登录日志失败:" + throwable.getMessage());
} }
}; };

View File

@ -36,6 +36,12 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
{ {
return R.fail("注册用户失败:" + throwable.getMessage()); return R.fail("注册用户失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> recordUserLogin(SysUser sysUser, String source)
{
return R.fail("记录用户登录信息失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@ -1,4 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.system.api.factory.RemoteUserFallbackFactory,\
com.ruoyi.system.api.factory.RemoteLogFallbackFactory, \
com.ruoyi.system.api.factory.RemoteFileFallbackFactory

View File

@ -0,0 +1,3 @@
com.ruoyi.system.api.factory.RemoteUserFallbackFactory
com.ruoyi.system.api.factory.RemoteLogFallbackFactory
com.ruoyi.system.api.factory.RemoteFileFallbackFactory

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -2,19 +2,20 @@ package com.ruoyi.auth.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.UserStatus; import com.ruoyi.common.core.enums.UserStatus;
import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils; import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.api.model.LoginUser;
@ -27,10 +28,16 @@ import com.ruoyi.system.api.model.LoginUser;
public class SysLoginService public class SysLoginService
{ {
@Autowired @Autowired
private RemoteLogService remoteLogService; private RemoteUserService remoteUserService;
@Autowired @Autowired
private RemoteUserService remoteUserService; private SysPasswordService passwordService;
@Autowired
private SysRecordLogService recordLogService;
@Autowired
private RedisService redisService;
/** /**
* *
@ -40,23 +47,30 @@ public class SysLoginService
// 用户名或密码为空 错误 // 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) if (StringUtils.isAnyBlank(username, password))
{ {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
throw new ServiceException("用户/密码必须填写"); throw new ServiceException("用户/密码必须填写");
} }
// 密码如果不在指定范围内 错误 // 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{ {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
throw new ServiceException("用户密码不在指定范围"); throw new ServiceException("用户密码不在指定范围");
} }
// 用户名不在指定范围内 错误 // 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) || username.length() > UserConstants.USERNAME_MAX_LENGTH)
{ {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
throw new ServiceException("用户名不在指定范围"); throw new ServiceException("用户名不在指定范围");
} }
// IP黑名单校验
String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾访问IP已被列入系统黑名单");
throw new ServiceException("很遗憾访问IP已被列入系统黑名单");
}
// 查询用户信息 // 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
@ -65,35 +79,43 @@ public class SysLoginService
throw new ServiceException(userResult.getMsg()); throw new ServiceException(userResult.getMsg());
} }
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
LoginUser userInfo = userResult.getData(); LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser(); SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{ {
recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
} }
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{ {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用"); throw new ServiceException("对不起,您的账号:" + username + " 已停用");
} }
if (!SecurityUtils.matchesPassword(password, user.getPassword())) passwordService.validate(user, password);
{ recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误"); recordLoginInfo(user.getUserId());
throw new ServiceException("用户不存在/密码错误");
}
recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
return userInfo; return userInfo;
} }
/**
*
*
* @param userId ID
*/
public void recordLoginInfo(Long userId)
{
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
// 更新用户登录IP
sysUser.setLoginIp(IpUtils.getIpAddr());
// 更新用户登录时间
sysUser.setLoginDate(DateUtils.getNowDate());
remoteUserService.recordUserLogin(sysUser, SecurityConstants.INNER);
}
public void logout(String loginName) public void logout(String loginName)
{ {
recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
} }
/** /**
@ -121,6 +143,7 @@ public class SysLoginService
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserName(username); sysUser.setUserName(username);
sysUser.setNickName(username); sysUser.setNickName(username);
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
@ -128,32 +151,6 @@ public class SysLoginService
{ {
throw new ServiceException(registerResult.getMsg()); throw new ServiceException(registerResult.getMsg());
} }
recordLogininfor(username, Constants.REGISTER, "注册成功"); recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");
}
/**
*
*
* @param username
* @param status
* @param message
* @return
*/
public void recordLogininfor(String username, String status, String message)
{
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
} }
} }

View File

@ -0,0 +1,85 @@
package com.ruoyi.auth.service;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysUser;
/**
*
*
* @author ruoyi
*/
@Component
public class SysPasswordService
{
@Autowired
private RedisService redisService;
private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT;
private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME;
@Autowired
private SysRecordLogService recordLogService;
/**
*
*
* @param username
* @return key
*/
private String getCacheKey(String username)
{
return CacheConstants.PWD_ERR_CNT_KEY + username;
}
public void validate(SysUser user, String password)
{
String username = user.getUserName();
Integer retryCount = redisService.getCacheObject(getCacheKey(username));
if (retryCount == null)
{
retryCount = 0;
}
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
{
String errMsg = String.format("密码输入错误%s次帐户锁定%s分钟", maxRetryCount, lockTime);
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL,errMsg);
throw new ServiceException(errMsg);
}
if (!matches(user, password))
{
retryCount = retryCount + 1;
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", retryCount));
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
throw new ServiceException("用户不存在/密码错误");
}
else
{
clearLoginRecordCache(username);
}
}
public boolean matches(SysUser user, String rawPassword)
{
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
}
public void clearLoginRecordCache(String loginName)
{
if (redisService.hasKey(getCacheKey(loginName)))
{
redisService.deleteObject(getCacheKey(loginName));
}
}
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.auth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.domain.SysLogininfor;
/**
*
*
* @author ruoyi
*/
@Component
public class SysRecordLogService
{
@Autowired
private RemoteLogService remoteLogService;
/**
*
*
* @param username
* @param status
* @param message
* @return
*/
public void recordLogininfor(String username, String status, String message)
{
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr());
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
}
}

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -12,8 +12,10 @@
<module>ruoyi-common-log</module> <module>ruoyi-common-log</module>
<module>ruoyi-common-core</module> <module>ruoyi-common-core</module>
<module>ruoyi-common-redis</module> <module>ruoyi-common-redis</module>
<module>ruoyi-common-seata</module>
<module>ruoyi-common-swagger</module> <module>ruoyi-common-swagger</module>
<module>ruoyi-common-security</module> <module>ruoyi-common-security</module>
<module>ruoyi-common-sensitive</module>
<module>ruoyi-common-datascope</module> <module>ruoyi-common-datascope</module>
<module>ruoyi-common-datasource</module> <module>ruoyi-common-datasource</module>
</modules> </modules>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -67,8 +67,8 @@
<!-- Alibaba Fastjson --> <!-- Alibaba Fastjson -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson2</artifactId>
</dependency> </dependency>
<!-- Jwt --> <!-- Jwt -->
@ -95,12 +95,6 @@
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</dependency> </dependency>
<!-- Commons Fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- excel工具 --> <!-- excel工具 -->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
@ -113,12 +107,6 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -5,6 +5,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.ruoyi.common.core.utils.poi.ExcelHandlerAdapter; import com.ruoyi.common.core.utils.poi.ExcelHandlerAdapter;
/** /**
@ -52,17 +54,12 @@ public @interface Excel
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/** /**
* 0 1 * excel
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* excel
*/ */
public double height() default 14; public double height() default 14;
/** /**
* excel * excel
*/ */
public double width() default 16; public double width() default 16;
@ -81,11 +78,21 @@ public @interface Excel
*/ */
public String prompt() default ""; public String prompt() default "";
/**
*
*/
public boolean wrapText() default false;
/** /**
* . * .
*/ */
public String[] combo() default {}; public String[] combo() default {};
/**
* ,:list)
*/
public boolean needMerge() default false;
/** /**
* ,:,. * ,:,.
*/ */
@ -102,9 +109,34 @@ public @interface Excel
public boolean isStatistics() default false; public boolean isStatistics() default false;
/** /**
* 0123 * 0 1
*/ */
public Align align() default Align.AUTO; 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;
/**
*
*/
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/** /**
* *
@ -116,22 +148,6 @@ public @interface Excel
*/ */
public String[] args() default {}; 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;
}
}
/** /**
* 012 * 012
*/ */
@ -155,7 +171,7 @@ public @interface Excel
public enum ColumnType public enum ColumnType
{ {
NUMERIC(0), STRING(1), IMAGE(2); NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
private final int value; private final int value;
ColumnType(int value) ColumnType(int value)

View File

@ -1,7 +1,7 @@
package com.ruoyi.common.core.constant; package com.ruoyi.common.core.constant;
/** /**
* key *
* *
* @author ruoyi * @author ruoyi
*/ */
@ -17,8 +17,43 @@ public class CacheConstants
*/ */
public final static long REFRESH_TIME = 120; public final static long REFRESH_TIME = 120;
/**
*
*/
public final static int PASSWORD_MAX_RETRY_COUNT = 5;
/**
* 10
*/
public final static long PASSWORD_LOCK_TIME = 10;
/** /**
* *
*/ */
public final static String LOGIN_TOKEN_KEY = "login_tokens:"; public final static String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* redis key
*/
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
/**
* IP cache key
*/
public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList";
} }

View File

@ -17,6 +17,11 @@ public class Constants
*/ */
public static final String GBK = "GBK"; public static final String GBK = "GBK";
/**
* www
*/
public static final String WWW = "www.";
/** /**
* RMI * RMI
*/ */
@ -82,6 +87,16 @@ public class Constants
*/ */
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/**
*
*/
public static final String ALL_PERMISSION = "*:*:*";
/**
*
*/
public static final String SUPER_ADMIN = "admin";
/** /**
* *
*/ */
@ -102,36 +117,25 @@ public class Constants
*/ */
public static final String IS_ASC = "isAsc"; public static final String IS_ASC = "isAsc";
/**
* redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/** /**
* *
*/ */
public static final long CAPTCHA_EXPIRATION = 2; public static final long CAPTCHA_EXPIRATION = 2;
/**
* cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/** /**
* *
*/ */
public static final String RESOURCE_PREFIX = "/profile"; public static final String RESOURCE_PREFIX = "/profile";
/**
* json
*/
public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
/** /**
* 访 * 访
*/ */
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.job.task" };
/** /**
* *

View File

@ -42,7 +42,7 @@ public class GenConstants
/** 数据库数字类型 */ /** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bigint", "float", "double", "decimal" }; "bit", "bigint", "float", "double", "decimal" };
/** 页面不需要编辑字段 */ /** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };

View File

@ -86,4 +86,9 @@ public class HttpStatus
* *
*/ */
public static final int NOT_IMPLEMENTED = 501; public static final int NOT_IMPLEMENTED = 501;
/**
*
*/
public static final int WARN = 601;
} }

View File

@ -20,7 +20,7 @@ public class SecurityConstants
/** /**
* *
*/ */
public static final String AUTHORIZATION_HEADER = "authorization"; public static final String AUTHORIZATION_HEADER = "Authorization";
/** /**
* *
@ -41,4 +41,9 @@ public class SecurityConstants
* *
*/ */
public static final String LOGIN_USER = "login_user"; public static final String LOGIN_USER = "login_user";
/**
*
*/
public static final String ROLE_PERMISSION = "role_permission";
} }

View File

@ -7,11 +7,6 @@ package com.ruoyi.common.core.constant;
*/ */
public class TokenConstants public class TokenConstants
{ {
/**
*
*/
public static final String AUTHENTICATION = "Authorization";
/** /**
* *
*/ */

View File

@ -21,6 +21,9 @@ public class UserConstants
/** 用户封禁状态 */ /** 用户封禁状态 */
public static final String USER_DISABLE = "1"; public static final String USER_DISABLE = "1";
/** 角色正常状态 */
public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */ /** 角色封禁状态 */
public static final String ROLE_DISABLE = "1"; public static final String ROLE_DISABLE = "1";
@ -60,10 +63,9 @@ public class UserConstants
/** InnerLink组件标识 */ /** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink"; public final static String INNER_LINK = "InnerLink";
/** 校验返回结果码 */ /** 校验是否唯一的返回标识 */
public final static String UNIQUE = "0"; public final static boolean UNIQUE = true;
public final static boolean NOT_UNIQUE = false;
public final static String NOT_UNIQUE = "1";
/** /**
* *
@ -78,4 +80,9 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20; public static final int PASSWORD_MAX_LENGTH = 20;
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
} }

View File

@ -81,6 +81,16 @@ public class SecurityContextHolder
set(SecurityConstants.USER_KEY, userKey); set(SecurityConstants.USER_KEY, userKey);
} }
public static String getPermission()
{
return get(SecurityConstants.ROLE_PERMISSION);
}
public static void setPermission(String permissions)
{
set(SecurityConstants.ROLE_PERMISSION, permissions);
}
public static void remove() public static void remove()
{ {
THREAD_LOCAL.remove(); THREAD_LOCAL.remove();

View File

@ -102,4 +102,14 @@ public class R<T> implements Serializable
{ {
this.data = data; 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();
}
} }

View File

@ -7,7 +7,6 @@ package com.ruoyi.common.core.exception;
*/ */
public class GlobalException extends RuntimeException public class GlobalException extends RuntimeException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@ -45,6 +44,7 @@ public class GlobalException extends RuntimeException
return this; return this;
} }
@Override
public String getMessage() public String getMessage()
{ {
return message; return message;

View File

@ -49,6 +49,7 @@ public final class ServiceException extends RuntimeException
return detailMessage; return detailMessage;
} }
@Override
public String getMessage() public String getMessage()
{ {
return message; return message;

View File

@ -11,9 +11,9 @@ public class FileException extends BaseException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) public FileException(String code, Object[] args, String msg)
{ {
super("file", code, args, null); super("file", code, args, msg);
} }
} }

View File

@ -11,6 +11,6 @@ public class FileNameLengthLimitExceededException extends FileException
public FileNameLengthLimitExceededException(int defaultFileNameLength) public FileNameLengthLimitExceededException(int defaultFileNameLength)
{ {
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }, "the filename is too long");
} }
} }

View File

@ -11,6 +11,6 @@ public class FileSizeLimitExceededException extends FileException
public FileSizeLimitExceededException(long defaultMaxSize) public FileSizeLimitExceededException(long defaultMaxSize)
{ {
super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); super("upload.exceed.maxSize", new Object[] { defaultMaxSize }, "the filesize is too large");
} }
} }

View File

@ -0,0 +1,61 @@
package com.ruoyi.common.core.exception.file;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
*
*
* @author ruoyi
*/
public class FileUploadException extends Exception
{
private static final long serialVersionUID = 1L;
private final Throwable cause;
public FileUploadException()
{
this(null, null);
}
public FileUploadException(final String msg)
{
this(msg, null);
}
public FileUploadException(String msg, Throwable cause)
{
super(msg);
this.cause = cause;
}
@Override
public void printStackTrace(PrintStream stream)
{
super.printStackTrace(stream);
if (cause != null)
{
stream.println("Caused by:");
cause.printStackTrace(stream);
}
}
@Override
public void printStackTrace(PrintWriter writer)
{
super.printStackTrace(writer);
if (cause != null)
{
writer.println("Caused by:");
cause.printStackTrace(writer);
}
}
@Override
public Throwable getCause()
{
return cause;
}
}

View File

@ -1,7 +1,6 @@
package com.ruoyi.common.core.exception.file; package com.ruoyi.common.core.exception.file;
import java.util.Arrays; import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/** /**
* *

View File

@ -2,6 +2,7 @@ package com.ruoyi.common.core.text;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.NumberFormat; import java.text.NumberFormat;
@ -313,7 +314,7 @@ public class Convert
* Integer<br> * Integer<br>
* *
* @param split * @param split
* @param split * @param str
* @return * @return
*/ */
public static Integer[] toIntArray(String split, String str) public static Integer[] toIntArray(String split, String str)
@ -363,6 +364,10 @@ public class Convert
*/ */
public static String[] toStrArray(String str) public static String[] toStrArray(String str)
{ {
if (StringUtils.isEmpty(str))
{
return new String[] {};
}
return toStrArray(",", str); return toStrArray(",", str);
} }
@ -370,7 +375,7 @@ public class Convert
* String<br> * String<br>
* *
* @param split * @param split
* @param split * @param str
* @return * @return
*/ */
public static String[] toStrArray(String split, String str) public static String[] toStrArray(String split, String str)
@ -535,7 +540,7 @@ public class Convert
/** /**
* boolean<br> * boolean<br>
* Stringtruefalseyesokno1,0 <br> * Stringtruefalseyesokno10, <br>
* *
* *
* @param value * @param value
@ -561,18 +566,15 @@ public class Convert
switch (valueStr) switch (valueStr)
{ {
case "true": case "true":
case "yes":
case "ok":
case "1":
case "是":
return true; return true;
case "false": case "false":
return false;
case "yes":
return true;
case "ok":
return true;
case "no": case "no":
return false;
case "1":
return true;
case "0": case "0":
case "否":
return false; return false;
default: default:
return defaultValue; return defaultValue;
@ -717,7 +719,7 @@ public class Convert
} }
if (value instanceof Double) if (value instanceof Double)
{ {
return new BigDecimal((Double) value); return BigDecimal.valueOf((Double) value);
} }
if (value instanceof Integer) if (value instanceof Integer)
{ {
@ -907,7 +909,7 @@ public class Convert
*/ */
public static String toSBC(String input, Set<Character> notConvertSet) 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++) for (int i = 0; i < c.length; i++)
{ {
if (null != notConvertSet && notConvertSet.contains(c[i])) if (null != notConvertSet && notConvertSet.contains(c[i]))
@ -949,7 +951,7 @@ public class Convert
*/ */
public static String toDBC(String text, Set<Character> notConvertSet) 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++) for (int i = 0; i < c.length; i++)
{ {
if (null != notConvertSet && notConvertSet.contains(c[i])) if (null != notConvertSet && notConvertSet.contains(c[i]))
@ -967,9 +969,7 @@ public class Convert
c[i] = (char) (c[i] - 65248); c[i] = (char) (c[i] - 65248);
} }
} }
String returnString = new String(c); return new String(c);
return returnString;
} }
/** /**
@ -990,7 +990,12 @@ public class Convert
String s = ""; String s = "";
for (int i = 0; i < fraction.length; i++) for (int i = 0; i < fraction.length; i++)
{ {
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); // 优化double计算精度丢失问题
BigDecimal nNum = new BigDecimal(n);
BigDecimal decimal = new BigDecimal(10);
BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
double d = scale.doubleValue();
s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
} }
if (s.length() < 1) if (s.length() < 1)
{ {

View File

@ -137,16 +137,28 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
} }
/** /**
* *
*/ */
public static String getDatePoor(Date endDate, Date nowDate) public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/**
*
*
* @param endDate
* @param startTime
* @return //
*/
public static String timeDistance(Date endDate, Date startTime)
{ {
long nd = 1000 * 24 * 60 * 60; long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60; long nh = 1000 * 60 * 60;
long nm = 1000 * 60; long nm = 1000 * 60;
// long ns = 1000; // long ns = 1000;
// 获得两个时间的毫秒时间差异 // 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime(); long diff = endDate.getTime() - startTime.getTime();
// 计算差多少天 // 计算差多少天
long day = diff / nd; long day = diff / nd;
// 计算差多少小时 // 计算差多少小时

View File

@ -20,13 +20,10 @@ public class PageUtils extends PageHelper
PageDomain pageDomain = TableSupport.buildPageRequest(); PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum(); Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize(); Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable(); Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
} }
}
/** /**
* 线 * 线

View File

@ -1,164 +0,0 @@
package com.ruoyi.common.core.utils;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils;
public class ReUtil
{
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
/**
*
*/
public final static Set<Character> RE_KEYS = new HashSet<>(
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));;
/**
* <br>
* replacementTemplate$11
*
* <p>
* 12341234(1234)
*
* <pre>
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
*
* (1234)
* </pre>
*
* @param content
* @param regex
* @param replacementTemplate 使$1
* @return
*/
public static String replaceAll(CharSequence content, String regex, String replacementTemplate)
{
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
return replaceAll(content, pattern, replacementTemplate);
}
/**
* <br>
* replacementTemplate$11
*
* @param content
* @param pattern {@link Pattern}
* @param replacementTemplate 使$1
* @return
* @since 3.0.4
*/
public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate)
{
if (StringUtils.isEmpty(content))
{
return StringUtils.EMPTY;
}
final Matcher matcher = pattern.matcher(content);
boolean result = matcher.find();
if (result)
{
final Set<String> varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>());
final StringBuffer sb = new StringBuffer();
do
{
String replacement = replacementTemplate;
for (String var : varNums)
{
int group = Integer.parseInt(var);
replacement = replacement.replace("$" + var, matcher.group(group));
}
matcher.appendReplacement(sb, escape(replacement));
result = matcher.find();
}
while (result);
matcher.appendTail(sb);
return sb.toString();
}
return Convert.toStr(content);
}
/**
*
*
* @param <T>
* @param pattern
* @param content
* @param group
* @param collection
* @return
*/
public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group,
T collection)
{
if (null == pattern || null == content)
{
return null;
}
if (null == collection)
{
throw new NullPointerException("Null collection param provided!");
}
final Matcher matcher = pattern.matcher(content);
while (matcher.find())
{
collection.add(matcher.group(group));
}
return collection;
}
/**
*
*
* @param c
* @return
*/
public static String escape(char c)
{
final StringBuilder builder = new StringBuilder();
if (RE_KEYS.contains(c))
{
builder.append('\\');
}
builder.append(c);
return builder.toString();
}
/**
*
*
* @param content
* @return
*/
public static String escape(CharSequence content)
{
if (StringUtils.isBlank(content))
{
return StringUtils.EMPTY;
}
final StringBuilder builder = new StringBuilder();
int len = content.length();
char current;
for (int i = 0; i < len; i++)
{
current = content.charAt(i);
if (RE_KEYS.contains(current))
{
builder.append('\\');
}
builder.append(current);
}
return builder.toString();
}
}

View File

@ -4,9 +4,11 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.LinkedHashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
@ -15,10 +17,11 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
@ -79,6 +82,34 @@ public class ServletUtils
return Convert.toBool(getRequest().getParameter(name), defaultValue); return Convert.toBool(getRequest().getParameter(name), defaultValue);
} }
/**
*
*
* @param request {@link ServletRequest}
* @return Map
*/
public static Map<String, String[]> getParams(ServletRequest request)
{
final Map<String, String[]> map = request.getParameterMap();
return Collections.unmodifiableMap(map);
}
/**
*
*
* @param request {@link ServletRequest}
* @return Map
*/
public static Map<String, String> getParamMap(ServletRequest request)
{
Map<String, String> params = new HashMap<>();
for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
{
params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
}
return params;
}
/** /**
* request * request
*/ */
@ -142,7 +173,7 @@ public class ServletUtils
public static Map<String, String> getHeaders(HttpServletRequest request) public static Map<String, String> getHeaders(HttpServletRequest request)
{ {
Map<String, String> map = new LinkedHashMap<>(); Map<String, String> map = new LinkedCaseInsensitiveMap<>();
Enumeration<String> enumeration = request.getHeaderNames(); Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null) if (enumeration != null)
{ {
@ -296,7 +327,7 @@ public class ServletUtils
response.setStatusCode(status); response.setStatusCode(status);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
R<?> result = R.fail(code, value.toString()); R<?> result = R.fail(code, value.toString());
DataBuffer dataBuffer = response.bufferFactory().wrap(JSONObject.toJSONString(result).getBytes()); DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
return response.writeWith(Mono.just(dataBuffer)); return response.writeWith(Mono.just(dataBuffer));
} }
} }

View File

@ -20,6 +20,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** 下划线 */ /** 下划线 */
private static final char SEPARATOR = '_'; private static final char SEPARATOR = '_';
/** 星号 */
private static final char ASTERISK = '*';
/** /**
* *
* *
@ -160,6 +163,49 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return (str == null ? "" : str.trim()); return (str == null ? "" : str.trim());
} }
/**
* "*"
*
* @param str
* @param startInclude
* @param endExclude
* @return
*/
public static String hide(CharSequence str, int startInclude, int endExclude)
{
if (isEmpty(str))
{
return NULLSTR;
}
final int strLength = str.length();
if (startInclude > strLength)
{
return NULLSTR;
}
if (endExclude > strLength)
{
endExclude = strLength;
}
if (startInclude > endExclude)
{
// 如果起始位置大于结束位置,不替换
return NULLSTR;
}
final char[] chars = new char[strLength];
for (int i = 0; i < strLength; i++)
{
if (i >= startInclude && i < endExclude)
{
chars[i] = ASTERISK;
}
else
{
chars[i] = str.charAt(i);
}
}
return new String(chars);
}
/** /**
* *
* *
@ -237,6 +283,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return str.substring(start, end); return str.substring(start, end);
} }
/**
* `open` `close`
*
* @param str
* @param open
* @param close
* @return
*/
public static String substringBetweenLast(final String str, final String open, final String close)
{
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
{
return NULLSTR;
}
final int start = str.indexOf(open);
if (start != INDEX_NOT_FOUND)
{
final int end = str.lastIndexOf(close);
if (end != INDEX_NOT_FOUND)
{
return str.substring(start + open.length(), end);
}
}
return NULLSTR;
}
/** /**
* *
* *
@ -294,6 +366,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS); return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
} }
/**
* collectionarray arrayvalue
*
* @param collection
* @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;
}
}
/** /**
* 线 * 线
*/ */
@ -402,7 +500,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
} }
/** /**
* user_name->userName *
* user_name->userName
*/ */
public static String toCamelCase(String s) public static String toCamelCase(String s)
{ {
@ -410,6 +509,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
{ {
return null; return null;
} }
if (s.indexOf(SEPARATOR) == -1)
{
return s;
}
s = s.toLowerCase(); s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length()); StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false; boolean upperCase = false;

View File

@ -1,7 +1,10 @@
package com.ruoyi.common.core.utils.file; package com.ruoyi.common.core.utils.file;
import java.io.File; import java.io.File;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
/** /**
* *
@ -45,6 +48,22 @@ public class FileTypeUtils
return fileName.substring(separatorIndex + 1).toLowerCase(); return fileName.substring(separatorIndex + 1).toLowerCase();
} }
/**
*
*
* @param file
* @return
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
/** /**
* *
* *

View File

@ -97,8 +97,7 @@ public class FileUtils
// 路径为文件且不为空则进行删除 // 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) if (file.isFile() && file.exists())
{ {
file.delete(); flag = file.delete();
flag = true;
} }
return flag; return flag;
} }
@ -115,27 +114,20 @@ public class FileUtils
} }
/** /**
* *
* *
* @param resource * @param fileUrl
* @return true false * @return true false
*/ */
public static boolean checkAllowDownload(String resource) public static boolean validateFilePath(String fileUrl)
{ {
// 禁止目录上跳级别 // 禁止目录上跳级别
if (StringUtils.contains(resource, "..")) if (StringUtils.contains(fileUrl, ".."))
{ {
return false; return false;
} }
// 判断是否在允许下载的文件规则内
// 检查允许下载的文件规则 return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl));
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
} }
/** /**

View File

@ -332,7 +332,7 @@ public final class HTMLFilter
final String name = m.group(1).toLowerCase(); final String name = m.group(1).toLowerCase();
if (allowed(name)) if (allowed(name))
{ {
if (false == inArray(name, vSelfClosingTags)) if (!inArray(name, vSelfClosingTags))
{ {
if (vTagCounts.containsKey(name)) if (vTagCounts.containsKey(name))
{ {
@ -387,7 +387,7 @@ public final class HTMLFilter
{ {
paramValue = processParamProtocol(paramValue); paramValue = processParamProtocol(paramValue);
} }
params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\""); params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
} }
} }

View File

@ -3,6 +3,7 @@ package com.ruoyi.common.core.utils.ip;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
/** /**
@ -12,6 +13,23 @@ import com.ruoyi.common.core.utils.StringUtils;
*/ */
public class IpUtils public class IpUtils
{ {
public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
// 匹配 ip
public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
// 匹配网段
public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
/**
* IP
*
* @return IP
*/
public static String getIpAddr()
{
return getIpAddr(ServletUtils.getRequest());
}
/** /**
* IP * IP
* *
@ -248,7 +266,7 @@ public class IpUtils
} }
} }
} }
return ip; return StringUtils.substring(ip, 0, 255);
} }
/** /**
@ -261,4 +279,104 @@ public class IpUtils
{ {
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
} }
/**
* IP
*/
public static boolean isIP(String ip)
{
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
}
/**
* IP *
*/
public static boolean isIpWildCard(String ip)
{
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
}
/**
* ip
*/
public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
{
String[] s1 = ipWildCard.split("\\.");
String[] s2 = ip.split("\\.");
boolean isMatchedSeg = true;
for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
{
if (!s1[i].equals(s2[i]))
{
isMatchedSeg = false;
break;
}
}
return isMatchedSeg;
}
/**
* :10.10.10.1-10.10.10.99ip
*/
public static boolean isIPSegment(String ipSeg)
{
return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
}
/**
* ip
*/
public static boolean ipIsInNetNoCheck(String iparea, String ip)
{
int idx = iparea.indexOf('-');
String[] sips = iparea.substring(0, idx).split("\\.");
String[] sipe = iparea.substring(idx + 1).split("\\.");
String[] sipt = ip.split("\\.");
long ips = 0L, ipe = 0L, ipt = 0L;
for (int i = 0; i < 4; ++i)
{
ips = ips << 8 | Integer.parseInt(sips[i]);
ipe = ipe << 8 | Integer.parseInt(sipe[i]);
ipt = ipt << 8 | Integer.parseInt(sipt[i]);
}
if (ips > ipe)
{
long t = ips;
ips = ipe;
ipe = t;
}
return ips <= ipt && ipt <= ipe;
}
/**
* ip
*
* @param filter IP,'*',:`10.10.10.1-10.10.10.99`
* @param ip IP
* @return boolean
*/
public static boolean isMatchedIp(String filter, String ip)
{
if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
{
return false;
}
String[] ips = filter.split(";");
for (String iStr : ips)
{
if (isIP(iStr) && iStr.equals(ip))
{
return true;
}
else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
{
return true;
}
else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
{
return true;
}
}
return false;
}
} }

View File

@ -1,5 +1,8 @@
package com.ruoyi.common.core.utils.poi; package com.ruoyi.common.core.utils.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
/** /**
* Excel * Excel
* *
@ -12,8 +15,10 @@ public interface ExcelHandlerAdapter
* *
* @param value * @param value
* @param args excelargs * @param args excelargs
* @param cell
* @param wb 簿
* *
* @return * @return
*/ */
Object format(Object value, String[] args); Object format(Object value, String[] args, Cell cell, Workbook wb);
} }

View File

@ -4,12 +4,14 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -18,12 +20,15 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint; import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper; import org.apache.poi.ss.usermodel.DataValidationHelper;
@ -33,6 +38,7 @@ import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
@ -50,6 +56,7 @@ import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.exception.UtilException;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@ -66,6 +73,8 @@ public class ExcelUtil<T>
{ {
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String SEPARATOR = ",";
public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
@ -125,26 +134,71 @@ public class ExcelUtil<T>
*/ */
private short maxHeight; private short maxHeight;
/**
*
*/
private int subMergedLastRowNum = 0;
/**
*
*/
private int subMergedFirstRowNum = 1;
/**
*
*/
private Map<String, Method> subMethods;
/**
*
*/
private Map<String, List<Field>> subFieldsMap;
/** /**
* *
*/ */
private Map<Integer, Double> statistics = new HashMap<Integer, Double>(); private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
*
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/** /**
* *
*/ */
public Class<T> clazz; public Class<T> clazz;
/**
*
*/
public String[] includeFields;
/**
*
*/
public String[] excludeFields;
public ExcelUtil(Class<T> clazz) public ExcelUtil(Class<T> clazz)
{ {
this.clazz = clazz; this.clazz = clazz;
} }
/**
* Excel
*
* @param fields ["name"/"id","name"]
*/
public void showColumn(String... fields)
{
this.includeFields = fields;
}
/**
* Excel
*
* @param fields ["name"/"id","name"]
*/
public void hideColumn(String... fields)
{
this.excludeFields = fields;
}
public void init(List<T> list, String sheetName, String title, Type type) public void init(List<T> list, String sheetName, String title, Type type)
{ {
if (list == null) if (list == null)
@ -158,6 +212,7 @@ public class ExcelUtil<T>
createExcelField(); createExcelField();
createWorkbook(); createWorkbook();
createTitle(); createTitle();
createSubHead();
} }
/** /**
@ -167,13 +222,58 @@ public class ExcelUtil<T>
{ {
if (StringUtils.isNotEmpty(title)) if (StringUtils.isNotEmpty(title))
{ {
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
for (List<Field> currentSubFields : subFieldsMap.values())
{
titleLastCol = titleLastCol + currentSubFields.size() - 1;
}
}
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30); titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0); Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title")); titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title); titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
this.fields.size() - 1)); }
}
/**
*
*/
public void createSubHead()
{
if (isSubList())
{
Row subRow = sheet.createRow(rownum);
int column = 0;
for (Object[] objects : fields)
{
Field field = (Field) objects[0];
Excel attr = (Excel) objects[1];
CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
if (Collection.class.isAssignableFrom(field.getType()))
{
Cell cell = subRow.createCell(column);
cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle);
int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
if (subFieldSize > 1)
{
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
sheet.addMergedRegion(cellAddress);
}
column += subFieldSize;
}
else
{
Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle);
}
}
rownum++;
} }
} }
@ -183,7 +283,7 @@ public class ExcelUtil<T>
* @param is * @param is
* @return * @return
*/ */
public List<T> importExcel(InputStream is) throws Exception public List<T> importExcel(InputStream is)
{ {
return importExcel(is, 0); return importExcel(is, 0);
} }
@ -195,9 +295,23 @@ public class ExcelUtil<T>
* @param titleNum * @param titleNum
* @return * @return
*/ */
public List<T> importExcel(InputStream is, int titleNum) throws Exception public List<T> importExcel(InputStream is, int titleNum)
{ {
return importExcel(StringUtils.EMPTY, is, titleNum); List<T> list = null;
try
{
list = importExcel(StringUtils.EMPTY, is, titleNum);
}
catch (Exception e)
{
log.error("导入Excel异常{}", e.getMessage());
throw new UtilException(e.getMessage());
}
finally
{
IOUtils.closeQuietly(is);
}
return list;
} }
/** /**
@ -222,14 +336,17 @@ public class ExcelUtil<T>
// 获取最后一个非空行的行下标比如总行数为n则返回的为n-1 // 获取最后一个非空行的行下标比如总行数为n则返回的为n-1
int rows = sheet.getLastRowNum(); int rows = sheet.getLastRowNum();
if (rows > 0) if (rows > 0)
{ {
// 定义一个map用于存放excel列的序号和field. // 定义一个map用于存放excel列的序号和field.
Map<String, Integer> cellMap = new HashMap<String, Integer>(); Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头 // 获取表头
Row heard = sheet.getRow(titleNum); Row heard = sheet.getRow(titleNum);
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) if (heard == null)
{
throw new UtilException("文件标题行为空请检查Excel文件格式");
}
for (int i = 0; i < heard.getLastCellNum(); i++)
{ {
Cell cell = heard.getCell(i); Cell cell = heard.getCell(i);
if (StringUtils.isNotNull(cell)) if (StringUtils.isNotNull(cell))
@ -237,10 +354,6 @@ public class ExcelUtil<T>
String value = this.getCellValue(heard, i).toString(); String value = this.getCellValue(heard, i).toString();
cellMap.put(value, i); cellMap.put(value, i);
} }
else
{
cellMap.put(null, i);
}
} }
// 有数据时才处理 得到类的所有field. // 有数据时才处理 得到类的所有field.
List<Object[]> fields = this.getFields(); List<Object[]> fields = this.getFields();
@ -278,7 +391,7 @@ public class ExcelUtil<T>
if (String.class == fieldType) if (String.class == fieldType)
{ {
String s = Convert.toStr(val); String s = Convert.toStr(val);
if (StringUtils.endsWith(s, ".0")) if (s.matches("^\\d+\\.0$"))
{ {
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0");
} }
@ -337,13 +450,13 @@ public class ExcelUtil<T>
{ {
propertyName = field.getName() + "." + attr.targetAttr(); propertyName = field.getName() + "." + attr.targetAttr();
} }
else if (StringUtils.isNotEmpty(attr.readConverterExp())) if (StringUtils.isNotEmpty(attr.readConverterExp()))
{ {
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
} }
else if (!attr.handler().equals(ExcelHandlerAdapter.class)) else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{ {
val = dataFormatHandlerAdapter(val, attr); val = dataFormatHandlerAdapter(val, attr, null);
} }
ReflectUtils.invokeSetter(entity, propertyName, val); ReflectUtils.invokeSetter(entity, propertyName, val);
} }
@ -361,7 +474,6 @@ public class ExcelUtil<T>
* @param list * @param list
* @param sheetName * @param sheetName
* @return * @return
* @throws IOException
*/ */
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName) public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
{ {
@ -376,7 +488,6 @@ public class ExcelUtil<T>
* @param sheetName * @param sheetName
* @param title * @param title
* @return * @return
* @throws IOException
*/ */
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title) public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
{ {
@ -386,12 +497,6 @@ public class ExcelUtil<T>
exportExcel(response); exportExcel(response);
} }
/**
* listexcel
*
* @param sheetName
* @return
*/
/** /**
* listexcel * listexcel
* *
@ -457,12 +562,25 @@ public class ExcelUtil<T>
// 写入各个字段的列头名称 // 写入各个字段的列头名称
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
this.createCell(excel, row, column++); if (Collection.class.isAssignableFrom(field.getType()))
{
List<Field> currentSubFields = subFieldsMap.get(field.getName());
for (Field subField : currentSubFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++);
}
}
else
{
this.createHeadCell(excel, row, column++);
}
} }
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index, row); fillExcelData(index);
addStatisticsRow(); addStatisticsRow();
} }
} }
@ -472,25 +590,98 @@ public class ExcelUtil<T>
* excel * excel
* *
* @param index * @param index
* @param row
*/ */
public void fillExcelData(int index, Row row) @SuppressWarnings("unchecked")
public void fillExcelData(int index)
{ {
int startNo = index * sheetSize; int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
int currentRowNum = rownum + 1; // 从标题行后开始
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
row = sheet.createRow(i + 1 + rownum - startNo); Row row = sheet.createRow(currentRowNum);
// 得到导出对象.
T vo = (T) list.get(i); T vo = (T) list.get(i);
int column = 0; int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0]; Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
this.addCell(excel, row, vo, field, column++); if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
List<Field> currentSubFields = subFieldsMap.get(field.getName());
if (subList != null && !subList.isEmpty())
{
int subIndex = 0;
for (Object subVo : subList)
{
Row subRow = sheet.getRow(currentRowNum + subIndex);
if (subRow == null)
{
subRow = sheet.createRow(currentRowNum + subIndex);
}
int subColumn = column;
for (Field subField : currentSubFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
}
subIndex++;
} }
} }
column += currentSubFields.size();
}
catch (Exception e)
{
log.error("填充集合数据失败", e);
}
}
else
{
// 创建单元格并设置值
addCell(excel, row, vo, field, column);
if (maxSubListSize > 1 && excel.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
}
column++;
}
}
currentRowNum += maxSubListSize;
}
}
/**
*
*/
private int getCurrentMaxSubListSize(T vo)
{
int maxSubListSize = 1;
for (Object[] os : fields)
{
Field field = (Field) os[0];
if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
if (subList != null && !subList.isEmpty())
{
maxSubListSize = Math.max(maxSubListSize, subList.size());
}
}
catch (Exception e)
{
log.error("获取集合大小失败", e);
}
}
}
return maxSubListSize;
} }
/** /**
@ -511,6 +702,8 @@ public class ExcelUtil<T>
titleFont.setFontHeightInPoints((short) 16); titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true); titleFont.setBold(true);
style.setFont(titleFont); style.setFont(titleFont);
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
styles.put("title", style); styles.put("title", style);
style = wb.createCellStyle(); style = wb.createCellStyle();
@ -530,58 +723,151 @@ public class ExcelUtil<T>
style.setFont(dataFont); style.setFont(dataFont);
styles.put("data", style); 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 = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(dataFormat.getFormat("######0.00"));
Font totalFont = wb.createFont(); Font totalFont = wb.createFont();
totalFont.setFontName("Arial"); totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10); totalFont.setFontHeightInPoints((short) 10);
style.setFont(totalFont); style.setFont(totalFont);
styles.put("total", style); styles.put("total", style);
style = wb.createCellStyle(); styles.putAll(annotationHeaderStyles(wb, styles));
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
style = wb.createCellStyle(); styles.putAll(annotationDataStyles(wb));
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
return styles; return styles;
} }
/**
* Excel
*
* @param wb
* @return
*/
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);
// 设置表格头单元格文本形式
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
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)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType()))
{
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
annotationDataStyles(styles, subField, subExcel);
}
}
else
{
annotationDataStyles(styles, field, excel);
}
}
return styles;
}
/**
* Excel
*
* @param styles
* @param field
* @param excel
*/
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{
String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style.setAlignment(excel.align());
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(BorderStyle.THIN);
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());
style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
dataFont.setColor(excel.color().index);
style.setFont(dataFont);
if (ColumnType.TEXT == excel.cellType())
{
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
}
styles.put(key, style);
}
}
/** /**
* *
*/ */
public Cell createCell(Excel attr, Row row, int column) public Cell createHeadCell(Excel attr, Row row, int column)
{ {
// 创建列 // 创建列
Cell cell = row.createCell(column); Cell cell = row.createCell(column);
// 写入列信息 // 写入列信息
cell.setCellValue(attr.name()); cell.setCellValue(attr.name());
setDataValidation(attr, row, column); 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(), attr.cellType(), attr.wrapText())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
}
}
return cell; return cell;
} }
@ -594,7 +880,7 @@ public class ExcelUtil<T>
*/ */
public void setCellVo(Object value, Excel attr, Cell cell) public void setCellVo(Object value, Excel attr, Cell cell)
{ {
if (ColumnType.STRING == attr.cellType()) if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
{ {
String cellValue = Convert.toStr(value); String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入。 // 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入。
@ -602,6 +888,10 @@ public class ExcelUtil<T>
{ {
cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); 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()); cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
} }
else if (ColumnType.NUMERIC == attr.cellType()) else if (ColumnType.NUMERIC == attr.cellType())
@ -668,11 +958,19 @@ public class ExcelUtil<T>
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
} }
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
{
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); setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
} }
} }
}
/** /**
* *
@ -689,8 +987,14 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
int align = attr.align().value(); if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge())
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); {
if (subMergedLastRowNum >= subMergedFirstRowNum)
{
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
}
}
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
@ -699,6 +1003,7 @@ public class ExcelUtil<T>
String separator = attr.separator(); String separator = attr.separator();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(parseDateToStr(dateFormat, value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
@ -707,11 +1012,11 @@ public class ExcelUtil<T>
} }
else if (value instanceof BigDecimal && -1 != attr.scale()) 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)) else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{ {
cell.setCellValue(dataFormatHandlerAdapter(value, attr)); cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
} }
else else
{ {
@ -765,6 +1070,76 @@ public class ExcelUtil<T>
sheet.addValidationData(dataValidation); 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 = null;
String hideSheetDataName = hideSheetName + "_data";
Name name = wb.getName(hideSheetDataName);
if (name != null)
{
// 名称已存在尝试从名称的引用中找到sheet名称
String refersToFormula = name.getRefersToFormula();
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
{
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
hideSheet = wb.getSheet(sheetNameFromFormula);
}
}
if (hideSheet == null)
{
hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
name = wb.createName();
name.setNameName(hideSheetDataName);
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
}
DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
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= * 0=,1=,2=
* *
@ -776,11 +1151,11 @@ public class ExcelUtil<T>
public static String convertByExp(String propertyValue, String converterExp, String separator) public static String convertByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(","); String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) if (StringUtils.containsAny(propertyValue, separator))
{ {
for (String value : propertyValue.split(separator)) for (String value : propertyValue.split(separator))
{ {
@ -813,11 +1188,11 @@ public class ExcelUtil<T>
public static String reverseByExp(String propertyValue, String converterExp, String separator) public static String reverseByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(","); String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) if (StringUtils.containsAny(propertyValue, separator))
{ {
for (String value : propertyValue.split(separator)) for (String value : propertyValue.split(separator))
{ {
@ -846,13 +1221,13 @@ public class ExcelUtil<T>
* @param excel * @param excel
* @return * @return
*/ */
public String dataFormatHandlerAdapter(Object value, Excel excel) public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
{ {
try try
{ {
Object instance = excel.handler().newInstance(); Object instance = excel.handler().newInstance();
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
value = formatMethod.invoke(instance, value, excel.args()); value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
} }
catch (Exception e) catch (Exception e)
{ {
@ -901,7 +1276,7 @@ public class ExcelUtil<T>
{ {
cell = row.createCell(key); cell = row.createCell(key);
cell.setCellStyle(styles.get("total")); cell.setCellStyle(styles.get("total"));
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); cell.setCellValue(statistics.get(key));
} }
statistics.clear(); statistics.clear();
} }
@ -918,6 +1293,7 @@ public class ExcelUtil<T>
*/ */
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{ {
field.setAccessible(true);
Object o = field.get(vo); Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr())) if (StringUtils.isNotEmpty(excel.targetAttr()))
{ {
@ -975,9 +1351,44 @@ public class ExcelUtil<T>
{ {
List<Object[]> fields = new ArrayList<Object[]>(); List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
subFieldsMap = new HashMap<>();
subMethods = new HashMap<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (StringUtils.isNotEmpty(includeFields))
{
for (Field field : tempFields) for (Field field : tempFields)
{
if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
{
addField(fields, field);
}
}
}
else if (StringUtils.isNotEmpty(excludeFields))
{
for (Field field : tempFields)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{
addField(fields, field);
}
}
}
else
{
for (Field field : tempFields)
{
addField(fields, field);
}
}
return fields;
}
/**
*
*/
public void addField(List<Object[]> fields, Field field)
{ {
// 单注解 // 单注解
if (field.isAnnotationPresent(Excel.class)) if (field.isAnnotationPresent(Excel.class))
@ -985,9 +1396,16 @@ public class ExcelUtil<T>
Excel attr = field.getAnnotation(Excel.class); Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{ {
field.setAccessible(true);
fields.add(new Object[] { field, attr }); fields.add(new Object[] { field, attr });
} }
if (Collection.class.isAssignableFrom(field.getType()))
{
String fieldName = field.getName();
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
}
} }
// 多注解 // 多注解
@ -997,15 +1415,24 @@ public class ExcelUtil<T>
Excel[] excels = attrs.value(); Excel[] excels = attrs.value();
for (Excel attr : excels) for (Excel attr : excels)
{ {
if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) if (StringUtils.isNotEmpty(includeFields))
{
if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
fields.add(new Object[] { field, attr });
}
}
else
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{ {
field.setAccessible(true);
fields.add(new Object[] { field, attr }); fields.add(new Object[] { field, attr });
} }
} }
} }
} }
return fields;
} }
/** /**
@ -1046,7 +1473,8 @@ public class ExcelUtil<T>
{ {
this.sheet = wb.createSheet(); this.sheet = wb.createSheet();
this.createTitle(); this.createTitle();
wb.setSheetName(index, sheetName + index); int actualIndex = wb.getSheetIndex(this.sheet);
wb.setSheetName(actualIndex, sheetName + index);
} }
} }
@ -1165,4 +1593,69 @@ public class ExcelUtil<T>
} }
return str; return str;
} }
/**
*
*/
public boolean isSubList()
{
return !StringUtils.isEmpty(subFieldsMap);
}
/**
*
*/
public boolean isSubListValue(T vo)
{
return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0;
}
/**
*
*/
public int getListCellValue(Object obj)
{
Collection<?> value;
int max = 0;
try
{
for (String s : subMethods.keySet())
{
value = (Collection<?>) subMethods.get(s).invoke(obj);
if (value.size() > max)
{
max = value.size();
}
}
}
catch (Exception e)
{
return 0;
}
return max;
}
/**
*
*
* @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;
}
} }

View File

@ -13,13 +13,18 @@ public class SqlUtil
/** /**
* sql * 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 = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
/** /**
* 线 * 线
*/ */
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* orderBy
*/
private static final int ORDER_BY_MAX_LENGTH = 500;
/** /**
* *
*/ */
@ -29,6 +34,10 @@ public class SqlUtil
{ {
throw new UtilException("参数不符合规范,不能进行查询"); throw new UtilException("参数不符合规范,不能进行查询");
} }
if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
{
throw new UtilException("参数已超过最大限制,不能进行查询");
}
return value; return value;
} }

View File

@ -22,7 +22,7 @@ public class Seq
private static AtomicInteger uploadSeq = new AtomicInteger(1); private static AtomicInteger uploadSeq = new AtomicInteger(1);
// 机器标识 // 机器标识
private static String machineCode = "A"; private static final String machineCode = "A";
/** /**
* *

View File

@ -66,7 +66,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
} }
/** /**
* 4UUID 使线 UUID * 4UUID
* *
* @return {@code UUID} * @return {@code UUID}
*/ */
@ -343,25 +343,25 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low // time_low
builder.append(digits(mostSigBits >> 32, 8)); builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_mid // time_mid
builder.append(digits(mostSigBits >> 16, 4)); builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_high_and_version // time_high_and_version
builder.append(digits(mostSigBits, 4)); builder.append(digits(mostSigBits, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// variant_and_sequence // variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4)); builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }

View File

@ -7,12 +7,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PageUtils; import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.sql.SqlUtil;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.core.web.page.TableSupport;
/** /**
* web * web
@ -48,6 +53,19 @@ public class BaseController
PageUtils.startPage(); PageUtils.startPage();
} }
/**
*
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/** /**
* 线 * 线
*/ */
@ -70,6 +88,54 @@ public class BaseController
return rspData; return rspData;
} }
/**
*
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
*
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
*
*/
public AjaxResult success(Object data)
{
return AjaxResult.success(data);
}
/**
*
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
*
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
*
*/
public AjaxResult warn(String message)
{
return AjaxResult.warn(message);
}
/** /**
* *
* *
@ -91,36 +157,4 @@ public class BaseController
{ {
return result ? success() : error(); return result ? success() : error();
} }
/**
*
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
*
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
*
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
*
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
} }

View File

@ -1,6 +1,7 @@
package com.ruoyi.common.core.web.domain; package com.ruoyi.common.core.web.domain;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@ -58,20 +59,6 @@ public class AjaxResult extends HashMap<String, Object>
} }
} }
/**
* 便
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
/** /**
* *
* *
@ -115,10 +102,33 @@ public class AjaxResult extends HashMap<String, Object>
return new AjaxResult(HttpStatus.SUCCESS, msg, data); 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() public static AjaxResult error()
{ {
@ -129,7 +139,7 @@ public class AjaxResult extends HashMap<String, Object>
* *
* *
* @param msg * @param msg
* @return * @return
*/ */
public static AjaxResult error(String msg) public static AjaxResult error(String msg)
{ {
@ -141,7 +151,7 @@ public class AjaxResult extends HashMap<String, Object>
* *
* @param msg * @param msg
* @param data * @param data
* @return * @return
*/ */
public static AjaxResult error(String msg, Object data) public static AjaxResult error(String msg, Object data)
{ {
@ -153,10 +163,54 @@ public class AjaxResult extends HashMap<String, Object>
* *
* @param code * @param code
* @param msg * @param msg
* @return * @return
*/ */
public static AjaxResult error(int code, String msg) public static AjaxResult error(int code, String msg)
{ {
return new AjaxResult(code, msg, null); return new AjaxResult(code, msg, null);
} }
/**
*
*
* @return
*/
public boolean isSuccess()
{
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
}
/**
*
*
* @return
*/
public boolean isWarn()
{
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
}
/**
*
*
* @return
*/
public boolean isError()
{
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
}
/**
* 便
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
} }

View File

@ -5,6 +5,8 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/** /**
* Entity * Entity
@ -16,6 +18,7 @@ public class BaseEntity implements Serializable
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 搜索值 */ /** 搜索值 */
@JsonIgnore
private String searchValue; private String searchValue;
/** 创建者 */ /** 创建者 */
@ -36,6 +39,7 @@ public class BaseEntity implements Serializable
private String remark; private String remark;
/** 请求参数 */ /** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params; private Map<String, Object> params;
public String getSearchValue() public String getSearchValue()

View File

@ -37,7 +37,7 @@ public class TableDataInfo implements Serializable
* @param list * @param list
* @param total * @param total
*/ */
public TableDataInfo(List<?> list, int total) public TableDataInfo(List<?> list, long total)
{ {
this.rows = list; this.rows = list;
this.total = total; this.total = total;

View File

@ -1,5 +1,6 @@
package com.ruoyi.common.core.web.page; package com.ruoyi.common.core.web.page;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
/** /**
@ -40,8 +41,8 @@ public class TableSupport
public static PageDomain getPageDomain() public static PageDomain getPageDomain()
{ {
PageDomain pageDomain = new PageDomain(); PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));

View File

@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
public static boolean containsHtml(String value) public static boolean containsHtml(String value)
{ {
StringBuilder sHtml = new StringBuilder();
Pattern pattern = Pattern.compile(HTML_PATTERN); Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value); Matcher matcher = pattern.matcher(value);
return matcher.matches(); while (matcher.find())
{
sHtml.append(matcher.group());
}
return pattern.matcher(sHtml).matches();
} }
} }

View File

@ -1,4 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.core.utils.SpringUtils

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -25,4 +25,9 @@ public @interface DataScope
* *
*/ */
public String userAlias() default ""; public String userAlias() default "";
/**
* @RequiresPermissions
*/
public String permission() default "";
} }

View File

@ -1,9 +1,14 @@
package com.ruoyi.common.datascope.aspect; package com.ruoyi.common.datascope.aspect;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.datascope.annotation.DataScope; import com.ruoyi.common.datascope.annotation.DataScope;
@ -68,8 +73,8 @@ public class DataScopeAspect
// 如果是超级管理员,则不过滤数据 // 如果是超级管理员,则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{ {
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), SecurityContextHolder.getPermission());
controllerDataScope.userAlias()); dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
} }
} }
} }
@ -81,24 +86,48 @@ public class DataScopeAspect
* @param user * @param user
* @param deptAlias * @param deptAlias
* @param userAlias * @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(); StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))))
{
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
}
});
for (SysRole role : user.getRoles()) for (SysRole role : user.getRoles())
{ {
String dataScope = role.getDataScope(); String dataScope = role.getDataScope();
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
{
continue;
}
if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope)) if (DATA_SCOPE_ALL.equals(dataScope))
{ {
sqlString = new StringBuilder(); sqlString = new StringBuilder();
conditions.add(dataScope);
break; break;
} }
else if (DATA_SCOPE_CUSTOM.equals(dataScope)) else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{ {
sqlString.append(StringUtils.format( if (scopeCustomIds.size() > 1)
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, {
role.getRoleId())); // 多个自定数据权限使用in查询避免多次拼接。
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
}
else
{
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
}
} }
else if (DATA_SCOPE_DEPT.equals(dataScope)) else if (DATA_SCOPE_DEPT.equals(dataScope))
{ {
@ -106,9 +135,7 @@ public class DataScopeAspect
} }
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{ {
sqlString.append(StringUtils.format( sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
} }
else if (DATA_SCOPE_SELF.equals(dataScope)) else if (DATA_SCOPE_SELF.equals(dataScope))
{ {
@ -119,9 +146,16 @@ public class DataScopeAspect
else else
{ {
// 数据权限为仅本人且没有userAlias别名不查询任何数据 // 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 "); sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
} }
} }
conditions.add(dataScope);
}
// 角色都不包含传递过来的权限字符这个时候sqlString也会为空所以要限制一下,不查询任何数据
if (StringUtils.isEmpty(conditions))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
} }
if (StringUtils.isNotBlank(sqlString.toString())) if (StringUtils.isNotBlank(sqlString.toString()))

View File

@ -1,4 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.datascope.aspect.DataScopeAspect

View File

@ -0,0 +1 @@
com.ruoyi.common.datascope.aspect.DataScopeAspect

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -31,11 +31,5 @@
<version>${dynamic-ds.version}</version> <version>${dynamic-ds.version}</version>
</dependency> </dependency>
<!-- SpringBoot Seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,26 +0,0 @@
package com.ruoyi.common.datasource.env;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* seata springboot 2.6.x
*
* @author ruoyi
*/
public class ApplicationSeataInitializer implements EnvironmentPostProcessor, Ordered
{
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
{
System.setProperty("spring.main.allow-circular-references", "true");
}
@Override
public int getOrder()
{
return Ordered.LOWEST_PRECEDENCE;
}
}

View File

@ -1,2 +0,0 @@
org.springframework.boot.env.EnvironmentPostProcessor=\
com.ruoyi.common.datasource.env.ApplicationSeataInitializer

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -43,4 +43,9 @@ public @interface Log
* *
*/ */
public boolean isSaveResponseData() default true; public boolean isSaveResponseData() default true;
/**
*
*/
public String[] excludeParamNames() default {};
} }

View File

@ -4,23 +4,29 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.ExceptionUtil;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils; import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessStatus; import com.ruoyi.common.log.enums.BusinessStatus;
import com.ruoyi.common.log.filter.PropertyPreExcludeFilter;
import com.ruoyi.common.log.service.AsyncLogService; import com.ruoyi.common.log.service.AsyncLogService;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysOperLog; import com.ruoyi.system.api.domain.SysOperLog;
@ -36,9 +42,27 @@ public class LogAspect
{ {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class); private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/** 排除敏感属性字段 */
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
/** 计算操作消耗时间 */
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
/** 参数最大长度限制 */
private static final int PARAM_MAX_LENGTH = 2000;
@Autowired @Autowired
private AsyncLogService asyncLogService; private AsyncLogService asyncLogService;
/**
*
*/
@Before(value = "@annotation(controllerLog)")
public void doBefore(JoinPoint joinPoint, Log controllerLog)
{
TIME_THREADLOCAL.set(System.currentTimeMillis());
}
/** /**
* *
* *
@ -70,9 +94,9 @@ public class LogAspect
SysOperLog operLog = new SysOperLog(); SysOperLog operLog = new SysOperLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址 // 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); String ip = IpUtils.getIpAddr();
operLog.setOperIp(ip); operLog.setOperIp(ip);
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
String username = SecurityUtils.getUsername(); String username = SecurityUtils.getUsername();
if (StringUtils.isNotBlank(username)) if (StringUtils.isNotBlank(username))
{ {
@ -82,7 +106,7 @@ public class LogAspect
if (e != null) if (e != null)
{ {
operLog.setStatus(BusinessStatus.FAIL.ordinal()); operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000));
} }
// 设置方法名称 // 设置方法名称
String className = joinPoint.getTarget().getClass().getName(); String className = joinPoint.getTarget().getClass().getName();
@ -92,16 +116,21 @@ public class LogAspect
operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数 // 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 设置消耗时间
operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
// 保存数据库 // 保存数据库
asyncLogService.saveSysLog(operLog); asyncLogService.saveSysLog(operLog);
} }
catch (Exception exp) catch (Exception exp)
{ {
// 记录本地异常日志 // 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage()); log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace(); exp.printStackTrace();
} }
finally
{
TIME_THREADLOCAL.remove();
}
} }
/** /**
@ -123,7 +152,7 @@ public class LogAspect
if (log.isSaveRequestData()) if (log.isSaveRequestData())
{ {
// 获取参数的信息,传入到数据库中。 // 获取参数的信息,传入到数据库中。
setRequestValue(joinPoint, operLog); setRequestValue(joinPoint, operLog, log.excludeParamNames());
} }
// 是否需要保存response参数和值 // 是否需要保存response参数和值
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
@ -138,22 +167,27 @@ public class LogAspect
* @param operLog * @param operLog
* @throws Exception * @throws Exception
*/ */
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
{ {
String requestMethod = operLog.getRequestMethod(); String requestMethod = operLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
{ {
String params = argsArrayToString(joinPoint.getArgs()); String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(StringUtils.substring(params, 0, 2000)); operLog.setOperParam(params);
}
else
{
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH));
} }
} }
/** /**
* *
*/ */
private String argsArrayToString(Object[] paramsArray) private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{ {
String params = ""; StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (Object o : paramsArray) for (Object o : paramsArray)
@ -162,16 +196,29 @@ public class LogAspect
{ {
try try
{ {
Object jsonObj = JSON.toJSON(o); String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params += jsonObj.toString() + " "; params.append(jsonObj).append(" ");
if (params.length() >= PARAM_MAX_LENGTH)
{
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
}
} }
catch (Exception e) catch (Exception e)
{ {
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
} }
} }
} }
} }
return params.trim(); return params.toString();
}
/**
*
*/
public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
{
return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
} }
/** /**

View File

@ -0,0 +1,24 @@
package com.ruoyi.common.log.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;
}
}

View File

@ -22,7 +22,7 @@ public class AsyncLogService
* *
*/ */
@Async @Async
public void saveSysLog(SysOperLog sysOperLog) public void saveSysLog(SysOperLog sysOperLog) throws Exception
{ {
remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER); remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER);
} }

View File

@ -1,3 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.log.service.AsyncLogService,\
com.ruoyi.common.log.aspect.LogAspect

View File

@ -0,0 +1,2 @@
com.ruoyi.common.log.service.AsyncLogService
com.ruoyi.common.log.aspect.LogAspect

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -1,15 +1,13 @@
package com.ruoyi.common.redis.configure; package com.ruoyi.common.redis.configure;
import com.alibaba.fastjson.JSON; import java.nio.charset.Charset;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson2.JSON;
import org.springframework.util.Assert; import com.alibaba.fastjson2.JSONReader;
import java.nio.charset.Charset; import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.ruoyi.common.core.constant.Constants;
/** /**
* Redis使FastJson * Redis使FastJson
@ -18,17 +16,11 @@ import java.nio.charset.Charset;
*/ */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{ {
@SuppressWarnings("unused")
private ObjectMapper objectMapper = new ObjectMapper();
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz; static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
static private Class<T> clazz;
{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
}
public FastJson2JsonRedisSerializer(Class<T> clazz) public FastJson2JsonRedisSerializer(Class<T> clazz)
{ {
@ -43,7 +35,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{ {
return new byte[0]; return new byte[0];
} }
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
} }
@Override @Override
@ -55,17 +47,6 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
} }
String str = new String(bytes, DEFAULT_CHARSET); String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz); return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
}
public void setObjectMapper(ObjectMapper objectMapper)
{
Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper;
}
protected JavaType getJavaType(Class<?> clazz)
{
return TypeFactory.defaultInstance().constructType(clazz);
} }
} }

View File

@ -1,5 +1,7 @@
package com.ruoyi.common.redis.configure; package com.ruoyi.common.redis.configure;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -7,11 +9,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
/** /**
* redis * redis
@ -20,6 +17,7 @@ import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator
*/ */
@Configuration @Configuration
@EnableCaching @EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport public class RedisConfig extends CachingConfigurerSupport
{ {
@Bean @Bean
@ -31,11 +29,6 @@ public class RedisConfig extends CachingConfigurerSupport
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
// 使用StringRedisSerializer来序列化和反序列化redis的key值 // 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer); template.setValueSerializer(serializer);

View File

@ -124,9 +124,9 @@ public class RedisService
* @param collection * @param collection
* @return * @return
*/ */
public long deleteObject(final Collection collection) public boolean deleteObject(final Collection collection)
{ {
return redisTemplate.delete(collection); return redisTemplate.delete(collection) > 0;
} }
/** /**
@ -243,6 +243,18 @@ public class RedisService
return redisTemplate.opsForHash().multiGet(key, hKeys); 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;
}
/** /**
* *
* *

View File

@ -1,5 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.redis.configure.RedisConfig,\
com.ruoyi.common.redis.service.RedisService

View File

@ -0,0 +1,2 @@
com.ruoyi.common.redis.configure.RedisConfig
com.ruoyi.common.redis.service.RedisService

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>3.6.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-seata</artifactId>
<description>
ruoyi-common-seata分布式事务
</description>
<dependencies>
<!-- SpringBoot Seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.5.0</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -56,16 +56,8 @@ public class PreAuthorizeAspect
// 注解鉴权 // 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
checkMethodAnnotation(signature.getMethod()); checkMethodAnnotation(signature.getMethod());
try
{
// 执行原有逻辑 // 执行原有逻辑
Object obj = joinPoint.proceed(); return joinPoint.proceed();
return obj;
}
catch (Throwable e)
{
throw e;
}
} }
/** /**

View File

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.springframework.util.PatternMatchUtils; import org.springframework.util.PatternMatchUtils;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.exception.auth.NotLoginException; import com.ruoyi.common.core.exception.auth.NotLoginException;
import com.ruoyi.common.core.exception.auth.NotPermissionException; import com.ruoyi.common.core.exception.auth.NotPermissionException;
import com.ruoyi.common.core.exception.auth.NotRoleException; import com.ruoyi.common.core.exception.auth.NotRoleException;
@ -134,6 +135,7 @@ public class AuthLogic
*/ */
public void checkPermi(RequiresPermissions requiresPermissions) public void checkPermi(RequiresPermissions requiresPermissions)
{ {
SecurityContextHolder.setPermission(StringUtils.join(requiresPermissions.value(), ","));
if (requiresPermissions.logical() == Logical.AND) if (requiresPermissions.logical() == Logical.AND)
{ {
checkPermiAnd(requiresPermissions.value()); checkPermiAnd(requiresPermissions.value());
@ -353,7 +355,7 @@ public class AuthLogic
public boolean hasPermi(Collection<String> authorities, String permission) public boolean hasPermi(Collection<String> authorities, String permission)
{ {
return authorities.stream().filter(StringUtils::hasText) return authorities.stream().filter(StringUtils::hasText)
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission)); .anyMatch(x -> ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
} }
/** /**
@ -366,6 +368,6 @@ public class AuthLogic
public boolean hasRole(Collection<String> roles, String role) public boolean hasRole(Collection<String> roles, String role)
{ {
return roles.stream().filter(StringUtils::hasText) return roles.stream().filter(StringUtils::hasText)
.anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role)); .anyMatch(x -> SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
} }
} }

View File

@ -27,7 +27,7 @@ public class AuthUtil
/** /**
* Token * Token
* *
* @param tokenValue token * @param token token
*/ */
public static void logoutByToken(String token) public static void logoutByToken(String token)
{ {
@ -44,6 +44,9 @@ public class AuthUtil
/** /**
* *
*
* @param token token
* @return
*/ */
public static LoginUser getLoginUser(String token) public static LoginUser getLoginUser(String token)
{ {
@ -52,6 +55,8 @@ public class AuthUtil
/** /**
* *
*
* @param loginUser
*/ */
public static void verifyLoginUserExpire(LoginUser loginUser) public static void verifyLoginUserExpire(LoginUser loginUser)
{ {

View File

@ -31,6 +31,11 @@ public class FeignRequestInterceptor implements RequestInterceptor
{ {
requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId); requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);
} }
String userKey = headers.get(SecurityConstants.USER_KEY);
if (StringUtils.isNotEmpty(userKey))
{
requestTemplate.header(SecurityConstants.USER_KEY, userKey);
}
String userName = headers.get(SecurityConstants.DETAILS_USERNAME); String userName = headers.get(SecurityConstants.DETAILS_USERNAME);
if (StringUtils.isNotEmpty(userName)) if (StringUtils.isNotEmpty(userName))
{ {
@ -43,7 +48,7 @@ public class FeignRequestInterceptor implements RequestInterceptor
} }
// 配置客户端IP // 配置客户端IP
requestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr(ServletUtils.getRequest())); requestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr());
} }
} }
} }

View File

@ -6,15 +6,19 @@ import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.exception.DemoModeException; import com.ruoyi.common.core.exception.DemoModeException;
import com.ruoyi.common.core.exception.InnerAuthException; import com.ruoyi.common.core.exception.InnerAuthException;
import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.exception.auth.NotPermissionException; import com.ruoyi.common.core.exception.auth.NotPermissionException;
import com.ruoyi.common.core.exception.auth.NotRoleException; import com.ruoyi.common.core.exception.auth.NotRoleException;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.html.EscapeUtil;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
/** /**
@ -53,8 +57,7 @@ public class GlobalExceptionHandler
* *
*/ */
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request)
HttpServletRequest request)
{ {
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
@ -72,6 +75,33 @@ public class GlobalExceptionHandler
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
} }
/**
*
*/
@ExceptionHandler(MissingPathVariableException.class)
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
}
/**
*
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
String value = Convert.toStr(e.getValue());
if (StringUtils.isNotEmpty(value))
{
value = EscapeUtil.clean(value);
}
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
}
/** /**
* *
*/ */

View File

@ -4,6 +4,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.CacheConstants;
@ -25,6 +27,8 @@ import com.ruoyi.system.api.model.LoginUser;
@Component @Component
public class TokenService public class TokenService
{ {
private static final Logger log = LoggerFactory.getLogger(TokenService.class);
@Autowired @Autowired
private RedisService redisService; private RedisService redisService;
@ -32,11 +36,11 @@ public class TokenService
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private final static long expireTime = CacheConstants.EXPIRATION; private final static long TOKEN_EXPIRE_TIME = CacheConstants.EXPIRATION;
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY; private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; private final static Long TOKEN_REFRESH_THRESHOLD_MINUTES = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
/** /**
* *
@ -49,7 +53,7 @@ public class TokenService
loginUser.setToken(token); loginUser.setToken(token);
loginUser.setUserid(userId); loginUser.setUserid(userId);
loginUser.setUsername(userName); loginUser.setUsername(userName);
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest())); loginUser.setIpaddr(IpUtils.getIpAddr());
refreshToken(loginUser); refreshToken(loginUser);
// Jwt存储信息 // Jwt存储信息
@ -61,7 +65,7 @@ public class TokenService
// 接口返回信息 // 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>(); Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap)); rspMap.put("access_token", JwtUtils.createToken(claimsMap));
rspMap.put("expires_in", expireTime); rspMap.put("expires_in", TOKEN_EXPIRE_TIME);
return rspMap; return rspMap;
} }
@ -106,6 +110,7 @@ public class TokenService
} }
catch (Exception e) catch (Exception e)
{ {
log.error("获取用户信息异常'{}'", e.getMessage());
} }
return user; return user;
} }
@ -142,7 +147,7 @@ public class TokenService
{ {
long expireTime = loginUser.getExpireTime(); long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) if (expireTime - currentTime <= TOKEN_REFRESH_THRESHOLD_MINUTES)
{ {
refreshToken(loginUser); refreshToken(loginUser);
} }
@ -156,10 +161,10 @@ public class TokenService
public void refreshToken(LoginUser loginUser) public void refreshToken(LoginUser loginUser)
{ {
loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + TOKEN_EXPIRE_TIME * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken()); String userKey = getTokenKey(loginUser.getToken());
redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); redisService.setCacheObject(userKey, loginUser, TOKEN_EXPIRE_TIME, TimeUnit.MINUTES);
} }
private String getTokenKey(String token) private String getTokenKey(String token)

View File

@ -2,7 +2,8 @@ package com.ruoyi.common.security.utils;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import com.ruoyi.common.core.constant.Constants; import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.common.redis.service.RedisService;
@ -34,10 +35,10 @@ public class DictUtils
*/ */
public static List<SysDictData> getDictCache(String key) public static List<SysDictData> getDictCache(String key)
{ {
Object cacheObj = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key)); JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj)) if (StringUtils.isNotNull(arrayCache))
{ {
return StringUtils.cast(cacheObj); return arrayCache.toList(SysDictData.class);
} }
return null; return null;
} }
@ -57,7 +58,7 @@ public class DictUtils
*/ */
public static void clearDictCache() public static void clearDictCache()
{ {
Collection<String> keys = SpringUtils.getBean(RedisService.class).keys(Constants.SYS_DICT_KEY + "*"); Collection<String> keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*");
SpringUtils.getBean(RedisService.class).deleteObject(keys); SpringUtils.getBean(RedisService.class).deleteObject(keys);
} }
@ -69,6 +70,6 @@ public class DictUtils
*/ */
public static String getCacheKey(String configKey) public static String getCacheKey(String configKey)
{ {
return Constants.SYS_DICT_KEY + configKey; return CacheConstants.SYS_DICT_KEY + configKey;
} }
} }

View File

@ -62,7 +62,7 @@ public class SecurityUtils
public static String getToken(HttpServletRequest request) public static String getToken(HttpServletRequest request)
{ {
// 从header获取token标识 // 从header获取token标识
String token = request.getHeader(TokenConstants.AUTHENTICATION); String token = request.getHeader(SecurityConstants.AUTHORIZATION_HEADER);
return replaceTokenPrefix(token); return replaceTokenPrefix(token);
} }

View File

@ -1,6 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.common.security.config.WebMvcConfig,\
com.ruoyi.common.security.service.TokenService,\
com.ruoyi.common.security.aspect.PreAuthorizeAspect,\
com.ruoyi.common.security.aspect.InnerAuthAspect,\
com.ruoyi.common.security.handler.GlobalExceptionHandler

View File

@ -0,0 +1,5 @@
com.ruoyi.common.security.config.WebMvcConfig
com.ruoyi.common.security.service.TokenService
com.ruoyi.common.security.aspect.PreAuthorizeAspect
com.ruoyi.common.security.aspect.InnerAuthAspect
com.ruoyi.common.security.handler.GlobalExceptionHandler

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