122 Commits

Author SHA1 Message Date
RuoYi
df0f7d16a4 添加菜单路由地址和名称的校验规则 2026-01-09 11:19:12 +08:00
RuoYi
a5ced3b531 优化防重提交间隔时间可自定义 2026-01-08 13:42:35 +08:00
RuoYi
2d9ce89b2e 修复Excel自定义格式样式污染问题 2026-01-06 13:55:05 +08:00
RuoYi
ec8e955955 copyright 2026 2026-01-05 15:10:29 +08:00
RuoYi
0398aa0333 将isAdmin方法统一到SecurityUtils 2026-01-05 15:10:16 +08:00
RuoYi
14063cd6ed 若依 3.6.7 2025-12-22 09:17:25 +08:00
RuoYi
a8b6799d8d 优化topbar顶部菜单样式 2025-12-18 14:46:55 +08:00
RuoYi
a492ebf41e 默认固定头部 2025-12-18 14:42:47 +08:00
RuoYi
8d6790b358 优化字典组件值宽松匹配 2025-12-16 16:42:25 +08:00
RuoYi
c763a0f356 升级fastjson到最新版2.0.60 2025-12-16 13:47:55 +08:00
RuoYi
227f62dbe2 升级commons.io到最新版本2.21.0 2025-12-16 13:47:39 +08:00
RuoYi
e5d494d018 升级druid到最新版本1.2.27 2025-12-16 13:47:17 +08:00
RuoYi
0f9e698fb5 菜单导航设置支持纯顶部 2025-12-16 13:03:25 +08:00
RuoYi
3d4c6f4fa1 优化数据权限控制逻辑,放开permission限制 2025-12-04 17:36:17 +08:00
RuoYi
40a52af8ee 优化代码 2025-12-04 16:51:23 +08:00
RuoYi
9e67041290 优化表单构建关闭页签销毁复制插件 2025-12-04 13:55:04 +08:00
RuoYi
c17ed8bb04 支持Excel导出对象的多个子列表 2025-12-03 11:26:41 +08:00
RuoYi
64e5288625 优化生成代码下载的zip文件名 2025-12-03 10:28:19 +08:00
RuoYi
afe8236b42 网页标题设置新增SET_TITLE方法 2025-12-02 19:31:12 +08:00
RuoYi
21ee628202 支持Excel导出对象的多个子列表 2025-12-02 19:14:14 +08:00
RuoYi
b54e00529a 登录/注册页面底部版权信息修改为读取配置 2025-12-02 15:34:40 +08:00
RuoYi
3f4484107a 修复v3时间控件between选择后清空报错问题 2025-12-02 15:00:49 +08:00
RuoYi
341c9a8851 修复表单构建移除所有控件后切换路由回来空白问题 2025-12-02 13:14:02 +08:00
RuoYi
81bfef9a3c 修复combo属性过多sheet出现的异常问题 2025-11-13 11:58:59 +08:00
RuoYi
7238dbb807 修复固定头部时出现的导航栏偏移问题 2025-09-04 20:06:41 +08:00
RuoYi
ff9068b9d4 文件支持防盗链配置 2025-09-02 13:27:08 +08:00
RuoYi
ea8351cce0 优化代码 2025-08-28 13:52:06 +08:00
RuoYi
8ef3b5490e 优化代码 2025-08-27 16:02:32 +08:00
RuoYi
1284f6763f 用户导入添加验证提示 2025-08-23 11:47:17 +08:00
RuoYi
eeb6303200 优化布局设置显示 2025-08-23 11:47:07 +08:00
RuoYi
513335d9db 修复用户归属部门无法修改为空问题 2025-08-21 15:00:54 +08:00
RuoYi
1a373f41e6 columns default value 2025-08-09 16:14:01 +08:00
RuoYi
e73aa3b497 显示列信息支持对象格式 2025-08-09 15:19:23 +08:00
RuoYi
d5d6b9789c 自动识别json对象白名单配置范围缩小 2025-08-09 15:18:37 +08:00
RuoYi
6b0bd81f56 添加新群号:112869560 2025-07-19 19:28:57 +08:00
RuoYi
0be3a0720d 优化定时任务包名白名单匹配方式 2025-06-20 11:56:39 +08:00
RuoYi
83e5f2e24d 优化Excel统计行数值的单元格样式显示 2025-06-19 14:54:12 +08:00
RuoYi
942df70c21 用户头像更换后移除旧头像文件 2025-06-06 19:38:36 +08:00
RuoYi
32cb5e8851 若依 3.6.6 2025-05-30 08:03:15 +08:00
若依
ffce2af11e !412 升级到springboot3后 HttpServletResponse的包名发生变化
Merge pull request !412 from coach-tam/N/A
2025-05-28 01:52:58 +00:00
coach-tam
aeb698985b 升级到springboot3后 HttpServletResponse的包名发生变化
Signed-off-by: coach-tam <yaorange2019@sina.com>
2025-05-28 01:44:11 +00:00
RuoYi
ec15604725 升级fastjson到最新版2.0.57 2025-05-26 11:17:18 +08:00
RuoYi
67642ed19a 注册账号设置默认密码最后更新时间 2025-05-26 11:17:06 +08:00
RuoYi
604345f72b 添加底部版权信息及开关 2025-05-24 14:34:05 +08:00
RuoYi
eb01cde0b1 添加页签图标显示开关功能 2025-05-23 14:58:02 +08:00
RuoYi
217119575d 账号密码支持自定义更新周期 2025-05-23 10:35:58 +08:00
RuoYi
86d5eae71f 初始密码支持自定义修改策略 2025-05-23 10:33:48 +08:00
RuoYi
aa72ac20d1 升级commons.io到最新版本2.19.0 2025-05-15 10:28:53 +08:00
RuoYi
b1e0418c77 delete eslint&vue-meta 2025-05-15 10:28:18 +08:00
RuoYi
8e32654d46 优化导航栏显示昵称&设置 2025-05-09 14:02:42 +08:00
RuoYi
c8c0127185 菜单搜索支持键盘选择&悬浮主题背景 2025-05-07 13:25:29 +08:00
RuoYi
46e75b4d7e 图片上传组件新增disabled属性 2025-05-06 19:15:04 +08:00
RuoYi
a735ed90f7 add columnName Drag 2025-05-06 14:54:22 +08:00
RuoYi
e64bb2d7be 修复上传组件被多次引用拖动仅对第一个有效的问题 2025-05-06 13:47:03 +08:00
RuoYi
496d6113c4 update icon 2025-05-06 11:09:46 +08:00
RuoYi
f871171d32 上传组件新增拖动排序属性 2025-04-30 10:31:53 +08:00
RuoYi
a36e19d88e 优化Excel匹配数值型.0结尾 2025-04-28 11:22:04 +08:00
RuoYi
235728fdb9 remove all semicolons 2025-04-27 11:56:31 +08:00
RuoYi
381077253d 使用Gateway CacheRequestBody代替CacheRequestFilter 2025-04-25 15:12:16 +08:00
RuoYi
5f3a93d12e 优化代码 2025-04-25 15:12:03 +08:00
RuoYi
e22323971e 富文本复制粘贴图片上传至url 2025-04-24 18:20:01 +08:00
RuoYi
f593d36745 update package.json 2025-04-24 18:19:44 +08:00
RuoYi
9978594069 优化低版本node无法启动的问题 2025-04-22 12:07:33 +08:00
RuoYi
9026c8e49e 优化代码 2025-04-22 12:07:27 +08:00
RuoYi
c359924d4e 显隐列组件支持全选/全不选 2025-04-21 15:30:44 +08:00
RuoYi
f8d726f966 优化菜单搜索查询页 2025-04-21 13:28:45 +08:00
RuoYi
cbdbc91784 支持文件&图片组件自定义地址&参数 2025-04-18 13:25:08 +08:00
RuoYi
3a61e8df5a 优化角色禁用不允许分配 2025-04-17 15:42:20 +08:00
RuoYi
9d242f0182 update status name 2025-04-17 15:42:03 +08:00
RuoYi
2afad16eba remove dev runjs 2025-03-18 16:04:35 +08:00
RuoYi
637a628cfc 登录页和注册页表头使用VUE_APP_TITLE配置值 2025-03-18 16:04:25 +08:00
RuoYi
785f3c3515 update handleTree 2025-03-14 16:14:24 +08:00
RuoYi
85dc2aef8f 优化代码 2025-03-11 12:55:20 +08:00
RuoYi
3a91cb47a4 修复actuator暴漏问题 2025-03-10 11:47:59 +08:00
RuoYi
7d611b754f 优化isAdmin方法,避免脱敏模块security依赖 2025-03-07 12:59:16 +08:00
RuoYi
6be79bd7d4 菜单管理新增路由名称 2025-03-06 11:09:28 +08:00
RuoYi
13942b41b2 优化顶部菜单搜索栏为多层级显示 2025-03-05 20:32:38 +08:00
RuoYi
583f653890 文件上传组件新增disabled属性&类型 2025-03-05 20:32:30 +08:00
RuoYi
9ebb230d66 优化导出Excel日期格式双击离开后与设定的格式不一致问题 2025-03-05 20:32:18 +08:00
RuoYi
65cc92286f 代码生成列表支持按时间排序 2025-03-05 20:31:10 +08:00
RuoYi
fe1badd9a6 优化空指针异常时无法获取错误信息问题 2025-03-05 20:30:52 +08:00
RuoYi
48830b1181 优化定时任务字符包含多个括号导致数据错误 2025-03-05 20:30:04 +08:00
RuoYi
4257ca91b2 优化代码 2025-03-05 20:28:38 +08:00
RuoYi
15b2502ffa update ry_config_20250224 2025-02-24 16:26:28 +08:00
RuoYi
eb035d179b add nacos2.5.0 sql 2025-02-18 08:42:57 +08:00
RuoYi
b959a91d26 copyright 2025 2025-01-07 10:58:41 +08:00
RuoYi
28377670bb 代码生成新增配置是否允许文件覆盖到本地 2024-12-25 16:40:33 +08:00
RuoYi
1215d5d474 优化导入带标题文件关闭清理 2024-12-25 16:37:26 +08:00
RuoYi
7b4fbf4e13 update sqlkeyword 2024-12-25 16:37:14 +08:00
RuoYi
eaeb8d759e 优化特殊字符密码修改失败问题 2024-12-17 14:40:29 +08:00
RuoYi
bba6433113 优化TopNav内链菜单点击没有高亮(IB8WHJ) 2024-12-17 14:39:49 +08:00
RuoYi
61a49b5951 优化菜单管理切换Mini布局错乱问题 2024-12-17 14:39:37 +08:00
RuoYi
8d631d1325 用户管理过滤掉已禁用部门 2024-12-11 11:52:50 +08:00
RuoYi
d302cdb324 修改主题样式本地读取 2024-12-10 16:43:28 +08:00
RuoYi
33af14461f 优化文件异常输入流未关闭的问题 2024-12-07 14:53:38 +08:00
RuoYi
cff2e611c5 白名单支持对通配符路径匹配 2024-12-07 14:53:07 +08:00
RuoYi
72bc8bfc53 Excel注解支持wrapText是否允许内容换行 2024-12-07 14:52:52 +08:00
RuoYi
4a6603d8b3 修复导出子列表对象只能在最后的问题 2024-12-07 14:52:31 +08:00
RuoYi
2b425e62e4 修复默认关闭Tags-Views时,内链页面打不开 2024-11-27 20:02:51 +08:00
RuoYi
a837f49291 修复TopNav无法正确获取active的问题 2024-11-27 20:02:40 +08:00
RuoYi
3a2e434a53 菜单面包屑导航支持多层级显示 2024-11-25 22:40:49 +08:00
RuoYi
08484eea75 优化代码 2024-11-25 22:40:21 +08:00
RuoYi
a5f3be78ec 分栏参数微调 2024-11-22 14:53:51 +08:00
RuoYi
0fc5c7199e 用户管理支持分栏拖动 2024-11-22 14:16:07 +08:00
RuoYi
1af0861a3b 优化代码 2024-11-22 14:15:50 +08:00
RuoYi
bea8f763bb update .env.staging 2024-11-22 14:15:13 +08:00
RuoYi
78d958ec8c 若依 3.6.5 2024-11-13 11:21:07 +08:00
RuoYi
101f7e3cf7 升级quill到最新版本2.0.2 2024-11-13 11:10:27 +08:00
RuoYi
b92fb20439 支持自定义显示Excel属性列 2024-11-07 22:48:35 +08:00
RuoYi
264d6e320e update pom.xml 2024-11-06 22:07:16 +08:00
RuoYi
1f0eb72a58 优化代码 2024-11-06 22:06:44 +08:00
RuoYi
eb2e089d57 优化无用户编号不校验数据权限 2024-11-05 16:45:33 +08:00
RuoYi
efdc96abb6 校检文件名是否包含特殊字符 2024-11-05 16:44:17 +08:00
RuoYi
64dc968949 优化身份证脱敏正则 2024-10-21 17:31:33 +08:00
RuoYi
dcc303a8d4 优化权限更新后同步缓存 2024-10-21 17:31:22 +08:00
RuoYi
cc0c6deb38 操作日志记录DELETE请求参数 2024-10-17 13:20:28 +08:00
RuoYi
c2157d7f2a 修改代码生成上级菜单字段类型 2024-10-17 13:20:06 +08:00
RuoYi
f6c8be3285 修复角色禁用权限不失效问题 2024-09-21 12:06:51 +08:00
RuoYi
4f8c2215b3 update ry_config 2024-09-14 12:52:24 +08:00
RuoYi
6f94f4d1e0 update ry_config 2024-09-02 20:30:38 +08:00
RuoYi
f2aad7a76c 优化提示 2024-09-02 20:26:00 +08:00
RuoYi
c50a2b4200 update springboot3 2024-08-29 21:00:35 +08:00
220 changed files with 4160 additions and 3904 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.6.5</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.7</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.6.5-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.7-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>
@@ -126,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群](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群 [![加入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_20240629.sql ./mysql/db cp ../sql/ry_20250523.sql ./mysql/db
cp ../sql/ry_config_20250224.sql ./mysql/db cp ../sql/ry_config_20250902.sql ./mysql/db
# copy html # copy html
echo "begin copy html " echo "begin copy html "

95
pom.xml
View File

@@ -6,54 +6,40 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.7</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.6.5</ruoyi.version> <ruoyi.version>3.6.7</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>17</java.version>
<spring-boot.version>2.7.18</spring-boot.version> <spring-boot.version>3.3.5</spring-boot.version>
<spring-cloud.version>2021.0.9</spring-cloud.version> <spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2023.0.1.2</spring-cloud-alibaba.version>
<spring-boot-admin.version>2.7.16</spring-boot-admin.version> <spring-boot-admin.version>3.3.5</spring-boot-admin.version>
<tobato.version>1.27.2</tobato.version> <mybatis-spring.version>3.0.3</mybatis-spring.version>
<kaptcha.version>2.3.3</kaptcha.version> <kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version> <pagehelper.boot.version>2.1.0</pagehelper.boot.version>
<druid.version>1.2.23</druid.version> <druid.version>1.2.27</druid.version>
<dynamic-ds.version>4.3.1</dynamic-ds.version> <dynamic-ds.version>4.3.1</dynamic-ds.version>
<commons.io.version>2.13.0</commons.io.version> <commons.io.version>2.21.0</commons.io.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>2.0.53</fastjson.version> <fastjson.version>2.0.60</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>
<springdoc.version>1.6.9</springdoc.version> <springdoc.version>2.6.0</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version -->
<tomcat.version>9.0.98</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>
@@ -81,49 +67,10 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- 覆盖logback的依赖配置-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- 覆盖tomcat的依赖配置-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
<!-- FastDFS 分布式文件系统 -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>${tobato.version}</version>
</dependency>
<!-- Springdoc webmvc 依赖配置 --> <!-- Springdoc webmvc 依赖配置 -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>
@@ -139,6 +86,18 @@
<groupId>com.github.pagehelper</groupId> <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version> <version>${pagehelper.boot.version}</version>
<exclusions>
<exclusion>
<artifactId>mybatis-spring</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency> </dependency>
<!-- io常用工具类 --> <!-- io常用工具类 -->
@@ -279,7 +238,9 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration> <configuration>
<parameters>true</parameters>
<source>${java.version}</source> <source>${java.version}</source>
<target>${java.version}</target> <target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding> <encoding>${project.build.sourceEncoding}</encoding>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.7</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.6.5</version> <version>3.6.7</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

@@ -2,10 +2,10 @@ package com.ruoyi.system.api.domain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.constraints.Email; import jakarta.validation.constraints.Email;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.api.domain; package com.ruoyi.system.api.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;

View File

@@ -1,8 +1,8 @@
package com.ruoyi.system.api.domain; package com.ruoyi.system.api.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;

View File

@@ -252,8 +252,4 @@ public class SysOperLog extends BaseEntity
{ {
this.costTime = costTime; this.costTime = costTime;
} }
public String toLogString(){
return "";
}
} }

View File

@@ -1,9 +1,9 @@
package com.ruoyi.system.api.domain; package com.ruoyi.system.api.domain;
import java.util.Set; import java.util.Set;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;

View File

@@ -2,7 +2,7 @@ package com.ruoyi.system.api.domain;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import javax.validation.constraints.*; import jakarta.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;
@@ -56,8 +56,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 +71,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),
@@ -111,11 +114,6 @@ public class SysUser extends BaseEntity
} }
public boolean isAdmin() public boolean isAdmin()
{
return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{ {
return UserConstants.isAdmin(userId); return UserConstants.isAdmin(userId);
} }
@@ -248,6 +246,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;
@@ -297,6 +305,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)
@@ -313,6 +322,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

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

View File

@@ -1,6 +1,6 @@
package com.ruoyi.auth.controller; package com.ruoyi.auth.controller;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;

View File

@@ -143,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);

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.7</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-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -53,12 +53,24 @@
<artifactId>pagehelper-spring-boot-starter</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- Mybatis Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<!-- Hibernate Validator --> <!-- Hibernate Validator -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<!-- Spring Aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Jackson --> <!-- Jackson -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
@@ -81,6 +93,7 @@
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency> </dependency>
<!-- Apache Lang3 --> <!-- Apache Lang3 -->
@@ -103,8 +116,8 @@
<!-- Java Servlet --> <!-- Java Servlet -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>jakarta.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>jakarta.servlet-api</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -51,7 +51,8 @@ public @interface Excel
/** /**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/ */
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; @SuppressWarnings("deprecation")
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/** /**
* 导出时在excel中每个列的高度 * 导出时在excel中每个列的高度

View File

@@ -87,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";
/** /**
* 当前记录起始索引 * 当前记录起始索引
*/ */
@@ -120,7 +130,7 @@ public class Constants
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" }; public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
/** /**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)

View File

@@ -3,7 +3,7 @@ package com.ruoyi.common.core.exception.file;
import java.util.Arrays; import java.util.Arrays;
/** /**
* 文件上传异常类 * 文件上传无效扩展名异常类
* *
* @author ruoyi * @author ruoyi
*/ */

View File

@@ -136,6 +136,14 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算时间差 * 计算时间差
* *

View File

@@ -8,10 +8,10 @@ import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;

View File

@@ -1,9 +1,9 @@
package com.ruoyi.common.core.utils.bean; package com.ruoyi.common.core.utils.bean;
import java.util.Set; import java.util.Set;
import javax.validation.ConstraintViolation; import jakarta.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException; import jakarta.validation.ConstraintViolationException;
import javax.validation.Validator; import jakarta.validation.Validator;
/** /**
* bean对象属性验证 * bean对象属性验证

View File

@@ -8,8 +8,8 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@@ -114,20 +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(resource)); return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl));
} }
/** /**

View File

@@ -2,7 +2,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 jakarta.servlet.http.HttpServletRequest;
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;

View File

@@ -19,7 +19,7 @@ import java.util.List;
import java.util.Map; 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 jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils; 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.commons.lang3.reflect.FieldUtils;
@@ -73,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 = { "=", "-", "+", "@" };
@@ -145,23 +147,18 @@ public class ExcelUtil<T>
/** /**
* 对象的子列表方法 * 对象的子列表方法
*/ */
private Method subMethod; private Map<String, Method> subMethods;
/** /**
* 对象的子列表属性 * 对象的子列表属性
*/ */
private List<Field> subFields; 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");
/** /**
* 实体对象 * 实体对象
*/ */
@@ -228,7 +225,10 @@ public class ExcelUtil<T>
int titleLastCol = this.fields.size() - 1; int titleLastCol = this.fields.size() - 1;
if (isSubList()) if (isSubList())
{ {
titleLastCol = titleLastCol + subFields.size() - 1; 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);
@@ -248,16 +248,17 @@ public class ExcelUtil<T>
{ {
Row subRow = sheet.createRow(rownum); Row subRow = sheet.createRow(rownum);
int column = 0; int column = 0;
int subFieldSize = subFields != null ? subFields.size() : 0;
for (Object[] objects : fields) for (Object[] objects : fields)
{ {
Field field = (Field) objects[0]; Field field = (Field) objects[0];
Excel attr = (Excel) objects[1]; Excel attr = (Excel) objects[1];
CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
Cell cell = subRow.createCell(column); Cell cell = subRow.createCell(column);
cell.setCellValue(attr.name()); cell.setCellValue(attr.name());
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); cell.setCellStyle(cellStyle);
int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
if (subFieldSize > 1) if (subFieldSize > 1)
{ {
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
@@ -269,7 +270,7 @@ public class ExcelUtil<T>
{ {
Cell cell = subRow.createCell(column++); Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name()); cell.setCellValue(attr.name());
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); cell.setCellStyle(cellStyle);
} }
} }
rownum++; rownum++;
@@ -341,7 +342,11 @@ public class ExcelUtil<T>
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))
@@ -349,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();
@@ -381,7 +382,7 @@ public class ExcelUtil<T>
Object val = this.getCellValue(row, entry.getKey()); Object val = this.getCellValue(row, entry.getKey());
// 如果不存在实例则新建. // 如果不存在实例则新建.
entity = (entity == null ? clazz.newInstance() : entity); entity = (entity == null ? clazz.getDeclaredConstructor().newInstance() : entity);
// 从map中得到对应列的field. // 从map中得到对应列的field.
Field field = (Field) entry.getValue()[0]; Field field = (Field) entry.getValue()[0];
Excel attr = (Excel) entry.getValue()[1]; Excel attr = (Excel) entry.getValue()[1];
@@ -390,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");
} }
@@ -565,7 +566,8 @@ public class ExcelUtil<T>
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
for (Field subField : subFields) List<Field> currentSubFields = subFieldsMap.get(field.getName());
for (Field subField : currentSubFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++); this.createHeadCell(subExcel, row, column++);
@@ -578,7 +580,7 @@ public class ExcelUtil<T>
} }
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index, row); fillExcelData(index);
addStatisticsRow(); addStatisticsRow();
} }
} }
@@ -588,10 +590,9 @@ public class ExcelUtil<T>
* 填充excel数据 * 填充excel数据
* *
* @param index 序号 * @param index 序号
* @param row 单元格行
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void fillExcelData(int index, Row row) 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());
@@ -599,7 +600,7 @@ public class ExcelUtil<T>
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
row = sheet.createRow(currentRowNum); 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); int maxSubListSize = getCurrentMaxSubListSize(vo);
@@ -612,6 +613,7 @@ public class ExcelUtil<T>
try try
{ {
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel); Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
List<Field> currentSubFields = subFieldsMap.get(field.getName());
if (subList != null && !subList.isEmpty()) if (subList != null && !subList.isEmpty())
{ {
int subIndex = 0; int subIndex = 0;
@@ -624,15 +626,15 @@ public class ExcelUtil<T>
} }
int subColumn = column; int subColumn = column;
for (Field subField : subFields) for (Field subField : currentSubFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++); addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
} }
subIndex++; subIndex++;
} }
column += subFields.size();
} }
column += currentSubFields.size();
} }
catch (Exception e) catch (Exception e)
{ {
@@ -724,6 +726,7 @@ public class ExcelUtil<T>
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);
@@ -972,7 +975,8 @@ public class ExcelUtil<T>
/** /**
* 添加单元格 * 添加单元格
*/ */
public Cell addCell(Excel attr, Row row, T vo, Field field, int column) @SuppressWarnings("deprecation")
public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
{ {
Cell cell = null; Cell cell = null;
try try
@@ -984,7 +988,7 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge())
{ {
if (subMergedLastRowNum >= subMergedFirstRowNum) if (subMergedLastRowNum >= subMergedFirstRowNum)
{ {
@@ -1000,7 +1004,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.setCellStyle(createCellStyle(cell.getCellStyle(), 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))
@@ -1030,6 +1034,21 @@ public class ExcelUtil<T>
return cell; return cell;
} }
/**
* 使用自定义格式,同时避免样式污染
*
* @param cellStyle 从此样式复制
* @param format 格式匹配的字符串
* @return 格式化后CellStyle对象
*/
private CellStyle createCellStyle(CellStyle cellStyle, String format)
{
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(cellStyle);
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
return style;
}
/** /**
* 设置 POI XSSFSheet 单元格提示或选择框 * 设置 POI XSSFSheet 单元格提示或选择框
* *
@@ -1081,18 +1100,36 @@ public class ExcelUtil<T>
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
{ {
String hideSheetName = "combo_" + firstCol + "_" + endCol; String hideSheetName = "combo_" + firstCol + "_" + endCol;
Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 Sheet hideSheet = null;
for (int i = 0; i < textlist.length; i++) String hideSheetDataName = hideSheetName + "_data";
Name name = wb.getName(hideSheetDataName);
if (name != null)
{ {
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); // 名称已存在尝试从名称的引用中找到sheet名称
String refersToFormula = name.getRefersToFormula();
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
{
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
hideSheet = wb.getSheet(sheetNameFromFormula);
}
} }
// 创建名称,可被其他单元格引用
Name name = wb.createName(); if (hideSheet == null)
name.setNameName(hideSheetName + "_data"); {
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); 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(); DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容 // 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象 // 数据有效性对象
@@ -1130,7 +1167,7 @@ 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("=");
@@ -1167,7 +1204,7 @@ 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("=");
@@ -1204,7 +1241,7 @@ public class ExcelUtil<T>
{ {
try try
{ {
Object instance = excel.handler().newInstance(); Object instance = excel.handler().getDeclaredConstructor().newInstance();
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class }); Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb); value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
} }
@@ -1255,7 +1292,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();
} }
@@ -1330,6 +1367,8 @@ 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)) if (StringUtils.isNotEmpty(includeFields))
@@ -1377,10 +1416,11 @@ public class ExcelUtil<T>
} }
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
subMethod = getSubMethod(field.getName(), clazz); String fieldName = field.getName();
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
ParameterizedType pt = (ParameterizedType) field.getGenericType(); ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0]; Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
} }
} }
@@ -1449,7 +1489,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);
} }
} }
@@ -1574,7 +1615,7 @@ public class ExcelUtil<T>
*/ */
public boolean isSubList() public boolean isSubList()
{ {
return StringUtils.isNotNull(subFields) && subFields.size() > 0; return !StringUtils.isEmpty(subFieldsMap);
} }
/** /**
@@ -1582,24 +1623,32 @@ public class ExcelUtil<T>
*/ */
public boolean isSubListValue(T vo) public boolean isSubListValue(T vo)
{ {
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0;
} }
/** /**
* 获取集合的值 * 获取集合的值
*/ */
public Collection<?> getListCellValue(Object obj) public int getListCellValue(Object obj)
{ {
Object value; Collection<?> value;
int max = 0;
try try
{ {
value = subMethod.invoke(obj, new Object[] {}); for (String s : subMethods.keySet())
{
value = (Collection<?>) subMethods.get(s).invoke(obj);
if (value.size() > max)
{
max = value.size();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
return new ArrayList<Object>(); return 0;
} }
return (Collection<?>) value; return max;
} }
/** /**

View File

@@ -310,7 +310,8 @@ public class ReflectUtils
/** /**
* 改变private/protected的方法为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。 * 改变private/protected的方法为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/ */
public static void makeAccessible(Method method) @SuppressWarnings("deprecation")
public static void makeAccessible(Method method)
{ {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) && !method.isAccessible())
@@ -322,7 +323,8 @@ public class ReflectUtils
/** /**
* 改变private/protected的成员变量为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。 * 改变private/protected的成员变量为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/ */
public static void makeAccessible(Field field) @SuppressWarnings("deprecation")
public static void makeAccessible(Field field)
{ {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())

View File

@@ -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

@@ -1,7 +1,7 @@
package com.ruoyi.common.core.xss; package com.ruoyi.common.core.xss;
import javax.validation.Constraint; import jakarta.validation.Constraint;
import javax.validation.Payload; import jakarta.validation.Payload;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;

View File

@@ -2,8 +2,8 @@ package com.ruoyi.common.core.xss;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.validation.ConstraintValidator; import jakarta.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext; import jakarta.validation.ConstraintValidatorContext;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
/** /**

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.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -94,7 +94,7 @@ public class DataScopeAspect
List<String> conditions = new ArrayList<String>(); List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>(); List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> { user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) 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())); scopeCustomIds.add(Convert.toStr(role.getRoleId()));
} }
@@ -107,7 +107,7 @@ public class DataScopeAspect
{ {
continue; continue;
} }
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
continue; continue;
} }

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.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -20,14 +20,14 @@
<!-- Druid --> <!-- Druid -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version> <version>${druid.version}</version>
</dependency> </dependency>
<!-- Dynamic DataSource --> <!-- Dynamic DataSource -->
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>${dynamic-ds.version}</version> <version>${dynamic-ds.version}</version>
</dependency> </dependency>

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.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -2,8 +2,8 @@ package com.ruoyi.common.log.aspect;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils; 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;
@@ -48,6 +48,9 @@ public class LogAspect
/** 计算操作消耗时间 */ /** 计算操作消耗时间 */
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time"); private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
/** 参数最大长度限制 */
private static final int PARAM_MAX_LENGTH = 2000;
@Autowired @Autowired
private AsyncLogService asyncLogService; private AsyncLogService asyncLogService;
@@ -166,16 +169,16 @@ public class LogAspect
*/ */
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
{ {
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
String requestMethod = operLog.getRequestMethod(); String requestMethod = operLog.getRequestMethod();
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
{ {
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(StringUtils.substring(params, 0, 2000)); operLog.setOperParam(params);
} }
else else
{ {
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000)); operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH));
} }
} }
@@ -184,7 +187,7 @@ public class LogAspect
*/ */
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{ {
String params = ""; StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (Object o : paramsArray) for (Object o : paramsArray)
@@ -194,15 +197,20 @@ public class LogAspect
try try
{ {
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params += jsonObj.toString() + " "; params.append(jsonObj).append(" ");
if (params.length() >= PARAM_MAX_LENGTH)
{
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
}
} }
catch (Exception e) catch (Exception e)
{ {
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
} }
} }
} }
} }
return params.trim(); return params.toString();
} }
/** /**

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.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -18,6 +18,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration @Configuration
@EnableCaching @EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class) @AutoConfigureBefore(RedisAutoConfiguration.class)
@SuppressWarnings("deprecation")
public class RedisConfig extends CachingConfigurerSupport public class RedisConfig extends CachingConfigurerSupport
{ {
@Bean @Bean

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.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

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.6.5</version> <version>3.6.7</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 // 执行原有逻辑
{ return joinPoint.proceed();
// 执行原有逻辑
Object obj = joinPoint.proceed();
return obj;
}
catch (Throwable e)
{
throw e;
}
} }
/** /**

View File

@@ -1,7 +1,7 @@
package com.ruoyi.common.security.feign; package com.ruoyi.common.security.feign;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;

View File

@@ -1,6 +1,6 @@
package com.ruoyi.common.security.handler; package com.ruoyi.common.security.handler;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.common.security.interceptor; package com.ruoyi.common.security.interceptor;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor; import org.springframework.web.servlet.AsyncHandlerInterceptor;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;

View File

@@ -3,7 +3,7 @@ package com.ruoyi.common.security.service;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
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;

View File

@@ -1,13 +1,14 @@
package com.ruoyi.common.security.utils; package com.ruoyi.common.security.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants; import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder; import com.ruoyi.common.core.context.SecurityContextHolder;
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.system.api.model.LoginUser; import com.ruoyi.system.api.model.LoginUser;
import jakarta.servlet.http.HttpServletRequest;
/** /**
* 权限获取工具类 * 权限获取工具类
@@ -79,6 +80,16 @@ public class SecurityUtils
return token; return token;
} }
/**
* 是否为管理员
*
* @return 结果
*/
public static boolean isAdmin()
{
return isAdmin(getUserId());
}
/** /**
* 是否为管理员 * 是否为管理员
* *
@@ -87,7 +98,7 @@ public class SecurityUtils
*/ */
public static boolean isAdmin(Long userId) public static boolean isAdmin(Long userId)
{ {
return userId != null && 1L == userId; return UserConstants.isAdmin(userId);
} }
/** /**

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.6.5</version> <version>3.6.7</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-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -26,7 +26,7 @@
<!-- SpringDoc webmvc --> <!-- SpringDoc webmvc -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -2,6 +2,8 @@ package com.ruoyi.common.swagger.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springdoc.core.configuration.SpringDocConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -19,6 +21,7 @@ import io.swagger.v3.oas.models.servers.Server;
* *
* @author ruoyi * @author ruoyi
*/ */
@AutoConfiguration(before = SpringDocConfiguration.class)
@EnableConfigurationProperties(SpringDocProperties.class) @EnableConfigurationProperties(SpringDocProperties.class)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
public class SpringDocAutoConfiguration public class SpringDocAutoConfiguration

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -79,7 +79,7 @@
<!-- Springdoc --> <!-- Springdoc -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId> <artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>${springdoc.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>

View File

@@ -2,8 +2,8 @@ package com.ruoyi.gateway.config;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springdoc.core.AbstractSwaggerUiConfigProperties; import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.SwaggerUiConfigProperties; import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

View File

@@ -1,87 +0,0 @@
package com.ruoyi.gateway.filter;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 获取body请求数据解决流不能重复读取问题
*
* @author ruoyi
*/
@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{
public CacheRequestFilter()
{
super(Config.class);
}
@Override
public String name()
{
return "CacheRequestFilter";
}
@Override
public GatewayFilter apply(Config config)
{
CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
Integer order = config.getOrder();
if (order == null)
{
return cacheRequestGatewayFilter;
}
return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
}
public static class CacheRequestGatewayFilter implements GatewayFilter
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
// GET DELETE 不过滤
HttpMethod method = exchange.getRequest().getMethod();
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE)
{
return chain.filter(exchange);
}
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
if (serverHttpRequest == exchange.getRequest())
{
return chain.filter(exchange);
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
});
}
}
@Override
public List<String> shortcutFieldOrder()
{
return Collections.singletonList("order");
}
static class Config
{
private Integer order;
public Integer getOrder()
{
return order;
}
public void setOrder(Integer order)
{
this.order = order;
}
}
}

View File

@@ -64,6 +64,7 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
}; };
} }
@SuppressWarnings("deprecation")
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest)
{ {
// 获取请求体 // 获取请求体

View File

@@ -3,7 +3,7 @@ package com.ruoyi.gateway.service.impl;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.7</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-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -46,12 +46,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- Minio --> <!-- Minio -->
<dependency> <dependency>

View File

@@ -0,0 +1,46 @@
package com.ruoyi.file.config;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.file.filter.RefererFilter;
/**
* Filter配置
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Value("${referer.allowed-domains}")
private String allowedDomains;
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
public FilterRegistrationBean refererFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new RefererFilter());
registration.addUrlPatterns(localFilePrefix + "/*");
registration.setName("refererFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("allowedDomains", allowedDomains);
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@@ -3,10 +3,12 @@ package com.ruoyi.file.controller;
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.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService; import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile; import com.ruoyi.system.api.domain.SysFile;
@@ -45,4 +47,26 @@ public class SysFileController
return R.fail(e.getMessage()); return R.fail(e.getMessage());
} }
} }
}
/**
* 文件删除请求
*/
@DeleteMapping("delete")
public R<Boolean> delete(String fileUrl)
{
try
{
if (!FileUtils.validateFilePath(fileUrl))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl));
}
sysFileService.deleteFile(fileUrl);
return R.ok();
}
catch (Exception e)
{
log.error("删除文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -0,0 +1,77 @@
package com.ruoyi.file.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* 防盗链过滤器
*
* @author ruoyi
*/
public class RefererFilter implements Filter
{
/**
* 允许的域名列表
*/
public List<String> allowedDomains;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String domains = filterConfig.getInitParameter("allowedDomains");
this.allowedDomains = Arrays.asList(domains.split(","));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String referer = req.getHeader("Referer");
// 如果Referer为空拒绝访问
if (referer == null || referer.isEmpty())
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
return;
}
// 检查Referer是否在允许的域名列表中
boolean allowed = false;
for (String domain : allowedDomains)
{
if (referer.contains(domain))
{
allowed = true;
break;
}
}
// 根据检查结果决定是否放行
if (allowed)
{
chain.doFilter(request, response);
}
else
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
}
}
@Override
public void destroy()
{
}
}

View File

@@ -1,56 +0,0 @@
package com.ruoyi.file.service;
import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
/**
* FastDFS 文件存储
*
* @author ruoyi
*/
@Service
public class FastDfsSysFileServiceImpl implements ISysFileService
{
/**
* 域名或本机访问地址
*/
@Value("${fdfs.domain}")
public String domain;
@Autowired
private FastFileStorageClient storageClient;
/**
* FastDfs文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
InputStream inputStream = null;
try
{
inputStream = file.getInputStream();
StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(), FileTypeUtils.getExtension(file), null);
return domain + "/" + storePath.getFullPath();
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to upload file", e);
}
finally
{
IoUtils.closeQuietly(inputStream);
}
}
}

View File

@@ -17,4 +17,12 @@ public interface ISysFileService
* @throws Exception * @throws Exception
*/ */
public String uploadFile(MultipartFile file) throws Exception; public String uploadFile(MultipartFile file) throws Exception;
/**
* 文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
public void deleteFile(String fileUrl) throws Exception;
} }

View File

@@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
/** /**
@@ -47,4 +49,17 @@ public class LocalSysFileServiceImpl implements ISysFileService
String url = domain + localFilePrefix + name; String url = domain + localFilePrefix + name;
return url; return url;
} }
/**
* 本地文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
FileUtils.deleteFile(localFilePath + localFile);
}
} }

View File

@@ -5,10 +5,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils; import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.config.MinioConfig; import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient; import io.minio.MinioClient;
import io.minio.PutObjectArgs; import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
/** /**
* Minio 文件存储 * Minio 文件存储
@@ -57,4 +59,24 @@ public class MinioSysFileServiceImpl implements ISysFileService
IoUtils.closeQuietly(inputStream); IoUtils.closeQuietly(inputStream);
} }
} }
/**
* Minio文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName());
client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build());
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to delete file", e);
}
}
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -57,7 +57,7 @@ public class GenController extends BaseController
} }
/** /**
* 修改代码生成业务 * 获取代码生成信息
*/ */
@RequiresPermissions("tool:gen:query") @RequiresPermissions("tool:gen:query")
@GetMapping(value = "/{tableId}") @GetMapping(value = "/{tableId}")

View File

@@ -1,8 +1,8 @@
package com.ruoyi.gen.domain; package com.ruoyi.gen.domain;
import java.util.List; import java.util.List;
import javax.validation.Valid; import jakarta.validation.Valid;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.core.constant.GenConstants; import com.ruoyi.common.core.constant.GenConstants;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;

View File

@@ -1,6 +1,6 @@
package com.ruoyi.gen.domain; package com.ruoyi.gen.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
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;

View File

@@ -2,7 +2,7 @@ package ${packageName}.controller;
import java.util.List; import java.util.List;
import java.io.IOException; import java.io.IOException;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;

View File

@@ -283,9 +283,9 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -346,18 +346,18 @@ export default {
#end #end
#end #end
} }
}; }
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true; this.loading = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {}; this.queryParams.params = {}
#break #break
#end #end
#end #end
@@ -365,40 +365,40 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]; this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]; this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}"); this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
this.loading = false; this.loading = false
}); })
}, },
/** 转换${functionName}数据结构 */ /** 转换${functionName}数据结构 */
normalizer(node) { normalizer(node) {
if (node.children && !node.children.length) { if (node.children && !node.children.length) {
delete node.children; delete node.children
} }
return { return {
id: node.${treeCode}, id: node.${treeCode},
label: node.${treeName}, label: node.${treeName},
children: node.children children: node.children
}; }
}, },
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
getTreeselect() { getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
this.${businessName}Options = []; this.${businessName}Options = []
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }; const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}"); data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
this.${businessName}Options.push(data); this.${businessName}Options.push(data)
}); })
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false
this.reset(); this.reset()
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -410,61 +410,61 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
this.resetForm("form"); this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.getList(); this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = []; this.daterange${AttrName} = []
#end #end
#end #end
this.resetForm("queryForm"); this.resetForm("queryForm")
this.handleQuery(); this.handleQuery()
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd(row) { handleAdd(row) {
this.reset(); this.reset()
this.getTreeselect(); this.getTreeselect()
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
this.form.${treeParentCode} = row.${treeCode}; this.form.${treeParentCode} = row.${treeCode}
} else { } else {
this.form.${treeParentCode} = 0; this.form.${treeParentCode} = 0
} }
this.open = true; this.open = true
this.title = "添加${functionName}"; this.title = "添加${functionName}"
}, },
/** 展开/折叠操作 */ /** 展开/折叠操作 */
toggleExpandAll() { toggleExpandAll() {
this.refreshTable = false; this.refreshTable = false
this.isExpandAll = !this.isExpandAll; this.isExpandAll = !this.isExpandAll
this.$nextTick(() => { this.$nextTick(() => {
this.refreshTable = true; this.refreshTable = true
}); })
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset()
this.getTreeselect(); this.getTreeselect()
if (row != null) { if (row != null) {
this.form.${treeParentCode} = row.${treeParentCode}; this.form.${treeParentCode} = row.${treeParentCode}
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
this.form = response.data; this.form = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(","); this.form.$column.javaField = this.form.${column.javaField}.split(",")
#end #end
#end #end
this.open = true; this.open = true
this.title = "修改${functionName}"; this.title = "修改${functionName}"
}); })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -472,34 +472,34 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(","); this.form.$column.javaField = this.form.${column.javaField}.join(",")
#end #end
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功"); this.#[[$modal]]#.msgSuccess("修改成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功"); this.#[[$modal]]#.msgSuccess("新增成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
} }
}); })
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}); return del${BusinessName}(row.${pkColumn.javaField})
}).then(() => { }).then(() => {
this.getList(); this.getList()
this.#[[$modal]]#.msgSuccess("删除成功"); this.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
} }
}; }
</script> </script>

View File

@@ -353,7 +353,7 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -423,18 +423,18 @@ export default {
#end #end
#end #end
} }
}; }
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true; this.loading = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {}; this.queryParams.params = {}
#break #break
#end #end
#end #end
@@ -442,21 +442,21 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]; this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]; this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = response.rows; this.${businessName}List = response.rows
this.total = response.total; this.total = response.total
this.loading = false; this.loading = false
}); })
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false
this.reset(); this.reset()
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -468,27 +468,27 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
#if($table.sub) #if($table.sub)
this.${subclassName}List = []; this.${subclassName}List = []
#end #end
this.resetForm("form"); this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1
this.getList(); this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = []; this.daterange${AttrName} = []
#end #end
#end #end
this.resetForm("queryForm"); this.resetForm("queryForm")
this.handleQuery(); this.handleQuery()
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
@@ -498,27 +498,27 @@ export default {
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset(); this.reset()
this.open = true; this.open = true
this.title = "添加${functionName}"; this.title = "添加${functionName}"
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset()
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
get${BusinessName}(${pkColumn.javaField}).then(response => { get${BusinessName}(${pkColumn.javaField}).then(response => {
this.form = response.data; this.form = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(","); this.form.$column.javaField = this.form.${column.javaField}.split(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.${subclassName}List = response.data.${subclassName}List; this.${subclassName}List = response.data.${subclassName}List
#end #end
this.open = true; this.open = true
this.title = "修改${functionName}"; this.title = "修改${functionName}"
}); })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -526,64 +526,64 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(","); this.form.$column.javaField = this.form.${column.javaField}.join(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.form.${subclassName}List = this.${subclassName}List; this.form.${subclassName}List = this.${subclassName}List
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功"); this.#[[$modal]]#.msgSuccess("修改成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功"); this.#[[$modal]]#.msgSuccess("新增成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
} }
}); })
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids; const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s); return del${BusinessName}(${pkColumn.javaField}s)
}).then(() => { }).then(() => {
this.getList(); this.getList()
this.#[[$modal]]#.msgSuccess("删除成功"); this.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
}, },
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
row${subClassName}Index({ row, rowIndex }) { row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1; row.index = rowIndex + 1
}, },
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
handleAdd${subClassName}() { handleAdd${subClassName}() {
let obj = {}; let obj = {}
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = ""; obj.$column.javaField = ""
#end #end
#end #end
this.${subclassName}List.push(obj); this.${subclassName}List.push(obj)
}, },
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
handleDelete${subClassName}() { handleDelete${subClassName}() {
if (this.checked${subClassName}.length == 0) { if (this.checked${subClassName}.length == 0) {
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据"); this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
} else { } else {
const ${subclassName}List = this.${subclassName}List; const ${subclassName}List = this.${subclassName}List
const checked${subClassName} = this.checked${subClassName}; const checked${subClassName} = this.checked${subClassName}
this.${subclassName}List = ${subclassName}List.filter(function(item) { this.${subclassName}List = ${subclassName}List.filter(function(item) {
return checked${subClassName}.indexOf(item.index) == -1 return checked${subClassName}.indexOf(item.index) == -1
}); })
} }
}, },
/** 复选框选中数据 */ /** 复选框选中数据 */
@@ -598,5 +598,5 @@ export default {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
} }
}; }
</script> </script>

View File

@@ -271,26 +271,26 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance()
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}); const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
#end #end
const ${businessName}List = ref([]); const ${businessName}List = ref([])
const ${businessName}Options = ref([]); const ${businessName}Options = ref([])
const open = ref(false); const open = ref(false)
const loading = ref(true); const loading = ref(true)
const showSearch = ref(true); const showSearch = ref(true)
const title = ref(""); const title = ref("")
const isExpandAll = ref(true); const isExpandAll = ref(true)
const refreshTable = ref(true); const refreshTable = ref(true)
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]); const daterange${AttrName} = ref([])
#end #end
#end #end
@@ -318,48 +318,48 @@ const data = reactive({
#end #end
#end #end
} }
}); })
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data)
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true; loading.value = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {}; queryParams.value.params = {}
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) { if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]; queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]; queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}"); ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
loading.value = false; loading.value = false
}); })
} }
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
function getTreeselect() { function getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
${businessName}Options.value = []; ${businessName}Options.value = []
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }; const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}"); data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
${businessName}Options.value.push(data); ${businessName}Options.value.push(data)
}); })
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false; open.value = false
reset(); reset()
} }
// 表单重置 // 表单重置
@@ -372,13 +372,13 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
proxy.resetForm("${businessName}Ref"); proxy.resetForm("${businessName}Ref")
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
getList(); getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -386,52 +386,52 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = []; daterange${AttrName}.value = []
#end #end
#end #end
proxy.resetForm("queryRef"); proxy.resetForm("queryRef")
handleQuery(); handleQuery()
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd(row) { function handleAdd(row) {
reset(); reset()
getTreeselect(); getTreeselect()
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode}; form.value.${treeParentCode} = row.${treeCode}
} else { } else {
form.value.${treeParentCode} = 0; form.value.${treeParentCode} = 0
} }
open.value = true; open.value = true
title.value = "添加${functionName}"; title.value = "添加${functionName}"
} }
/** 展开/折叠操作 */ /** 展开/折叠操作 */
function toggleExpandAll() { function toggleExpandAll() {
refreshTable.value = false; refreshTable.value = false
isExpandAll.value = !isExpandAll.value; isExpandAll.value = !isExpandAll.value
nextTick(() => { nextTick(() => {
refreshTable.value = true; refreshTable.value = true
}); })
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
async function handleUpdate(row) { async function handleUpdate(row) {
reset(); reset()
await getTreeselect(); await getTreeselect()
if (row != null) { if (row != null) {
form.value.${treeParentCode} = row.${treeParentCode}; form.value.${treeParentCode} = row.${treeParentCode}
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
form.value = response.data; form.value = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(","); form.value.$column.javaField = form.value.${column.javaField}.split(",")
#end #end
#end #end
open.value = true; open.value = true
title.value = "修改${functionName}"; title.value = "修改${functionName}"
}); })
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -440,35 +440,35 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(","); form.value.$column.javaField = form.value.${column.javaField}.join(",")
#end #end
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功"); proxy.#[[$modal]]#.msgSuccess("修改成功")
open.value = false; open.value = false
getList(); getList()
}); })
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功"); proxy.#[[$modal]]#.msgSuccess("新增成功")
open.value = false; open.value = false
getList(); getList()
}); })
} }
} }
}); })
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}); return del${BusinessName}(row.${pkColumn.javaField})
}).then(() => { }).then(() => {
getList(); getList()
proxy.#[[$modal]]#.msgSuccess("删除成功"); proxy.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
getList(); getList()
</script> </script>

View File

@@ -343,33 +343,33 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance()
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}); const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
#end #end
const ${businessName}List = ref([]); const ${businessName}List = ref([])
#if($table.sub) #if($table.sub)
const ${subclassName}List = ref([]); const ${subclassName}List = ref([])
#end #end
const open = ref(false); const open = ref(false)
const loading = ref(true); const loading = ref(true)
const showSearch = ref(true); const showSearch = ref(true)
const ids = ref([]); const ids = ref([])
#if($table.sub) #if($table.sub)
const checked${subClassName} = ref([]); const checked${subClassName} = ref([])
#end #end
const single = ref(true); const single = ref(true)
const multiple = ref(true); const multiple = ref(true)
const total = ref(0); const total = ref(0)
const title = ref(""); const title = ref("")
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]); const daterange${AttrName} = ref([])
#end #end
#end #end
@@ -399,39 +399,39 @@ const data = reactive({
#end #end
#end #end
} }
}); })
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data)
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true; loading.value = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {}; queryParams.value.params = {}
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) { if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]; queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]; queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = response.rows; ${businessName}List.value = response.rows
total.value = response.total; total.value = response.total
loading.value = false; loading.value = false
}); })
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false; open.value = false
reset(); reset()
} }
// 表单重置 // 表单重置
@@ -444,17 +444,17 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
#if($table.sub) #if($table.sub)
${subclassName}List.value = []; ${subclassName}List.value = []
#end #end
proxy.resetForm("${businessName}Ref"); proxy.resetForm("${businessName}Ref")
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1
getList(); getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -462,44 +462,44 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = []; daterange${AttrName}.value = []
#end #end
#end #end
proxy.resetForm("queryRef"); proxy.resetForm("queryRef")
handleQuery(); handleQuery()
} }
// 多选框选中数据 // 多选框选中数据
function handleSelectionChange(selection) { function handleSelectionChange(selection) {
ids.value = selection.map(item => item.${pkColumn.javaField}); ids.value = selection.map(item => item.${pkColumn.javaField})
single.value = selection.length != 1; single.value = selection.length != 1
multiple.value = !selection.length; multiple.value = !selection.length
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd() { function handleAdd() {
reset(); reset()
open.value = true; open.value = true
title.value = "添加${functionName}"; title.value = "添加${functionName}"
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
function handleUpdate(row) { function handleUpdate(row) {
reset(); reset()
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(_${pkColumn.javaField}).then(response => { get${BusinessName}(_${pkColumn.javaField}).then(response => {
form.value = response.data; form.value = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(","); form.value.$column.javaField = form.value.${column.javaField}.split(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
${subclassName}List.value = response.data.${subclassName}List; ${subclassName}List.value = response.data.${subclassName}List
#end #end
open.value = true; open.value = true
title.value = "修改${functionName}"; title.value = "修改${functionName}"
}); })
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -508,68 +508,68 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(","); form.value.$column.javaField = form.value.${column.javaField}.join(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
form.value.${subclassName}List = ${subclassName}List.value; form.value.${subclassName}List = ${subclassName}List.value
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功"); proxy.#[[$modal]]#.msgSuccess("修改成功")
open.value = false; open.value = false
getList(); getList()
}); })
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功"); proxy.#[[$modal]]#.msgSuccess("新增成功")
open.value = false; open.value = false
getList(); getList()
}); })
} }
} }
}); })
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value; const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(_${pkColumn.javaField}s); return del${BusinessName}(_${pkColumn.javaField}s)
}).then(() => { }).then(() => {
getList(); getList()
proxy.#[[$modal]]#.msgSuccess("删除成功"); proxy.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
function row${subClassName}Index({ row, rowIndex }) { function row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1; row.index = rowIndex + 1
} }
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
function handleAdd${subClassName}() { function handleAdd${subClassName}() {
let obj = {}; let obj = {}
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = ""; obj.$column.javaField = ""
#end #end
#end #end
${subclassName}List.value.push(obj); ${subclassName}List.value.push(obj)
} }
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
function handleDelete${subClassName}() { function handleDelete${subClassName}() {
if (checked${subClassName}.value.length == 0) { if (checked${subClassName}.value.length == 0) {
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据"); proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
} else { } else {
const ${subclassName}s = ${subclassName}List.value; const ${subclassName}s = ${subclassName}List.value
const checked${subClassName}s = checked${subClassName}.value; const checked${subClassName}s = checked${subClassName}.value
${subclassName}List.value = ${subclassName}s.filter(function(item) { ${subclassName}List.value = ${subclassName}s.filter(function(item) {
return checked${subClassName}s.indexOf(item.index) == -1 return checked${subClassName}s.indexOf(item.index) == -1
}); })
} }
} }
@@ -586,5 +586,5 @@ function handleExport() {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
getList(); getList()
</script> </script>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,7 +1,7 @@
package com.ruoyi.job.controller; package com.ruoyi.job.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
@@ -178,7 +178,7 @@ public class SysJobController extends BaseController
@RequiresPermissions("monitor:job:remove") @RequiresPermissions("monitor:job:remove")
@Log(title = "定时任务", businessType = BusinessType.DELETE) @Log(title = "定时任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{jobIds}") @DeleteMapping("/{jobIds}")
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException
{ {
jobService.deleteJobByIds(jobIds); jobService.deleteJobByIds(jobIds);
return success(); return success();

View File

@@ -1,7 +1,7 @@
package com.ruoyi.job.controller; package com.ruoyi.job.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

View File

@@ -1,8 +1,8 @@
package com.ruoyi.job.domain; package com.ruoyi.job.domain;
import java.util.Date; import java.util.Date;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import jakarta.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;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.job.service; package com.ruoyi.job.service;
import java.util.List; import java.util.List;
import javax.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import org.quartz.JobDataMap; import org.quartz.JobDataMap;
import org.quartz.JobKey; import org.quartz.JobKey;
import org.quartz.Scheduler; import org.quartz.Scheduler;

View File

@@ -3,7 +3,6 @@ package com.ruoyi.job.util;
import java.util.Date; import java.util.Date;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.constant.ScheduleConstants; import com.ruoyi.common.core.constant.ScheduleConstants;
@@ -30,7 +29,7 @@ public abstract class AbstractQuartzJob implements Job
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>(); private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
@Override @Override
public void execute(JobExecutionContext context) throws JobExecutionException public void execute(JobExecutionContext context)
{ {
SysJob sysJob = new SysJob(); SysJob sysJob = new SysJob();
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));

View File

@@ -131,11 +131,11 @@ public class ScheduleUtils
int count = StringUtils.countMatches(packageName, "."); int count = StringUtils.countMatches(packageName, ".");
if (count > 1) if (count > 1)
{ {
return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); return StringUtils.startsWithAny(invokeTarget, Constants.JOB_WHITELIST_STR);
} }
Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
String beanPackageName = obj.getClass().getPackage().getName(); String beanPackageName = obj.getClass().getPackage().getName();
return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR) return StringUtils.startsWithAny(beanPackageName, Constants.JOB_WHITELIST_STR)
&& !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR); && !StringUtils.startsWithAny(beanPackageName, Constants.JOB_ERROR_STR);
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.7</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;

View File

@@ -2,7 +2,7 @@ package com.ruoyi.system.controller;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

View File

@@ -97,6 +97,10 @@ public class SysMenuController extends BaseController
{ {
return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} }
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setCreateBy(SecurityUtils.getUsername()); menu.setCreateBy(SecurityUtils.getUsername());
return toAjax(menuService.insertMenu(menu)); return toAjax(menuService.insertMenu(menu));
} }
@@ -121,6 +125,10 @@ public class SysMenuController extends BaseController
{ {
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
} }
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setUpdateBy(SecurityUtils.getUsername()); menu.setUpdateBy(SecurityUtils.getUsername());
return toAjax(menuService.updateMenu(menu)); return toAjax(menuService.updateMenu(menu));
} }

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;

View File

@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
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.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils; import com.ruoyi.common.core.utils.file.MimeTypeUtils;
@@ -99,7 +100,7 @@ public class SysProfileController extends BaseController
String oldPassword = params.get("oldPassword"); String oldPassword = params.get("oldPassword");
String newPassword = params.get("newPassword"); String newPassword = params.get("newPassword");
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String userName = loginUser.getUsername(); Long userId = loginUser.getUserid();
String password = loginUser.getSysUser().getPassword(); String password = loginUser.getSysUser().getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password)) if (!SecurityUtils.matchesPassword(oldPassword, password))
{ {
@@ -110,9 +111,10 @@ public class SysProfileController extends BaseController
return error("新密码不能与旧密码相同"); return error("新密码不能与旧密码相同");
} }
newPassword = SecurityUtils.encryptPassword(newPassword); newPassword = SecurityUtils.encryptPassword(newPassword);
if (userService.resetUserPwd(userName, newPassword) > 0) if (userService.resetUserPwd(userId, newPassword) > 0)
{ {
// 更新缓存用户密码 // 更新缓存用户密码&密码最后更新时间
loginUser.getSysUser().setPwdUpdateDate(DateUtils.getNowDate());
loginUser.getSysUser().setPassword(newPassword); loginUser.getSysUser().setPassword(newPassword);
tokenService.setLoginUser(loginUser); tokenService.setLoginUser(loginUser);
return success(); return success();
@@ -141,8 +143,13 @@ public class SysProfileController extends BaseController
return error("文件服务异常,请联系管理员"); return error("文件服务异常,请联系管理员");
} }
String url = fileResult.getData().getUrl(); String url = fileResult.getData().getUrl();
if (userService.updateUserAvatar(loginUser.getUsername(), url)) if (userService.updateUserAvatar(loginUser.getUserid(), url))
{ {
String oldAvatarUrl = loginUser.getSysUser().getAvatar();
if (StringUtils.isNotEmpty(oldAvatarUrl))
{
remoteFileService.delete(oldAvatarUrl);
}
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", url); ajax.put("imgUrl", url);
// 更新缓存用户头像 // 更新缓存用户头像

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;

View File

@@ -1,10 +1,11 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -18,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
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.poi.ExcelUtil; import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.controller.BaseController;
@@ -160,7 +163,7 @@ public class SysUserController extends BaseController
@PutMapping("/recordlogin") @PutMapping("/recordlogin")
public R<Boolean> recordlogin(@RequestBody SysUser sysUser) public R<Boolean> recordlogin(@RequestBody SysUser sysUser)
{ {
return R.ok(userService.updateUserProfile(sysUser)); return R.ok(userService.updateLoginInfo(sysUser));
} }
/** /**
@@ -186,9 +189,35 @@ public class SysUserController extends BaseController
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", roles); ajax.put("roles", roles);
ajax.put("permissions", permissions); ajax.put("permissions", permissions);
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
return ajax; return ajax;
} }
// 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate)
{
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
}
// 检查密码是否过期
public boolean passwordIsExpiration(Date pwdUpdateDate)
{
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
if (passwordValidateDays != null && passwordValidateDays > 0)
{
if (StringUtils.isNull(pwdUpdateDate))
{
// 如果从未修改过初始密码,直接提醒过期
return true;
}
Date nowDate = DateUtils.getNowDate();
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
return false;
}
/** /**
* 根据用户编号获取详细信息 * 根据用户编号获取详细信息
*/ */
@@ -206,7 +235,7 @@ public class SysUserController extends BaseController
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
} }
List<SysRole> roles = roleService.selectRoleAll(); List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll()); ajax.put("posts", postService.selectPostAll());
return ajax; return ajax;
} }
@@ -321,7 +350,7 @@ public class SysUserController extends BaseController
SysUser user = userService.selectUserById(userId); SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId); List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax; return ajax;
} }

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.domain; package com.ruoyi.system.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;

View File

@@ -2,9 +2,9 @@ package com.ruoyi.system.domain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.domain; package com.ruoyi.system.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;

View File

@@ -1,8 +1,8 @@
package com.ruoyi.system.domain; package com.ruoyi.system.domain;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.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;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;

View File

@@ -1,45 +0,0 @@
package com.ruoyi.system.log;
import javax.servlet.http.HttpServletRequest;
/**
* @Auther : qzy
* @Date: 2024/1/24 16:55
**/
public class AccessAddressUtils {
/**
* 获取用户真实IP地址不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
* 参考文章: http://developer.51cto.com/art/201111/305181.htm
*
* 可是如果通过了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP值究竟哪个才是真正的用户端的真实IP呢
* 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
*
* 如X-Forwarded-For192.168.1.110, 192.168.1.120, 192.168.1.130,
* 192.168.1.100
*
* 用户真实IP为 192.168.1.110
* @param request
* @return
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

View File

@@ -1,54 +0,0 @@
package com.ruoyi.system.log;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* 日志记录所有请求 工具类
* @Auther : qzy
* @Date: 2024/1/24 16:55
**/
public final class LoggerUtils {
public static final String LOGGER_RETURN = "LOGGER_RETURN";
private LoggerUtils() {}
/**
* 获取客户端ip地址
* @param request
* @return
*/
public static String getCliectIp(HttpServletRequest request)
{
String ip = request.getHeader("x-forwarded-for");
if (ip == null || Objects.equals(ip.trim(), "") || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || Objects.equals(ip.trim(), "") || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || Objects.equals(ip.trim(), "") || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 多个路由时取第一个非unknown的ip
final String[] arr = ip.split(",");
for (final String str : arr) {
if (!"unknown".equalsIgnoreCase(str)) {
ip = str;
break;
}
}
return ip;
}
/**
* 判断是否为ajax请求
* @param request
* @return
*/
public static String getRequestType(HttpServletRequest request) {
return request.getHeader("X-Requested-With");
}
}

View File

@@ -1,142 +0,0 @@
package com.ruoyi.system.log.aop;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.system.log.AccessAddressUtils;
import com.ruoyi.system.log.LoggerUtils;
import com.ruoyi.system.log.dto.LoggerEntity;
import org.apache.commons.lang3.RandomUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
/**
* @author : qzy
* @since : 2024/1/24 16:36
* <p style='color:yellow'>
* 通用请求日志打印处理类,方便联调/测试,生产环境视情况可选择是否保留
*
* </p>
**/
@Aspect
@Component
public class WebRequestLogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(WebRequestLogAspect.class);
private final ThreadLocal<LoggerEntity> threadLocal = new ThreadLocal<>();
private final ThreadLocal<Long> startTimeLocal = new ThreadLocal<>();
@Pointcut("within(com.ruoyi.*.controller.*)")
public void webRequestLog() {
}
@Before("webRequestLog()")
public void doBefore(JoinPoint joinPoint) {
try {
// 接收到请求,记录请求内容
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
// 防止拦截的不是接口层,获取不到请求数据的情况
threadLocal.remove();
return;
}
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = attributes.getRequest();
//处理特殊请求,直接返回
// if (request.getRequestURI().contains("admin/sysLog")) {
// threadLocal.remove();
// return;
// }
String method = request.getMethod();
String params;
String post_code = "POST";
if (post_code.equals(method)) {
Object[] paramsArray = joinPoint.getArgs();
params = argsArrayToString(paramsArray);
} else {
//获取请求参数信息
params = JSON.toJSONString(request.getParameterMap());
}
LoggerEntity optLog = new LoggerEntity();
//设置请求方法
optLog.setId(RandomUtils.nextLong());
optLog.setMethodCode(request.getMethod());
//设置请求类型json|普通请求)
optLog.setTypeCode(LoggerUtils.getRequestType(request));
//设置请求参数内容json字符串
optLog.setParamData(params);
//设置请求地址
optLog.setUri(request.getRequestURI());
//设置sessionId
optLog.setSessionId(request.getSession().getId());
//设置调用的java类
optLog.setJavaBean(joinPoint.getSignature().getDeclaringTypeName());
//设置调用的java方法
optLog.setJavaMethod(joinPoint.getSignature().getName());
// optLog.setParamData(params);
//设置调用方ip
optLog.setClientIp(AccessAddressUtils.getIpAddress(request));
threadLocal.set(optLog);
startTimeLocal.set(System.currentTimeMillis());
LOGGER.info(optLog.toLogStr());
} catch (Exception e) {
LOGGER.error("***操作请求日志记录失败doBefore()***", e);
}
}
@AfterReturning(returning = "result", pointcut = "webRequestLog()")
public void doAfterReturning(Object result) {
// 处理完请求,返回内容
if (threadLocal.get() == null) {
return;
}
LoggerEntity optLog = threadLocal.get();
Long startTime = startTimeLocal.get();
optLog.setReturnData(JSON.toJSONString(result));
optLog.setTimeConsuming((int) (System.currentTimeMillis() - startTime));
LOGGER.info(optLog.toLogStr());
threadLocal.remove();
startTimeLocal.remove();
}
/**
* 请求参数拼装
* @return String
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null) {
for (Object o : paramsArray) {
if (o instanceof MultipartFile || o instanceof MultipartFile[]) {
// 当导入文件时,不打印输出二进制
params.append("上传文件 ");
} else {
try {
Object jsonObj = JSON.toJSON(o);
params.append(jsonObj.toString()).append(" ");
} catch (Exception e) {
LOGGER.debug("参数json解析异常,{}", e.getMessage());
}
}
}
}
return params.toString().trim();
}
}

View File

@@ -1,216 +0,0 @@
package com.ruoyi.system.log.dto;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* 日志记录所有请求 实体类
* @Auther : qzy
* @Date: 2024/1/24 16:55
**/
public class LoggerEntity implements Serializable {
/**
* 编号
*/
private Long id;
/**
* 客户端请求ip
*/
private String clientIp;
/**
* 客户端请求路径
*/
private String uri;
/**
* 终端请求方式,普通请求,ajax请求
*/
private String type;
/**
* 请求方式method,post,get等
*/
private String method;
/**
* 请求参数内容,json
*/
private String paramData;
/**
* 请求接口唯一session标识
*/
private String sessionId;
/**
* 请求时间
*/
private Timestamp time;
/**
* 接口返回时间
*/
private String returnTime;
/**
* 接口返回数据json
*/
private String returnData;
/**
* 请求时httpStatusCode代码200,400,404等
*/
private String httpStatusCode;
/**
* 请求耗时秒单位
*/
private int timeConsuming;
private String javaBean;
private String javaMethod;
private String operaAdmin;
private String operaSource;
private String typeCode;
private String methodCode;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getParamData() {
return paramData;
}
public void setParamData(String paramData) {
this.paramData = paramData;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public Timestamp getTime() {
return time;
}
public void setTime(Timestamp time) {
this.time = time;
}
public String getReturnTime() {
return returnTime;
}
public void setReturnTime(String returnTime) {
this.returnTime = returnTime;
}
public String getReturnData() {
return returnData;
}
public void setReturnData(String returnData) {
this.returnData = returnData;
}
public String getHttpStatusCode() {
return httpStatusCode;
}
public void setHttpStatusCode(String httpStatusCode) {
this.httpStatusCode = httpStatusCode;
}
public int getTimeConsuming() {
return timeConsuming;
}
public void setTimeConsuming(int timeConsuming) {
this.timeConsuming = timeConsuming;
}
public void setJavaBean(String javaBean) {
this.javaBean = javaBean;
}
public String getJavaBean() {
return javaBean;
}
public void setJavaMethod(String javaMethod) {
this.javaMethod = javaMethod;
}
public String getJavaMethod() {
return javaMethod;
}
public void setOperaAdmin(String operaAdmin) {
this.operaAdmin = operaAdmin;
}
public String getOperaAdmin() {
return operaAdmin;
}
public void setOperaSource(String operaSource) {
this.operaSource = operaSource;
}
public String getOperaSource() {
return operaSource;
}
public void setTypeCode(String typeCode) {
this.typeCode = typeCode;
}
public String getTypeCode() {
return typeCode;
}
public void setMethodCode(String methodCode) {
this.methodCode = methodCode;
}
public String getMethodCode() {
return methodCode;
}
public String toLogStr(){
return String.format("\n==>请求IP{%s},\n==>请求路径:{%s} - {%s},\n==>方法名:{%s},\n==>入参:{%s},\n==>出参:{%s}", this.clientIp, this.methodCode, this.uri, this.javaMethod, this.paramData,this.returnData);
}
}

View File

@@ -1,4 +0,0 @@
/**
* 统一请求日志处理工具
*/
package com.ruoyi.system.log;

View File

@@ -122,4 +122,13 @@ public interface SysMenuMapper
* @return 结果 * @return 结果
*/ */
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
/**
* 根据路由路径或名称查询菜单信息(用于唯一性校验)
*
* @param path 路由地址
* @param routeName 路由名称
* @return 匹配的菜单列表
*/
public List<SysMenu> selectMenusByPathOrRouteName(@Param("path") String path, @Param("routeName") String routeName);
} }

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