115 Commits

Author SHA1 Message Date
9d02f8f7e7 若依 v4.7.6 2022-12-16 08:50:57 +08:00
70205922fc 优化代码 2022-12-13 15:45:13 +08:00
f3d1f0afe2 修改参数键名时移除前缓存配置 2022-12-13 15:09:38 +08:00
7ee6ad8aec 升级pagehelper到最新版1.4.6 2022-12-13 14:23:20 +08:00
4ff9afac23 升级oshi到最新版本6.4.0 2022-12-13 14:21:58 +08:00
167970e5c4 优化SQL关键字检查防止注入 2022-12-13 13:17:17 +08:00
29395be19a !432 优化deleteFile方法返回值,接受File.delete的false返回值
Merge pull request !432 from 岳林/master
2022-12-12 05:48:17 +00:00
da01f093f8 优化deleteFile方法返回值,接受File.delete的false返回值 2022-12-12 09:41:38 +08:00
f53515eb70 升级druid到最新版本1.2.15 2022-12-07 11:55:23 +08:00
84dde0dcf2 升级kaptcha到最新版2.3.3 2022-12-07 10:58:07 +08:00
df1c283335 定时任务违规的字符 2022-12-03 11:32:41 +08:00
faa4bfaef3 升级oshi到最新版本6.3.2 2022-12-01 11:49:25 +08:00
eef7ef6544 !426 升级shiro到最新版本1.10.1
Merge pull request !426 from Hacker/N/A
2022-11-25 11:05:20 +00:00
22d42048ab 升级shiro到最新版本1.10.1
Signed-off-by: Hacker <721806280@qq.com>
2022-11-24 07:31:40 +00:00
e5b905c455 优化用户管理重置时取消部门选择(I621OJ) 2022-11-21 13:39:09 +08:00
c64f027e66 兼容Excel下拉框内容过多无法显示的问题(I61HCG) 2022-11-21 11:13:02 +08:00
96934ca139 修复操作日志类型多选导出不生效问题(I617FW) 2022-11-15 13:30:43 +08:00
f4c763c84d 升级druid到最新版本1.2.14 2022-11-14 11:47:57 +08:00
8cd0d9f366 忽略不必要的属性数据返回 2022-11-12 11:57:08 +08:00
6a7f727f70 优化导出对象的子列表为空会出现[]问题(I60904) 2022-11-11 10:35:32 +08:00
62381f0472 修复sheet超出最大行数异常问题 2022-11-07 11:27:12 +08:00
2952337f15 !420 update ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java.
Merge pull request !420 from chenjh/N/A
2022-11-07 03:22:59 +00:00
c719be609a update ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionFactory.java.
ServletUtils.getRequest()应改request,可能为空

Signed-off-by: chenjh <asgard2023@outlook.com>
2022-11-06 14:26:47 +00:00
6253e41658 升级oshi到最新版本6.3.0 2022-10-28 21:31:14 +08:00
bd0e574268 优化select2搜索下拉后校验必填样式问题(I5VZY0) 2022-10-21 09:48:13 +08:00
6e176c807c 升级bootstrap-fileinput到最新版本5.5.2 2022-10-20 19:12:26 +08:00
2bdf12b1e1 升级shiro到最新版本1.10.0 2022-10-13 10:09:10 +08:00
67f2ba2aa9 修复导出包含空子列表数据异常的问题 2022-10-10 09:00:10 +08:00
c105f44eb9 优化树形表格层级显示(I5TQ87) 2022-10-09 21:17:20 +08:00
e23a6919af 优化topnav页缺少的样式右括号 2022-10-09 21:17:04 +08:00
b362e58646 R isError and isSuccess static 2022-10-09 21:16:52 +08:00
db3e571af0 优化代码生成同步后字典值NULL问题 2022-09-28 20:58:11 +08:00
52fe19e933 导入更新用户数据前校验数据权限 2022-09-28 20:58:02 +08:00
7b3ab45ecc 添加新群号:185760789 2022-09-28 10:56:36 +08:00
e337f685bc 修改用户登录账号重复验证 2022-09-18 11:25:03 +08:00
13287e02eb 修复关闭父页签后提交无法跳转的问题(I5QBMO) 2022-09-12 10:34:00 +08:00
d4a33eab94 优化代码 2022-09-09 10:09:56 +08:00
0ca327f538 若依 v4.7.5 2022-09-05 09:42:15 +08:00
31bd27fcf0 升级jquery到最新版3.6.1 2022-09-03 09:22:34 +08:00
dcfc062c01 修复用户分配角色大于默认页数丢失问题(I5OJA8) 2022-09-02 10:19:32 +08:00
daa8286804 AjaxResult错误消息结果类型的判断 2022-09-02 10:19:22 +08:00
5a3714e9bc 优化横向菜单下激活菜单样式 2022-08-27 11:54:15 +08:00
abe1f0d63e 定时任务支持执行父类方法 2022-08-27 11:54:06 +08:00
c95cb70af3 优化多角色数据权限匹配规则 2022-08-22 19:43:27 +08:00
47bd3c4c10 页签创建标题优先data-title属性(I4MC5L) 2022-08-22 19:41:08 +08:00
1c8f55c2c1 新增示例(进度条) 2022-08-20 18:52:26 +08:00
0f9558a825 自动设置切换多个树表格实例配置 2022-08-14 18:34:10 +08:00
8a4d37e975 菜单配置刷新时Tab页签切换时刷新 2022-08-14 10:32:24 +08:00
7fbabe1a8e 升级oshi到最新版本6.2.2 2022-08-14 09:19:19 +08:00
53cd4867df 修复树表onLoadSuccess不生效的问题 2022-08-10 13:07:28 +08:00
7aa4872cb9 优化导出对象的子列表判断条件 2022-08-10 12:47:46 +08:00
8fcc548d34 优化excel/scale属性导出单元格数值类型 2022-08-09 08:01:47 +08:00
d318b719fc Excel支持导出对象的子列表方法 2022-08-07 18:19:27 +08:00
d6db5963d5 数据逻辑删除不进行唯一验证 2022-08-03 15:54:58 +08:00
d5f4bba084 新增主子表提交校验示例 2022-08-02 12:09:11 +08:00
960dee7756 增加对AjaxResult消息结果类型的判断 2022-08-02 12:08:18 +08:00
08f775da4b 优化任务过期不执行调度 2022-07-29 20:07:29 +08:00
2a0fcdea21 升级layui到最新版本v2.7.5 2022-07-28 19:54:55 +08:00
3f0a34e20f 自定义数据权限不排除重复 2022-07-26 14:43:09 +08:00
289161b8c6 升级pagehelper到最新版1.4.3 2022-07-22 14:53:25 +08:00
47b51fe965 支持自定义隐藏Excel属性列 2022-07-21 13:51:09 +08:00
0c0efc9455 Excel注解支持backgroundColor属性设置背景颜色 2022-07-20 09:32:11 +08:00
dd86447176 优化多个相同角色数据导致权限SQL重复问题 2022-07-19 15:36:01 +08:00
3427223da2 升级oshi到最新版本6.2.1 2022-07-14 16:16:28 +08:00
1959b02220 升级shiro到最新版本1.9.1 2022-06-29 19:52:38 +08:00
acf8ea428f 修改错误命名属性 2022-06-24 23:09:44 +08:00
6e476e40af 新增内容编码/解码方便插件集成使用 2022-06-22 17:46:07 +08:00
25d07b11cc !395 修复导入导出时,当某字段类型为字典类型或解析类型时,如果有分隔符时无法正确解析的问题
Merge pull request !395 from jinyangaction/master
2022-06-22 09:20:38 +00:00
36013e6139 修复导入导出时,当某字段类型为字典类型或解析类型时,如果有分隔符时无法正确解析的问题 2022-06-20 22:23:05 +08:00
87d3c9a93c 升级druid到最新版本1.2.11 2022-06-14 11:30:24 +08:00
d1b3f4f397 优化druid开启wall过滤器出现的异常问题 2022-06-13 21:21:28 +08:00
5c5961f1b4 释放焦点,防止打开后按回车反复弹出(I5AA4V) 2022-06-08 19:52:07 +08:00
e932a7ead1 若依 v4.7.4 2022-06-01 08:21:04 +08:00
20db92ecf5 修复代码生成拖拽多次出现的排序不正确问题 2022-05-31 09:46:51 +08:00
e1c855b091 升级spring-boot到最新版本2.5.14 2022-05-26 11:05:19 +08:00
693498b877 添加新群号:213650505 2022-05-25 11:01:55 +08:00
0ef403d785 升级fastjson到最新版1.2.83 2022-05-24 09:20:26 +08:00
d8b2a9a905 用户头像上传格式限制 2022-05-22 12:44:40 +08:00
6df2609d1a 修复客户端分页序号方法显示错误问题 2022-05-22 11:10:12 +08:00
608f05b21b 接口使用泛型使其看到响应属性字段 2022-05-20 10:54:16 +08:00
8145485cff !385 update ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java.
Merge pull request !385 from np/N/A
2022-05-20 02:48:54 +00:00
7506ac77cb !384 【轻量级PR】新增SpringUtils.getRequiredProperty,以静态方式获取配置文件中的值
Merge pull request !384 from 阿超/master
2022-05-20 02:48:48 +00:00
5142e2d668 升级oshi到最新版本6.1.6 2022-05-11 09:55:07 +08:00
ef1cf982e3 优化excel创建表格样式 2022-05-09 16:57:05 +08:00
np
12d550d2b6 update ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java.
优化Switch case
2022-05-06 02:13:00 +00:00
2304f95b13 新增SpringUtils.getRequiredProperty,以静态方式获取配置文件中的值 2022-05-04 22:38:03 +08:00
a4be143104 升级spring-boot到最新版本2.5.13 2022-04-30 16:38:27 +08:00
0209ed0326 修改显示顺序orderNum类型为整型 2022-04-25 10:23:17 +08:00
55846c5658 Excel注解支持color字体颜色 2022-04-23 20:28:09 +08:00
799815c273 表格冻结列阴影效果显示 2022-04-23 20:27:57 +08:00
baa689b098 树表格操作时保留ajaxParams初始参数 2022-04-22 10:04:01 +08:00
e4bc44115a 设置分页参数默认值 2022-04-17 10:18:56 +08:00
53bb1da7a1 优化主子表单删方法 2022-04-17 10:18:19 +08:00
977ceb562e 新增获取不带后缀文件名称方法 2022-04-17 10:17:47 +08:00
0264da8d7c 主子表操作列新增单个删除 2022-04-16 21:42:30 +08:00
94e23ec0f8 检查定时任务bean所在包名是否为白名单配置 2022-04-16 21:42:09 +08:00
7610e138dc 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线) 2022-04-16 21:41:24 +08:00
b04c6833a3 升级shiro到最新版本1.9.0 2022-04-14 19:00:03 +08:00
035c326071 修复Excel注解prompt/combo同时使用不生效问题 2022-04-03 18:23:21 +08:00
e7660d94c9 用户缓存信息添加部门ancestors祖级列表 2022-04-03 18:22:11 +08:00
5f996472e1 修复URL类型回退键被禁止问题 2022-04-03 18:19:44 +08:00
7cbdc0eb8e 优化菜单侧边栏滚动条尺寸及颜色 2022-04-03 18:19:02 +08:00
615aa58bea 升级spring-boot到最新版本2.5.12 防止RCE漏洞 2022-04-02 10:05:49 +08:00
de7e2f1bfc 新增清理分页的线程变量方法 2022-03-31 11:52:39 +08:00
41bf76a49f 升级spring-boot到最新版本2.5.11 2022-03-30 10:47:27 +08:00
2a2744a1bf 升级fastjson到最新版1.2.80 2022-03-30 10:47:15 +08:00
757c0eebaf 优化IP地址获取到多个的问题 2022-03-27 11:31:48 +08:00
f60cb25245 优化导出excel单元格验证,包含变更为开头.防止正常内容被替换 2022-03-27 11:08:58 +08:00
199eb3f191 添加新群号:139845794 2022-03-24 09:48:37 +08:00
c1de1113c4 修复初始化多表格处理回调函数时获取的表格配置不一致的问题。 2022-03-22 20:40:20 +08:00
19803715be 自定义ShiroFilterFactoryBean防止中文请求被拦截 2022-03-17 19:53:16 +08:00
d60d0425bc 优化导出数据LocalDateTime类型无数据问题 2022-03-15 14:38:32 +08:00
28387c46e2 文件上传兼容Weblogic环境 2022-03-09 10:01:11 +08:00
6e06a6a9e8 修复导入Excel时字典字段类型为Long转义为空问题 2022-03-05 08:39:01 +08:00
9a60c27785 修复表格打印组件不识别多层对象属性值问题(I4V7YV) 2022-03-02 19:31:40 +08:00
121 changed files with 2569 additions and 1099 deletions

View File

@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-dd77653d7c9f197dd9d93684f3c8dcfbab6.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.3</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.6</h1>
<h4 align="center">基于SpringBoot开发的轻量级Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi/stargazers"><img src="https://gitee.com/y_project/RuoYi/badge/star.svg?theme=gvp"></a>
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.7.3-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.7.6-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
@ -99,4 +99,4 @@
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/已满-339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc) [![加入QQ群](https://img.shields.io/badge/已满-130035985-blue.svg)](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [![加入QQ群](https://img.shields.io/badge/已满-143151071-blue.svg)](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [![加入QQ群](https://img.shields.io/badge/已满-158781320-blue.svg)](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [![加入QQ群](https://img.shields.io/badge/已满-201531282-blue.svg)](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [![加入QQ群](https://img.shields.io/badge/已满-101526938-blue.svg)](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [![加入QQ群](https://img.shields.io/badge/已满-264355400-blue.svg)](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [![加入QQ群](https://img.shields.io/badge/298522656-blue.svg)](https://jq.qq.com/?_wv=1027&k=540WfdEr)
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/已满-339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc) [![加入QQ群](https://img.shields.io/badge/已满-130035985-blue.svg)](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [![加入QQ群](https://img.shields.io/badge/已满-143151071-blue.svg)](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [![加入QQ群](https://img.shields.io/badge/已满-158781320-blue.svg)](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [![加入QQ群](https://img.shields.io/badge/已满-201531282-blue.svg)](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [![加入QQ群](https://img.shields.io/badge/已满-101526938-blue.svg)](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [![加入QQ群](https://img.shields.io/badge/已满-264355400-blue.svg)](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [![加入QQ群](https://img.shields.io/badge/已满-298522656-blue.svg)](https://jq.qq.com/?_wv=1027&k=540WfdEr) [![加入QQ群](https://img.shields.io/badge/已满-139845794-blue.svg)](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [![加入QQ群](https://img.shields.io/badge/185760789-blue.svg)](https://jq.qq.com/?_wv=1027&k=Cqd66IKe)

41
pom.xml
View File

@ -5,29 +5,27 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>4.7.3</version>
<version>4.7.6</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>4.7.3</ruoyi.version>
<ruoyi.version>4.7.6</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<shiro.version>1.8.0</shiro.version>
<shiro.version>1.10.1</shiro.version>
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
<druid.version>1.2.8</druid.version>
<druid.version>1.2.15</druid.version>
<bitwalker.version>1.21</bitwalker.version>
<kaptcha.version>2.3.2</kaptcha.version>
<kaptcha.version>2.3.3</kaptcha.version>
<swagger.version>3.0.0</swagger.version>
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
<pagehelper.boot.version>1.4.1</pagehelper.boot.version>
<fastjson.version>1.2.79</fastjson.version>
<oshi.version>6.1.2</oshi.version>
<jna.version>5.10.0</jna.version>
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
<fastjson.version>1.2.83</fastjson.version>
<oshi.version>6.4.0</oshi.version>
<commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version>
<poi.version>4.1.2</poi.version>
@ -42,7 +40,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.10</version>
<version>2.5.14</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -56,7 +54,7 @@
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
@ -96,13 +94,6 @@
<version>${bitwalker.version}</version>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
@ -117,18 +108,6 @@
<version>${oshi.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
<!-- Swagger3依赖 -->
<dependency>
<groupId>io.springfox</groupId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.3</version>
<version>4.7.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

View File

@ -62,6 +62,15 @@ public class DemoFormController
return prefix + "/timeline";
}
/**
* 进度条
*/
@GetMapping("/progress_bars")
public String progress_bars()
{
return prefix + "/progress_bars";
}
/**
* 表单校验
*/

View File

@ -47,7 +47,7 @@ public class CacheController extends BaseController
public String getCacheKeys(String fragment, String cacheName, ModelMap mmap)
{
mmap.put("cacheName", cacheName);
mmap.put("cacheKyes", cacheService.getCacheKeys(cacheName));
mmap.put("cacheKeys", cacheService.getCacheKeys(cacheName));
return prefix + "/cache::" + fragment;
}

View File

@ -17,7 +17,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
@ -166,24 +165,13 @@ public class SysDeptController extends BaseController
*/
@GetMapping(value = { "/selectDeptTree/{deptId}", "/selectDeptTree/{deptId}/{excludeId}" })
public String selectDeptTree(@PathVariable("deptId") Long deptId,
@PathVariable(value = "excludeId", required = false) String excludeId, ModelMap mmap)
@PathVariable(value = "excludeId", required = false) Long excludeId, ModelMap mmap)
{
mmap.put("dept", deptService.selectDeptById(deptId));
mmap.put("excludeId", excludeId);
return prefix + "/tree";
}
/**
* 加载部门列表树
*/
@GetMapping("/treeData")
@ResponseBody
public List<Ztree> treeData()
{
List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
return ztrees;
}
/**
* 加载部门列表树(排除下级)
*/
@ -196,15 +184,4 @@ public class SysDeptController extends BaseController
List<Ztree> ztrees = deptService.selectDeptTreeExcludeChild(dept);
return ztrees;
}
/**
* 加载角色部门(数据权限)列表树
*/
@GetMapping("/roleDeptTreeData")
@ResponseBody
public List<Ztree> deptTreeData(SysRole role)
{
List<Ztree> ztrees = deptService.roleDeptTreeData(role);
return ztrees;
}
}

View File

@ -22,6 +22,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.system.service.ISysUserService;
@ -62,11 +63,7 @@ public class SysProfileController extends BaseController
public boolean checkPassword(String password)
{
SysUser user = getSysUser();
if (passwordService.matches(user, password))
{
return true;
}
return false;
return passwordService.matches(user, password);
}
@GetMapping("/resetPwd")
@ -168,7 +165,7 @@ public class SysProfileController extends BaseController
{
if (!file.isEmpty())
{
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file);
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
currentUser.setAvatar(avatar);
if (userService.updateUserInfo(currentUser) > 0)
{

View File

@ -15,6 +15,7 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
@ -22,6 +23,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.shiro.util.AuthorizationUtils;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@ -42,6 +44,9 @@ public class SysRoleController extends BaseController
@Autowired
private ISysUserService userService;
@Autowired
private ISysDeptService deptService;
@RequiresPermissions("system:role:view")
@GetMapping()
public String role()
@ -303,4 +308,16 @@ public class SysRoleController extends BaseController
roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds));
}
/**
* 加载角色部门(数据权限)列表树
*/
@RequiresPermissions("system:role:edit")
@GetMapping("/deptTreeData")
@ResponseBody
public List<Ztree> deptTreeData(SysRole role)
{
List<Ztree> ztrees = deptService.roleDeptTreeData(role);
return ztrees;
}
}

View File

@ -18,6 +18,8 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
@ -28,6 +30,7 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.framework.shiro.util.AuthorizationUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@ -48,6 +51,9 @@ public class SysUserController extends BaseController
@Autowired
private ISysRoleService roleService;
@Autowired
private ISysDeptService deptService;
@Autowired
private ISysPostService postService;
@ -124,7 +130,7 @@ public class SysUserController extends BaseController
@ResponseBody
public AjaxResult addSave(@Validated SysUser user)
{
if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user.getLoginName())))
if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user)))
{
return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
}
@ -170,7 +176,11 @@ public class SysUserController extends BaseController
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
if (StringUtils.isNotEmpty(user.getPhonenumber())
if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user)))
{
return error("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
@ -263,7 +273,7 @@ public class SysUserController extends BaseController
@ResponseBody
public String checkLoginNameUnique(SysUser user)
{
return userService.checkLoginNameUnique(user.getLoginName());
return userService.checkLoginNameUnique(user);
}
/**
@ -299,4 +309,29 @@ public class SysUserController extends BaseController
userService.checkUserDataScope(user.getUserId());
return toAjax(userService.changeStatus(user));
}
/**
* 加载部门列表树
*/
@RequiresPermissions("system:user:list")
@GetMapping("/deptTreeData")
@ResponseBody
public List<Ztree> deptTreeData()
{
List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
return ztrees;
}
/**
* 选择部门树
*
* @param deptId 部门ID
*/
@RequiresPermissions("system:user:list")
@GetMapping("/selectDeptTree/{deptId}")
public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap)
{
mmap.put("dept", deptService.selectDeptById(deptId));
return prefix + "/deptTree";
}
}

View File

@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@ -40,24 +40,24 @@ public class TestController extends BaseController
@ApiOperation("获取用户列表")
@GetMapping("/list")
public AjaxResult userList()
public R<List<UserEntity>> userList()
{
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
return AjaxResult.success(userList);
return R.ok(userList);
}
@ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@GetMapping("/{userId}")
public AjaxResult getUser(@PathVariable Integer userId)
public R<UserEntity> getUser(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
return AjaxResult.success(users.get(userId));
return R.ok(users.get(userId));
}
else
{
return error("用户不存在");
return R.fail("用户不存在");
}
}
@ -69,44 +69,46 @@ public class TestController extends BaseController
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
})
@PostMapping("/save")
public AjaxResult save(UserEntity user)
public R<String> save(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
return R.fail("用户ID不能为空");
}
return AjaxResult.success(users.put(user.getUserId(), user));
users.put(user.getUserId(), user);
return R.ok();
}
@ApiOperation("更新用户")
@PutMapping("/update")
public AjaxResult update(@RequestBody UserEntity user)
public R<String> update(@RequestBody UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
return R.fail("用户ID不能为空");
}
if (users.isEmpty() || !users.containsKey(user.getUserId()))
{
return error("用户不存在");
return R.fail("用户不存在");
}
users.remove(user.getUserId());
return AjaxResult.success(users.put(user.getUserId(), user));
users.put(user.getUserId(), user);
return R.ok();
}
@ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@DeleteMapping("/{userId}")
public AjaxResult delete(@PathVariable Integer userId)
public R<String> delete(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
users.remove(userId);
return success();
return R.ok();
}
else
{
return error("用户不存在");
return R.fail("用户不存在");
}
}
}

View File

@ -3,7 +3,7 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 4.7.3
version: 4.7.6
# 版权年份
copyrightYear: 2022
# 实例演示开关

View File

@ -1,11 +1,11 @@
/*!
* bootstrap-fileinput v5.2.4
* bootstrap-fileinput v5.5.2
* http://plugins.krajee.com/file-input
*
* Krajee default styling for bootstrap-fileinput.
*
* Author: Kartik Visweswaran
* Copyright: 2014 - 2021, Kartik Visweswaran, Krajee.com
* Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
*
* Licensed under the BSD-3-Clause
* https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
@ -50,6 +50,10 @@ input[type=file].file-loading {
display: none;
}
.file-caption .input-group {
align-items: center;
}
.btn-file input[type=file],
.file-caption-icon,
.file-preview .fileinput-remove,
@ -274,6 +278,7 @@ input[type=file].file-loading {
padding: 6px;
float: left;
text-align: center;
}
.krajee-default.file-preview-frame .kv-file-content {
@ -281,12 +286,6 @@ input[type=file].file-loading {
height: 160px;
}
.krajee-default .file-preview-other-frame {
display: flex;
align-items: center;
justify-content: center;
}
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
width: 400px;
}
@ -330,7 +329,7 @@ input[type=file].file-loading {
text-align: center;
padding-top: 4px;
font-size: 11px;
color: #777;
color: #999;
margin-bottom: 30px;
}
@ -406,7 +405,7 @@ input[type=file].file-loading {
height: 2.4rem;
top: 50%;
border-radius: 50%;
text-align:center;
text-align: center;
}
.btn-navigate * {
@ -426,19 +425,12 @@ input[type=file].file-loading {
right: 0;
}
.file-zoom-dialog .kv-zoom-caption {
max-width: 50%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.file-zoom-dialog .kv-zoom-header {
padding: 0.5rem;
}
.file-zoom-dialog .kv-zoom-body {
padding: 0.25rem 0.5rem 0.25rem 0;
padding: 0.25rem;
}
.file-zoom-dialog .kv-zoom-description {
@ -554,6 +546,10 @@ input[type=file].file-loading {
z-index: 3000;
}
.kv-zoom-actions {
min-width: 140px;
}
.kv-zoom-actions .btn-kv {
margin-left: 3px;
}
@ -568,15 +564,6 @@ input[type=file].file-loading {
background: transparent;
}
.file-zoom-content > * {
display: inline-block;
vertical-align: middle;
}
.file-zoom-content .kv-spacer {
height: 100%;
}
.file-zoom-content .file-preview-image {
max-height: 100%;
}
@ -668,4 +655,34 @@ input[type=file].file-loading {
.file-preview .kv-zoom-cache {
display: none;
}
.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body {
display: flex;
align-items: center;
justify-content: center;
}
.btn-kv-rotate,
.kv-file-rotate {
display: none;
}
.rotatable:not(.hide-rotate) .btn-kv-rotate,
.rotatable:not(.hide-rotate) .kv-file-rotate {
display: inline-block;
}
.rotatable .file-zoom-detail,
.rotatable .kv-file-content,
.rotatable .kv-file-content > :first-child {
transform-origin: center center;
}
.rotate-animate {
transition: transform 0.3s ease;
}
.kv-overflow-hidden {
overflow: hidden;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -136,7 +136,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
const formatValue = (row, i, column) => {
const value = Utils.calculateObjectValue(column,
column.printFormatter || column.formatter,
[row[column.field], row, i], row[column.field])
[$.common.getItemField(row, column.field), row, i], $.common.getItemField(row, column.field))
return typeof value === 'undefined' || value === null ?
this.options.undefinedText : value

View File

@ -182,11 +182,12 @@
$.ajax({
type: options.type,
url: options.url,
data: parms ? parms : options.ajaxParams,
data: $.extend(parms, options.ajaxParams),
dataType: "json",
success: function(data, textStatus, jqXHR) {
data = calculateObjectValue(options, options.responseHandler, [data], data);
renderTable(data);
calculateObjectValue(options, options.onLoadSuccess, [data], data);
},
error: function(xhr, textStatus) {
var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>'
@ -697,7 +698,8 @@
if (_ls && _ls.length > 0) {
$.each(_ls, function(index, item) {
var _p_icon = $("#" + $(item).attr("pid")).children().eq(options.expandColumn).find(".treetable-expander");
if (_p_icon.hasClass(options.expanderExpandedClass)) {
var _p_display = $("#" + $(item).attr("pid")).css('display');
if (_p_icon.hasClass(options.expanderExpandedClass) && _p_display == 'table') {
$(item).css("display", "table");
}
});
@ -728,7 +730,7 @@
$.ajax({
type: options.type,
url: options.dataUrl,
data: parms ? parms : options.ajaxParams,
data: $.extend(parms, options.ajaxParams),
dataType: "json",
success: function(data, textStatus, jqXHR) {
$("#" + row_id + "_load").remove();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -726,8 +726,8 @@ body.canvas-menu.mini-navbar nav.navbar-static-side {
}
.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {
background-color: #1a7bb9;
border-color: #1a7bb9;
background-color: #1a7bb9 !important;
border-color: #1a7bb9 !important;
color: #FFFFFF;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -338,7 +338,7 @@ label.error {
.input-group label.error {
z-index:99;
right: 42px
right: 42px;
}
.input-group input.error + label.error + .input-group-addon>i {
@ -347,10 +347,14 @@ label.error {
.input-group.date label.error {
z-index:99;
right: 42px
right: 42px;
}
.Validform_error,input.error,textarea.error,select.error {
.select2-hidden-accessible + label.error {
right: 38px;
}
.Validform_error,input.error,textarea.error,select.error,label.error+.select2-container--bootstrap .select2-selection--single {
background-color: #fbe2e2;
border-color: #c66161;
color: #c00
@ -508,7 +512,7 @@ div.ztree-border {
left: calc(100% - 20px);
background-color: #33cabb
}
.toggle-switch.switch-solid span {
height: 20px;
}
@ -843,7 +847,7 @@ label {
.table-bordered table>thead>tr>th:first-child, .table-bordered table>tbody>tr>td:first-child {
border-left: 1px solid #ddd;
}
.table-bordered table>thead>tr>th:last-child, .table-bordered table>tbody>tr>td:last-child {
border-right: 1px solid #ddd;
}
@ -872,7 +876,7 @@ label {
background-color: #eff3f8;
}
.fixed-table-container thead th >.both{
.fixed-table-container thead th >.both{
display: inline-block
}
@ -908,6 +912,9 @@ table.rc-table-resizing thead > th > a {
background-color: #fff;
box-sizing: border-box;
z-index: 1;
border-width: 0 0 0 1px;
-webkit-box-shadow: 0 0 10px rgba(0,0,0,.12);
box-shadow: 0 0 10px rgba(0,0,0,.12);
}
.fixed-columns {
@ -1037,12 +1044,12 @@ table.rc-table-resizing thead > th > a {
}
/** 表格列拖拽样式 **/
.dragtable-sortable {
.dragtable-sortable {
list-style-type: none; margin: 0; padding: 0; -moz-user-select: none;
}
.dragtable-sortable li {
margin: 0; padding: 0; float: left; font-size: 1em; background: white;
margin: 0; padding: 0; float: left; font-size: 1em; background: white;
}
.dragtable-sortable th, .dragtable-sortable td{
@ -1050,26 +1057,26 @@ table.rc-table-resizing thead > th > a {
}
.dragtable-sortable li:first-child th, .dragtable-sortable li:first-child td {
border-left: 1px solid #CCC;
border-left: 1px solid #CCC;
}
.ui-sortable-helper {
opacity: 0.7;filter: alpha(opacity=70);
}
.ui-sortable-placeholder {
.ui-sortable-placeholder {
-moz-box-shadow: 4px 5px 4px #C6C6C6 inset;
-webkit-box-shadow: 4px 5px 4px #C6C6C6 inset;
box-shadow: 4px 5px 4px #C6C6C6 inset;
border-bottom: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
visibility: visible !important;
background: #EFEFEF !important;
background: #EFEFEF !important;
visibility: visible !important;
}
.ui-sortable-placeholder * {
opacity: 0.0; visibility: hidden;
.ui-sortable-placeholder * {
opacity: 0.0; visibility: hidden;
}
/** 表格选中样式 **/

View File

@ -262,7 +262,7 @@ $(function() {
// 获取标识数据
var dataUrl = $(this).attr('href'),
dataIndex = $(this).data('index'),
menuName = $.trim($(this).text()),
menuName = $(this).data('title') || $.trim($(this).text()),
isRefresh = $(this).data("refresh"),
flag = true;
@ -306,7 +306,7 @@ $(function() {
$('.menuTab').removeClass('active');
// 添加选项卡对应的iframe
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" seamless></iframe>';
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-refresh="' + isRefresh + '" seamless></iframe>';
$('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
$.modal.loading("数据加载中,请稍候...");
@ -434,15 +434,20 @@ $(function() {
function activeTab() {
if (!$(this).hasClass('active')) {
var currentId = $(this).data('id');
var isRefresh = false;
syncMenuTab(currentId);
// 显示tab对应的内容区
$('.mainContent .RuoYi_iframe').each(function() {
if ($(this).data('id') == currentId) {
$(this).show().siblings('.RuoYi_iframe').hide();
isRefresh = $(this).data('refresh');
return false;
}
});
$(this).addClass('active').siblings('.menuTab').removeClass('active');
if (isRefresh) {
refreshTab();
}
scrollToTab(this);
}
}

View File

@ -417,7 +417,7 @@ var storage = {
// 主子表操作封装处理
var sub = {
editColumn: function() {
editRow: function() {
var dataColumns = [];
for (var columnIndex = 0; columnIndex < table.options.columns.length; columnIndex++) {
if (table.options.columns[columnIndex].visible != false) {
@ -442,7 +442,11 @@ var sub = {
} else if ($.common.isNotEmpty(textareaValue.val())) {
obj[key] = textareaValue.val();
} else {
obj[key] = "";
if (key == "index" && $.common.isNotEmpty(data[dataIndex].index)) {
obj[key] = data[dataIndex].index;
} else {
obj[key] = "";
}
}
}
var item = data[dataIndex];
@ -451,8 +455,8 @@ var sub = {
}
$("#" + table.options.id).bootstrapTable("updateRow", params);
},
delColumn: function(column) {
sub.editColumn();
delRow: function(column) {
sub.editRow();
var subColumn = $.common.isEmpty(column) ? "index" : column;
var ids = $.table.selectColumns(subColumn);
if (ids.length == 0) {
@ -461,15 +465,17 @@ var sub = {
}
$("#" + table.options.id).bootstrapTable('remove', { field: subColumn, values: ids });
},
addColumn: function(row, tableId) {
delRowByIndex: function(value) {
sub.editRow();
$("#" + table.options.id).bootstrapTable('remove', { field: "index", values: [value] });
sub.editRow();
},
addRow: function(row, tableId) {
var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
table.set(currentId);
var count = $("#" + currentId).bootstrapTable('getData').length;
sub.editColumn();
$("#" + currentId).bootstrapTable('insertRow', {
index: count + 1,
row: row
});
sub.editRow();
$("#" + currentId).bootstrapTable('insertRow', { index: count + 1, row: row });
}
};
@ -511,7 +517,7 @@ window.onload = function() {
return _stopIt(event);
}
var type_e = elem.type.toUpperCase();
if (name == 'INPUT' && (type_e != 'TEXT' && type_e != 'TEXTAREA' && type_e != 'PASSWORD' && type_e != 'FILE' && type_e != 'SEARCH' && type_e != 'NUMBER' && type_e != 'EMAIL')) {
if (name == 'INPUT' && (type_e != 'TEXT' && type_e != 'TEXTAREA' && type_e != 'PASSWORD' && type_e != 'FILE' && type_e != 'SEARCH' && type_e != 'NUMBER' && type_e != 'EMAIL' && type_e != 'URL')) {
return _stopIt(event);
}
if (name == 'INPUT' && (elem.readOnly == true || elem.disabled == true)) {

View File

@ -10,8 +10,8 @@ var table = {
options: {},
// 设置实例配置
set: function(id) {
if($.common.getLength(table.config) > 1 && $.common.isNotEmpty(event)) {
var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") : id;
if ($.common.getLength(table.config) > 1 && $.common.isNotEmpty(event)) {
var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") || $(event.currentTarget).parents(".bootstrap-tree-table").find("table.table").attr("id") : id;
if ($.common.isNotEmpty(tableId)) {
table.options = table.get(tableId);
}
@ -180,14 +180,15 @@ var table = {
if (typeof table.get(this.id).responseHandler == "function") {
table.get(this.id).responseHandler(res);
}
var thisOptions = table.config[this.id];
if (res.code == web_status.SUCCESS) {
if ($.common.isNotEmpty(table.options.sidePagination) && table.options.sidePagination == 'client') {
if ($.common.isNotEmpty(thisOptions.sidePagination) && thisOptions.sidePagination == 'client') {
return res.rows;
} else {
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
var column = $.common.isEmpty(table.options.uniqueId) ? table.options.columns[1].field : table.options.uniqueId;
if ($.common.isNotEmpty(thisOptions.rememberSelected) && thisOptions.rememberSelected) {
var column = $.common.isEmpty(thisOptions.uniqueId) ? thisOptions.columns[1].field : thisOptions.uniqueId;
$.each(res.rows, function(i, row) {
row.state = $.inArray(row[column], table.rememberSelectedIds[table.options.id]) !== -1;
row.state = $.inArray(row[column], table.rememberSelectedIds[thisOptions.id]) !== -1;
})
}
return { rows: res.rows, total: res.total };
@ -220,13 +221,13 @@ var table = {
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
var selectedIds = table.rememberSelectedIds[table.options.id];
if($.common.isNotEmpty(selectedIds)) {
if ($.common.isNotEmpty(selectedIds)) {
table.rememberSelectedIds[table.options.id] = _[func](selectedIds, rowIds);
} else {
table.rememberSelectedIds[table.options.id] = _[func]([], rowIds);
}
var selectedRows = table.rememberSelecteds[table.options.id];
if($.common.isNotEmpty(selectedRows)) {
if ($.common.isNotEmpty(selectedRows)) {
table.rememberSelecteds[table.options.id] = _[func](selectedRows, rows);
} else {
table.rememberSelecteds[table.options.id] = _[func]([], rows);
@ -248,7 +249,7 @@ var table = {
$(optionsIds).off("click").on("click", '.img-circle', function() {
var src = $(this).attr('src');
var target = $(this).data('target');
if($.common.equals("self", target)) {
if ($.common.equals("self", target)) {
var height = $(this).data('height');
var width = $(this).data('width');
top.layer.open({
@ -299,6 +300,9 @@ var table = {
var tableParams = $("#" + currentId).bootstrapTable('getOptions');
var pageSize = $.common.isNotEmpty(tableParams.pageSize) ? tableParams.pageSize: table.options.pageSize;
var pageNumber = $.common.isNotEmpty(tableParams.pageNumber) ? tableParams.pageNumber: table.options.pageNumber;
if (table.options.sidePagination == 'client') {
return index + 1;
}
return pageSize * (pageNumber - 1) + index + 1;
},
// 列超出指定长度浮动提示 targetcopy单击复制文本 open弹窗打开文本
@ -359,7 +363,7 @@ var table = {
if ($.common.isNotEmpty(pageSize)) {
params.pageSize = pageSize;
}
if($.common.isNotEmpty(tableId)){
if ($.common.isNotEmpty(tableId)){
$("#" + tableId).bootstrapTable('refresh', params);
} else{
$("#" + table.options.id).bootstrapTable('refresh', params);
@ -489,7 +493,7 @@ var table = {
});
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
var selectedRows = table.rememberSelecteds[table.options.id];
if($.common.isNotEmpty(selectedRows)) {
if ($.common.isNotEmpty(selectedRows)) {
rows = $.map(table.rememberSelecteds[table.options.id], function (row) {
return $.common.getItemField(row, column);
});
@ -518,7 +522,7 @@ var table = {
});
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
var selectedRows = table.rememberSelecteds[table.options.id];
if($.common.isNotEmpty(selectedRows)) {
if ($.common.isNotEmpty(selectedRows)) {
rows = $.map(selectedRows, function (row) {
return $.common.getItemField(row, table.options.columns[1].field);
});
@ -646,7 +650,7 @@ var table = {
search: function(formId) {
var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
var params = $.common.formToJSON(currentId);
$.bttTable.bootstrapTreeTable('refresh', params);
$.bttTable.bootstrapTreeTable('refresh', $.extend(params, table.options.ajaxParams));
},
// 刷新
refresh: function() {
@ -698,7 +702,7 @@ var table = {
}
$("#" + tableId).bootstrapTable('refresh', params);
} else if (table.options.type == table_type.bootstrapTreeTable) {
$("#" + tableId).bootstrapTreeTable('refresh', []);
$("#" + tableId).bootstrapTreeTable('refresh', table.options.ajaxParams);
}
if ($.common.isNotEmpty(startLayDate) && $.common.isNotEmpty(endLayDate)) {
endLayDate.config.min.year = '';
@ -808,7 +812,7 @@ var table = {
},
// 获取iframe页的DOM
getChildFrame: function (index) {
if($.common.isEmpty(index)){
if ($.common.isEmpty(index)){
var index = parent.layer.getFrameIndex(window.name);
return parent.layer.getChildFrame('body', index);
} else {
@ -817,7 +821,7 @@ var table = {
},
// 关闭窗体
close: function (index) {
if($.common.isEmpty(index)){
if ($.common.isEmpty(index)){
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
} else {
@ -879,6 +883,9 @@ var table = {
yes: callback,
cancel: function(index) {
return true;
},
success: function () {
$(':focus').blur();
}
});
},
@ -900,7 +907,7 @@ var table = {
}
}
var btnCallback = {};
if(options.btn instanceof Array){
if (options.btn instanceof Array){
for (var i = 1, len = options.btn.length; i < len; i++) {
var btn = options["btn" + (i + 1)];
if (btn) {
@ -925,6 +932,9 @@ var table = {
yes: options.yes,
cancel: function () {
return true;
},
success: function () {
$(':focus').blur();
}
}, btnCallback));
if ($.common.isNotEmpty(options.full) && options.full === true) {
@ -968,6 +978,9 @@ var table = {
},
cancel: function(index) {
return true;
},
success: function () {
$(':focus').blur();
}
});
top.layer.full(index);
@ -1082,7 +1095,7 @@ var table = {
table.set();
$.modal.confirm("确定删除该条" + table.options.modalName + "信息吗?", function() {
var url = $.common.isEmpty(id) ? table.options.removeUrl : table.options.removeUrl.replace("{id}", id);
if(table.options.type == table_type.bootstrapTreeTable) {
if (table.options.type == table_type.bootstrapTreeTable) {
$.operate.get(url);
} else {
var data = { "ids": id };
@ -1135,7 +1148,7 @@ var table = {
// 修改信息
edit: function(id) {
table.set();
if($.common.isEmpty(id) && table.options.type == table_type.bootstrapTreeTable) {
if ($.common.isEmpty(id) && table.options.type == table_type.bootstrapTreeTable) {
var row = $("#" + table.options.id).bootstrapTreeTable('getSelections')[0];
if ($.common.isEmpty(row)) {
$.modal.alertWarning("请至少选择一条记录");
@ -1159,7 +1172,7 @@ var table = {
if ($.common.isNotEmpty(id)) {
url = table.options.updateUrl.replace("{id}", id);
} else {
if(table.options.type == table_type.bootstrapTreeTable) {
if (table.options.type == table_type.bootstrapTreeTable) {
var row = $("#" + table.options.id).bootstrapTreeTable('getSelections')[0];
if ($.common.isEmpty(row)) {
$.modal.alertWarning("请至少选择一条记录");
@ -1285,7 +1298,7 @@ var table = {
successCallback: function(result) {
if (result.code == web_status.SUCCESS) {
var parent = activeWindow();
if($.common.isEmpty(parent.table)) {
if ($.common.isEmpty(parent.table)) {
$.modal.msgSuccessReload(result.msg);
} else if (parent.table.options.type == table_type.bootstrapTable) {
$.modal.close();
@ -1309,15 +1322,20 @@ var table = {
if (result.code == web_status.SUCCESS) {
var topWindow = $(window.parent.document);
var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-panel');
var $contentWindow = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow;
$.modal.close();
$contentWindow.$.modal.msgSuccess(result.msg);
$contentWindow.$(".layui-layer-padding").removeAttr("style");
if ($contentWindow.table.options.type == table_type.bootstrapTable) {
$contentWindow.$.table.refresh();
} else if ($contentWindow.table.options.type == table_type.bootstrapTreeTable) {
$contentWindow.$.treeTable.refresh();
var topWindow = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0];
if ($.common.isNotEmpty(topWindow) && $.common.isNotEmpty(currentId)) {
var $contentWindow = topWindow.contentWindow;
$contentWindow.$.modal.msgSuccess(result.msg);
$contentWindow.$(".layui-layer-padding").removeAttr("style");
if ($contentWindow.table.options.type == table_type.bootstrapTable) {
$contentWindow.$.table.refresh();
} else if ($contentWindow.table.options.type == table_type.bootstrapTreeTable) {
$contentWindow.$.treeTable.refresh();
}
} else {
$.modal.msgSuccess(result.msg);
}
$.modal.close();
$.modal.closeTab();
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg)
@ -1400,7 +1418,7 @@ var table = {
var node = tree.getNodesByParam("id", treeId, null)[0];
$.tree.selectByIdName(treeId, node);
// 回调tree方法
if(typeof(options.callBack) === "function"){
if (typeof(options.callBack) === "function"){
options.callBack(tree);
}
});
@ -1489,7 +1507,7 @@ var table = {
// 不允许根父节点选择
notAllowParents: function(_tree) {
var nodes = _tree.getSelectedNodes();
if(nodes.length == 0){
if (nodes.length == 0){
$.modal.msgError("请选择节点后提交");
return false;
}
@ -1536,7 +1554,7 @@ var table = {
common: {
// 判断字符串是否为空
isEmpty: function (value) {
if (value == null || this.trim(value) == "") {
if (value == null || this.trim(value) == "" || value == undefined || value == "undefined") {
return true;
}
return false;
@ -1677,7 +1695,7 @@ var table = {
formToJSON: function(formId) {
var json = {};
$.each($("#" + formId).serializeArray(), function(i, field) {
if(json[field.name]) {
if (json[field.name]) {
json[field.name] += ("," + field.value);
} else {
json[field.name] = field.value;

View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<th:block th:include="include :: header('进度条')" />
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>进度条 (Progress Bars)</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">选项1</a>
</li>
<li><a href="#">选项2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<!-- style: progress-bar-success/progress-bar-info/progress-bar-warning/progress-bar-danger -->
<h5>基本</h5>
<div class="progress">
<div style="width: 35%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="35" role="progressbar" class="progress-bar progress-bar-success">
<span class="sr-only">35% Complete (success)</span>
</div>
</div>
<div class="progress progress-bar-default">
<div style="width: 43%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="43" role="progressbar" class="progress-bar">
<span class="sr-only">43% Complete (success)</span>
</div>
</div>
<h5>条纹效果</h5>
<div class="progress progress-striped">
<div style="width: 50%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="50" role="progressbar" class="progress-bar progress-bar-warning">
<span class="sr-only">50% Complete (success)</span>
</div>
</div>
<h5>动画效果</h5>
<div class="progress progress-striped active">
<div style="width: 75%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="75" role="progressbar" class="progress-bar progress-bar-danger">
<span class="sr-only">75% Complete (success)</span>
</div>
</div>
<h5>堆叠效果</h5>
<div class="progress progress-striped active">
<div style="width: 30%" class="progress-bar progress-bar-success">
<span class="sr-only">30% Complete (success)</span>
</div>
<div style="width: 20%" class="progress-bar progress-bar-warning">
<span class="sr-only">20% Complete (warning)</span>
</div>
<div style="width: 40%" class="progress-bar progress-bar-danger">
<span class="sr-only">40% Complete (danger)</span>
</div>
</div>
<h5>带有提示标签的进度条</h5>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="95" aria-valuemin="0" aria-valuemax="100" style="width: 95%;">
95%
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
$("[data-toggle='tooltip']").tooltip();
$("[data-toggle=popover]").popover();
</script>
</body>
</html>

View File

@ -17,7 +17,7 @@
<h2>若依后台管理系统</h2>
<p>ruoyi是一个完全响应式基于Bootstrap3.3.7最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.7.3
<b>当前版本:</b>v4.7.6
</p>
<p>
<span class="label label-warning">免费开源</span>
@ -56,7 +56,7 @@
<h3>你好,若依 </h3>
<p>H+是一个完全响应式基于Bootstrap3.3.7最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.7.3
<b>当前版本:</b>v4.7.6
</p>
<p>
<span class="label label-warning">开源免费</span>

View File

@ -181,7 +181,7 @@ $('#smartwizard').smartWizard({
enableURLhash: true, // Enable selection of the step based on url hash
transition: {
animation: 'none', // Effect on navigation, none/fade/slide-horizontal/slide-vertical/slide-swing
speed: '400', // Transion animation speed
speed: '400', // Transition animation speed
easing:'' // Transition animation easing. Not supported without a jQuery easing plugin
},
toolbarSettings: {

View File

@ -1,8 +1,11 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('主子表提交')" />
<th:block th:include="include :: header('主子表提交')" />
<th:block th:include="include :: datetimepicker-css" />
<style type="text/css">
table label.error{position: inherit;}select + label.error{z-index:1;right:40px;}
</style>
</head>
<body class="gray-bg">
<div class="main-content">
@ -13,7 +16,7 @@
<div class="form-group">
<label class="col-sm-4 control-label is-required">客户名称:</label>
<div class="col-sm-8">
<input name="name" placeholder="请输入客户名称" class="form-control" type="text" maxlength="30">
<input name="name" placeholder="请输入客户名称" class="form-control" type="text" maxlength="30" required>
</div>
</div>
</div>
@ -31,9 +34,9 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">手机号码:</label>
<label class="col-sm-4 control-label">手机号码:</label>
<div class="col-sm-8">
<input id="phonenumber" name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11">
<input id="phonenumber" name="phonenumber" placeholder="请输入手机号码" class="form-control isPhone" type="text" maxlength="11">
</div>
</div>
</div>
@ -62,8 +65,8 @@
<h4 class="form-header h4">商品数据</h4>
<div class="row">
<div class="col-sm-12">
<button type="button" class="btn btn-white btn-sm" onclick="addColumn()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delColumn()"><i class="fa fa-minus"> 删除</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
@ -127,7 +130,7 @@
align: 'center',
title: '商品名称',
formatter: function(value, row, index) {
var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].name' value='%s'>", index, value);
var html = $.common.sprintf("<input class='form-control goodsName' type='text' name='goods[%s].name' value='%s'>", index, value);
return html;
}
},
@ -136,7 +139,7 @@
align: 'center',
title: '商品重量',
formatter: function(value, row, index) {
var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].weight' value='%s'>", index, value);
var html = $.common.sprintf("<input class='form-control goodsWeight' type='text' name='goods[%s].weight' value='%s'>", index, value);
return html;
}
},
@ -166,16 +169,34 @@
var data = [{ index: index, type: value }];
return $("#goodsTypeTpl").tmpl(data).html();
}
}]
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
}
}]
};
$.table.init(options);
});
/* 主子表-提交 */
$.validator.addMethod("goodsName", function(value, element) {
return !this.optional(element);
}, "商品名称必填。");
$.validator.addMethod("goodsWeight", function(value, element) {
return !this.optional(element) && (value <= 100 && value >= 0);
}, "商品重量长度区间0-100。");
/* 主子表-提交 */
function submitHandler(index, layero){
var data = $("#form-add").serializeArray();
alert(JSON.stringify(data))
$.operate.saveModal("/demo/operate/customer/add", data);
if ($.validate.form()) {
var data = $("#form-add").serializeArray();
alert(JSON.stringify(data))
$.operate.saveModal("/demo/operate/customer/add", data);
}
}
$("input[name='birthday']").datetimepicker({
@ -184,15 +205,17 @@
autoclose: true
});
function addColumn() {
function addRow() {
var count = $("#" + table.options.id).bootstrapTable('getData').length;
var row = {
index: $.table.serialNumber(count),
name: "",
weight: "",
price: "",
date: "",
type: "",
}
sub.addColumn(row);
sub.addRow(row);
}
$("#bootstrap-table").on("post-body.bs.table", function (e, args) {

View File

@ -7,19 +7,19 @@
<meta name="description" content="">
<title th:text="${title}"></title>
<link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/>
<link th:href="@{/css/font-awesome.min.css?v=4.7.3}" rel="stylesheet"/>
<link th:href="@{/css/font-awesome.min.css?v=4.7.0}" rel="stylesheet"/>
<!-- bootstrap-table 表格插件样式 -->
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.18.3}" rel="stylesheet"/>
<link th:href="@{/css/animate.min.css?v=20210831}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css?v=20210831}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.3}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.6}" rel="stylesheet"/>
</head>
<!-- 通用JS -->
<div th:fragment="footer">
<script th:inline="javascript"> var ctx = [[@{/}]]; var lockscreen = [[${session.lockscreen}]]; if(lockscreen){window.top.location=ctx+"lockscreen";} </script>
<a id="scroll-up" href="#" class="btn btn-sm display"><i class="fa fa-angle-double-up"></i></a>
<script th:src="@{/js/jquery.min.js?v=3.6.0}"></script>
<script th:src="@{/js/jquery.min.js?v=3.6.1}"></script>
<script th:src="@{/js/bootstrap.min.js?v=3.3.7}"></script>
<!-- bootstrap-table 表格插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=1.18.3}"></script>
@ -35,9 +35,9 @@
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script>
<script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js?v=3.5.1}"></script>
<script th:src="@{/ajax/libs/layui/layui.min.js?v=2.6.8}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script th:src="@{/ajax/libs/layui/layui.min.js?v=2.7.5}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.6}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
</div>
<!-- ztree树插件 -->
@ -108,10 +108,10 @@
<!-- fileinput文件上传插件 -->
<div th:fragment="bootstrap-fileinput-css">
<link th:href="@{/ajax/libs/bootstrap-fileinput/fileinput.min.css?v=5.2.4}" rel="stylesheet"/>
<link th:href="@{/ajax/libs/bootstrap-fileinput/fileinput.min.css?v=5.5.2}" rel="stylesheet"/>
</div>
<div th:fragment="bootstrap-fileinput-js">
<script th:src="@{/ajax/libs/bootstrap-fileinput/fileinput.min.js?v=5.2.4}"></script>
<script th:src="@{/ajax/libs/bootstrap-fileinput/fileinput.min.js?v=5.5.2}"></script>
</div>
<!-- duallistbox双列表框插件 -->

View File

@ -14,7 +14,8 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css?v=20200902}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.3}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.6}" rel="stylesheet"/>
<style type="text/css">.fixed-sidebar .nav:not(.navbar-toolbar)>li.active{border-left:0px!important;}</style>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper">
@ -98,6 +99,7 @@
<li><a class="menuItem" th:href="@{/demo/form/grid}">栅格</a></li>
<li><a class="menuItem" th:href="@{/demo/form/select}">下拉框</a></li>
<li><a class="menuItem" th:href="@{/demo/form/timeline}">时间轴</a></li>
<li><a class="menuItem" th:href="@{/demo/form/progress_bars}">进度条</a></li>
<li><a class="menuItem" th:href="@{/demo/form/basic}">基本表单</a></li>
<li><a class="menuItem" th:href="@{/demo/form/cards}">卡片列表</a></li>
<li><a class="menuItem" th:href="@{/demo/form/jasny}">功能扩展</a></li>
@ -316,8 +318,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.6}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:src="@{/js/resize-tabs.js}"></script>

View File

@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.3}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.6}" rel="stylesheet"/>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper">
@ -80,6 +80,7 @@
<li><a class="menuItem" th:href="@{/demo/form/grid}">栅格</a></li>
<li><a class="menuItem" th:href="@{/demo/form/select}">下拉框</a></li>
<li><a class="menuItem" th:href="@{/demo/form/timeline}">时间轴</a></li>
<li><a class="menuItem" th:href="@{/demo/form/progress_bars}">进度条</a></li>
<li><a class="menuItem" th:href="@{/demo/form/basic}">基本表单</a></li>
<li><a class="menuItem" th:href="@{/demo/form/cards}">卡片列表</a></li>
<li><a class="menuItem" th:href="@{/demo/form/jasny}">功能扩展</a></li>
@ -263,8 +264,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.6}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:inline="javascript">

View File

@ -38,7 +38,7 @@
<script src="../static/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script>
<script src="../static/js/three.min.js" th:src="@{/js/three.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
</body>
<script th:inline="javascript">
var ctx = [[@{/}]];

View File

@ -9,7 +9,7 @@
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.3}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.6}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@ -76,7 +76,7 @@
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
</body>
</html>

View File

@ -79,7 +79,7 @@
<div class="ibox-content">
<p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
</p>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <s>满101526938</s> <s>满264355400</s> <a href="https://jq.qq.com/?_wv=1027&k=540WfdEr" target="_blank">298522656</a>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <s>满101526938</s> <s>满264355400</s> <s>满298522656</s> <s>满139845794</s> <a href="https://jq.qq.com/?_wv=1027&k=Cqd66IKe" target="_blank">185760789</a>
</p>
<p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
</p>
@ -96,13 +96,134 @@
<div class="ibox-content no-padding">
<div class="panel-body">
<div class="panel-group" id="version">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v476">v4.7.6</a><code class="pull-right">2022.12.16</code>
</h5>
</div>
<div id="v476" class="panel-collapse collapse in">
<div class="panel-body">
<ol>
<li>定时任务违规的字符</li>
<li>忽略不必要的属性数据返回</li>
<li>导入更新用户数据前校验数据权限</li>
<li>修改参数键名时移除前缓存配置</li>
<li>修改用户登录账号进行重复验证</li>
<li>兼容Excel下拉框内容过多无法显示</li>
<li>升级oshi到最新版本6.4.0</li>
<li>升级kaptcha到最新版2.3.3</li>
<li>升级druid到最新版本1.2.15</li>
<li>升级shiro到最新版本1.10.1</li>
<li>升级pagehelper到最新版1.4.6</li>
<li>升级bootstrap-fileinput到最新版本5.5.2</li>
<li>修复sheet超出最大行数异常问题</li>
<li>修复关闭父页签后提交无法跳转的问题</li>
<li>修复操作日志类型多选导出不生效问题</li>
<li>修复导出包含空子列表数据异常的问题</li>
<li>优化树形表格层级显示</li>
<li>优化SQL关键字检查防止注入</li>
<li>优化用户管理重置时取消部门选择</li>
<li>优化代码生成同步后字典值NULL问题</li>
<li>优化导出对象的子列表为空会出现[]问题</li>
<li>优化select2搜索下拉后校验必填样式问题</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v475">v4.7.5</a><code class="pull-right">2022.09.05</code>
</h5>
</div>
<div id="v475" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<li>Excel支持导出对象的子列表方法</li>
<li>数据逻辑删除不进行唯一验证</li>
<li>优化多角色数据权限匹配规则</li>
<li>新增主子表提交校验示例</li>
<li>支持自定义隐藏Excel属性列</li>
<li>Excel注解支持backgroundColor属性设置背景颜色</li>
<li>菜单配置刷新时Tab页签切换时刷新</li>
<li>增加对AjaxResult消息结果类型的判断</li>
<li>新增示例(进度条)</li>
<li>新增内容编码/解码方便插件集成使用</li>
<li>升级jquery到最新版3.6.1</li>
<li>升级layui到最新版本2.7.5</li>
<li>升级shiro到最新版本1.9.1</li>
<li>升级druid到最新版本1.2.11</li>
<li>升级pagehelper到最新版1.4.3</li>
<li>升级oshi到最新版本6.2.2</li>
<li>修复树表onLoadSuccess不生效的问题</li>
<li>修复用户分配角色大于默认页数丢失问题</li>
<li>定时任务支持执行父类方法</li>
<li>自动设置切换多个树表格实例配置</li>
<li>页签创建标题优先data-title属性</li>
<li>优化任务过期不执行调度</li>
<li>优化横向菜单下激活菜单样式</li>
<li>优化按钮打开窗口后按回车反复弹出</li>
<li>优化excel/scale属性导出单元格数值类型</li>
<li>优化druid开启wall过滤器出现的异常问题</li>
<li>优化多个相同角色数据导致权限SQL重复问题</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v474">v4.7.4</a><code class="pull-right">2022.06.01</code>
</h5>
</div>
<div id="v474" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<li>用户头像上传图片格式限制</li>
<li>Excel注解支持color属性设置字体颜色</li>
<li>设置分页参数默认值</li>
<li>主子表操作列新增单个删除</li>
<li>定时任务检查Bean包名是否为白名单配置</li>
<li>升级spring-boot到最新版本2.5.14</li>
<li>升级shiro到最新版本1.9.0</li>
<li>升级oshi到最新版本6.1.6</li>
<li>升级fastjson到最新版1.2.83 安全修复版本</li>
<li>文件上传兼容Weblogic环境</li>
<li>新增清理分页的线程变量方法</li>
<li>新增获取不带后缀文件名称方法</li>
<li>用户缓存信息添加部门ancestors祖级列表</li>
<li>自定义ShiroFilterFactoryBean防止中文请求被拦截</li>
<li>字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)</li>
<li>优化IP地址获取到多个的问题</li>
<li>优化表格冻结列阴影效果显示</li>
<li>优化菜单侧边栏滚动条尺寸及颜色</li>
<li>优化显示顺序orderNum类型为整型</li>
<li>优化接口使用泛型使其看到响应属性字段</li>
<li>优化导出数据LocalDateTime类型无数据问题</li>
<li>修复导入Excel时字典字段类型为Long转义为空问题</li>
<li>优化导出excel单元格验证,包含变更为开头.防止正常内容被替换</li>
<li>修复URL类型回退键被禁止问题</li>
<li>修复表格客户端分页序号显示错误问题</li>
<li>修复代码生成拖拽多次出现的排序不正确问题</li>
<li>修复表格打印组件不识别多层对象属性值问题</li>
<li>修复操作日志查询类型条件为0时会查到所有数据</li>
<li>修复Excel注解prompt/combo同时使用不生效问题</li>
<li>修复初始化多表格处理回调函数时获取的表格配置不一致问题</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v473">v4.7.3</a><code class="pull-right">2022.03.01</code>
</h5>
</div>
<div id="v473" class="panel-collapse collapse in">
<div id="v473" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<li>表格树支持分页/异步加载</li>

View File

@ -53,8 +53,8 @@
<th>操作</th>
</tr>
</thead>
<tbody id="cacheKyes">
<tr th:fragment="fragment-cache-kyes" th:each="cacheKey, stat : ${cacheKyes}">
<tbody id="cacheKeys">
<tr th:fragment="fragment-cache-kyes" th:each="cacheKey, stat : ${cacheKeys}">
<td>[[${stat.index + 1}]]</td>
<td style="word-wrap:break-word;word-break:break-all;" th:onclick="getCacheValue([[${cacheName}]], [[${cacheKey}]])">[[${cacheKey}]]</td>
<td style="width: 50px"><a href="#" th:onclick="clearCacheKey([[${cacheName}]], [[${cacheKey}]])" title="清空"><i class="fa fa-trash-o text-danger"></i></a></td>
@ -125,7 +125,7 @@ function getCacheKeys(cacheName, isMsg) {
"fragment": 'fragment-cache-kyes'
},
success: function(data) {
$("#cacheKyes").html(data);
$("#cacheKeys").html(data);
$("#cacheName").val(_cacheName);
if (isMsg) {
$.modal.msgSuccess("刷新键名列表成功");
@ -174,7 +174,7 @@ function clearCacheKey(cacheName, cacheKey) {
function clearAll(){
$.get(prefix + "/clearAll", function(result) {
if (result.code == web_status.SUCCESS) {
$.modal.msgSuccess("清理缓存成功")
$.modal.msgSuccess("清理全部缓存成功")
} else {
$.modal.msgError(result.msg);
}

View File

@ -18,7 +18,7 @@
<label>操作人员: </label><input type="text" name="operName"/>
</li>
<li class="select-selectpicker">
<label>操作类型: </label><select id="businessTypes" th:with="type=${@dict.getType('sys_oper_type')}" class="selectpicker" data-none-selected-text="请选择" multiple>
<label>操作类型: </label><select id="businessTypes" name="businessTypes" th:with="type=${@dict.getType('sys_oper_type')}" class="selectpicker" data-none-selected-text="请选择" multiple>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>

View File

@ -152,7 +152,7 @@
<div class="row">
<div class="col-sm-12">
<table class="table table-hover margin bottom">
<table class="table table-hover margin bottom" style="table-layout:fixed;">
<tbody>
<tr>
<td>Java名称</td>

View File

@ -9,7 +9,7 @@
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.3}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.6}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@ -74,7 +74,7 @@
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.3}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.6}"></script>
<script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script>
</body>
</html>

View File

@ -140,7 +140,7 @@
</ul>
</body>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.3}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.6}"></script>
<script type="text/javascript">
//皮肤样式列表
var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];

View File

@ -116,7 +116,7 @@
var options = {
title: '部门选择',
width: "380",
url: prefix + "/selectDeptTree/" + treeId,
url: prefix + "/selectDeptTree/" + treeId + "/0",
callBack: doSubmit
};
$.modal.openOptions(options);

View File

@ -32,7 +32,7 @@
var deptId = [[${deptId}]];
var excludeId = [[${excludeId}]];
$(function() {
var url = $.common.isEmpty(excludeId) ? prefix + "/treeData": prefix + "/treeData/" + excludeId;
var url = prefix + "/treeData/" + excludeId;
var options = {
url: url,
expandLevel: 2,

View File

@ -52,7 +52,7 @@
<script type="text/javascript">
$(function() {
var url = ctx + "system/dept/roleDeptTreeData?roleId=" + $("#roleId").val();
var url = ctx + "system/role/deptTreeData?roleId=" + $("#roleId").val();
var options = {
id: "deptTrees",
url: url,

View File

@ -239,7 +239,7 @@
function selectDeptTree() {
var treeId = $("#treeId").val();
var deptId = $.common.isEmpty(treeId) ? "100" : $("#treeId").val();
var url = ctx + "system/dept/selectDeptTree/" + deptId;
var url = ctx + "system/user/selectDeptTree/" + deptId;
var options = {
title: '选择部门',
width: "380",
@ -250,7 +250,6 @@
}
function doSubmit(index, layero){
var tree = layero.find("iframe")[0].contentWindow.$._tree;
var body = $.modal.getChildFrame(index);
$("#treeId").val(body.find('#treeId').val());
$("#treeName").val(body.find('#treeName').val());

View File

@ -100,9 +100,14 @@
/* 添加角色-提交 */
function submitHandler(index, layero){
var rows = $.table.selectFirstColumns();
var data = { "userId": $("#userId").val(), "roleIds": rows.join() };
$.operate.saveTab(prefix + "/insertAuthRole", data);
var roleIds = [];
var data = $('#bootstrap-table').bootstrapTable('getData');
for (var i = 0; i < data.length; i++) {
if (data[i][0] || ($.common.isEmpty(data[i][0]) && data[i].flag)) {
roleIds.push(data[i].roleId)
}
}
$.operate.saveTab(prefix + "/insertAuthRole", { "userId": $("#userId").val(), "roleIds": roleIds.join() });
}
</script>
</body>

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('部门树选择')" />
<th:block th:include="include :: ztree-css" />
</head>
<style>
body{height:auto;font-family: "Microsoft YaHei";}
button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
</style>
<body class="hold-transition box box-main">
<input id="treeId" name="treeId" type="hidden" th:value="${dept.deptId}"/>
<input id="treeName" name="treeName" type="hidden" th:value="${dept.deptName}"/>
<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
<label id="btnShow" title="显示搜索" style="display:none;"></label>
<label id="btnHide" title="隐藏搜索"></label>
</div>
<div class="treeSearchInput" id="search">
<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
</div>
<div class="treeExpandCollapse">
<a href="#" onclick="$.tree.expand()">展开</a> /
<a href="#" onclick="$.tree.collapse()">折叠</a>
</div>
<div id="tree" class="ztree treeselect"></div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: ztree-js" />
<script th:inline="javascript">
var prefix = ctx + "system/user"
var deptId = [[${deptId}]];
$(function() {
var url = prefix + "/deptTreeData";
var options = {
url: url,
expandLevel: 2,
onClick : zOnClick
};
$.tree.init(options);
});
function zOnClick(event, treeId, treeNode) {
var treeId = treeNode.id;
var treeName = treeNode.name;
$("#treeId").val(treeId);
$("#treeName").val(treeName);
}
</script>
</body>
</html>

View File

@ -203,7 +203,7 @@
/* 用户管理-修改-选择部门树 */
function selectDeptTree() {
var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
var url = ctx + "system/dept/selectDeptTree/" + deptId;
var url = ctx + "system/user/selectDeptTree/" + deptId;
var options = {
title: '选择部门',
width: "380",
@ -214,7 +214,6 @@
}
function doSubmit(index, layero){
var tree = layero.find("iframe")[0].contentWindow.$._tree;
var body = $.modal.getChildFrame(index);
$("#treeId").val(body.find('#treeId').val());
$("#treeName").val(body.find('#treeName').val());

View File

@ -54,7 +54,7 @@
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="resetPre()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
@ -191,7 +191,7 @@
function queryDeptTree()
{
var url = ctx + "system/dept/treeData";
var url = ctx + "system/user/deptTreeData";
var options = {
url: url,
expandLevel: 2,
@ -221,6 +221,15 @@
$('#btnRefresh').click(function() {
queryDeptTree();
});
/* 自定义重置-表单重置/隐藏框/树节点选择色/搜索 */
function resetPre() {
$("#user-form")[0].reset();
$("#deptId").val("");
$("#parentId").val("");
$(".curSelectedNode").removeClass("curSelectedNode");
$.table.search();
}
/* 用户管理-部门 */
function dept() {

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.3</version>
<version>4.7.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -25,4 +25,9 @@ public @interface DataScope
* 用户表的别名
*/
public String userAlias() default "";
/**
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@RequiresPermissions获取多个权限用逗号分隔开来
*/
public String permission() default "";
}

View File

@ -5,6 +5,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/**
@ -56,11 +58,6 @@ public @interface Excel
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型0数字 1字符串
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出时在excel中每个列的高度 单位为字符
*/
@ -91,6 +88,11 @@ public @interface Excel
*/
public String[] combo() default {};
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
public boolean needMerge() default false;
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
@ -107,9 +109,34 @@ public @interface Excel
public boolean isStatistics() default false;
/**
* 导出字段对齐方式0默认1靠左2居中3靠右
* 导出类型0数字 1字符串 2图片
*/
public Align align() default Align.AUTO;
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出列头背景色
*/
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
/**
* 导出列头字体颜色
*/
public IndexedColors headerColor() default IndexedColors.WHITE;
/**
* 导出单元格背景色
*/
public IndexedColors backgroundColor() default IndexedColors.WHITE;
/**
* 导出单元格字体颜色
*/
public IndexedColors color() default IndexedColors.BLACK;
/**
* 导出字段对齐方式
*/
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/**
* 自定义数据处理器
@ -121,22 +148,6 @@ public @interface Excel
*/
public String[] args() default {};
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 字段类型0导出导入1仅导出2仅导入
*/

View File

@ -111,5 +111,5 @@ public class Constants
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file" };
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.common.core.context;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.ruoyi.common.core.text.Convert;
/**
* 权限信息
*
* @author ruoyi
*/
public class PermissionContextHolder
{
private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
public static void setContext(String permission)
{
RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
RequestAttributes.SCOPE_REQUEST);
}
public static String getContext()
{
return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
RequestAttributes.SCOPE_REQUEST));
}
}

View File

@ -72,6 +72,14 @@ public class BaseController
}
}
/**
* 清理分页的线程变量
*/
protected void clearPage()
{
PageUtils.clearPage();
}
/**
* 获取request
*/

View File

@ -1,6 +1,7 @@
package com.ruoyi.common.core.domain;
import java.util.HashMap;
import java.util.Objects;
import com.ruoyi.common.utils.StringUtils;
/**
@ -81,20 +82,6 @@ public class AjaxResult extends HashMap<String, Object>
}
}
/**
* 方便链式调用
*
* @param key 键
* @param value 值
* @return 数据对象
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
/**
* 返回成功消息
*
@ -193,4 +180,38 @@ public class AjaxResult extends HashMap<String, Object>
{
return new AjaxResult(Type.ERROR, msg, data);
}
/**
* 是否为成功消息
*
* @return 结果
*/
public boolean isSuccess()
{
return !isError();
}
/**
* 是否为错误消息
*
* @return 结果
*/
public boolean isError()
{
return Objects.equals(Type.ERROR.value, this.get(CODE_TAG));
}
/**
* 方便链式调用
*
* @param key 键
* @param value 值
* @return 数据对象
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
}

View File

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

View File

@ -0,0 +1,114 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
/**
* 响应信息主体
*
* @author ruoyi
*/
public class R<T> implements Serializable
{
private static final long serialVersionUID = 1L;
/** 成功 */
public static final int SUCCESS = 0;
/** 失败 */
public static final int FAIL = 500;
private int code;
private String msg;
private T data;
public static <T> R<T> ok()
{
return restResult(null, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data)
{
return restResult(data, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data, String msg)
{
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail()
{
return restResult(null, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg)
{
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data)
{
return restResult(data, FAIL, "操作失败");
}
public static <T> R<T> fail(T data, String msg)
{
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg)
{
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg)
{
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
public static <T> Boolean isError(R<T> ret)
{
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret)
{
return R.SUCCESS == ret.getCode();
}
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.common.core.domain.entity;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@ -30,7 +31,7 @@ public class SysDept extends BaseEntity
private String deptName;
/** 显示顺序 */
private String orderNum;
private Integer orderNum;
/** 负责人 */
private String leader;
@ -95,13 +96,13 @@ public class SysDept extends BaseEntity
this.deptName = deptName;
}
@NotBlank(message = "显示顺序不能为空")
public String getOrderNum()
@NotNull(message = "显示顺序不能为空")
public Integer getOrderNum()
{
return orderNum;
}
public void setOrderNum(String orderNum)
public void setOrderNum(Integer orderNum)
{
this.orderNum = orderNum;
}

View File

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

View File

@ -56,6 +56,7 @@ public class SysDictType extends BaseEntity
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
public String getDictType()
{
return dictType;

View File

@ -1,5 +1,6 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Set;
import javax.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@ -52,6 +53,9 @@ public class SysRole extends BaseEntity
/** 部门组(数据权限) */
private Long[] deptIds;
/** 角色菜单权限 */
private Set<String> permissions;
public SysRole()
{
@ -177,6 +181,16 @@ public class SysRole extends BaseEntity
this.deptIds = deptIds;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

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

View File

@ -562,17 +562,12 @@ public class Convert
switch (valueStr)
{
case "true":
return true;
case "false":
return false;
case "yes":
return true;
case "ok":
return true;
case "no":
return false;
case "1":
return true;
case "false":
case "no":
case "0":
return false;
default:
@ -718,7 +713,7 @@ public class Convert
}
if (value instanceof Double)
{
return new BigDecimal((Double) value);
return BigDecimal.valueOf((Double) value);
}
if (value instanceof Integer)
{

View File

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

View File

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

View File

@ -18,7 +18,7 @@ public class InvalidExtensionException extends FileUploadException
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;

View File

@ -82,7 +82,7 @@ public class DictUtils
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas))
if (StringUtils.containsAny(dictValue, separator) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
@ -122,7 +122,7 @@ public class DictUtils
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
if (StringUtils.containsAny(dictLabel, separator) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{

View File

@ -11,6 +11,12 @@ import javax.servlet.http.HttpServletRequest;
*/
public class IpUtils
{
/**
* 获取客户端IP
*
* @param request 请求对象
* @return IP地址
*/
public static String getIpAddr(HttpServletRequest request)
{
if (request == null)
@ -40,15 +46,27 @@ public class IpUtils
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
}
/**
* 检查是否为内部IP地址
*
* @param ip IP地址
* @return 结果
*/
public static boolean internalIp(String ip)
{
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
/**
* 检查是否为内部IP地址
*
* @param addr byte地址
* @return 结果
*/
private static boolean internalIp(byte[] addr)
{
if (StringUtils.isNull(addr) || addr.length < 2)
@ -109,7 +127,8 @@ public class IpUtils
{
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
if ((l < 0L) || (l > 4294967295L))
{
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
@ -119,12 +138,14 @@ public class IpUtils
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
if ((l < 0L) || (l > 255L))
{
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
if ((l < 0L) || (l > 16777215L))
{
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
@ -135,13 +156,15 @@ public class IpUtils
for (i = 0; i < 2; ++i)
{
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
if ((l < 0L) || (l > 255L))
{
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
if ((l < 0L) || (l > 65535L))
{
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
@ -151,7 +174,8 @@ public class IpUtils
for (i = 0; i < 4; ++i)
{
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
if ((l < 0L) || (l > 255L))
{
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
@ -168,6 +192,11 @@ public class IpUtils
return bytes;
}
/**
* 获取IP地址
*
* @return 本地IP地址
*/
public static String getHostIp()
{
try
@ -180,6 +209,11 @@ public class IpUtils
return "127.0.0.1";
}
/**
* 获取主机名
*
* @return 本地主机名
*/
public static String getHostName()
{
try
@ -191,4 +225,39 @@ public class IpUtils
}
return "未知";
}
/**
* 从多级反向代理中获得第一个非unknown IP地址
*
* @param ip 获得的IP地址
* @return 第一个非unknown IP地址
*/
public static String getMultistageReverseProxyIp(String ip)
{
// 多级反向代理检测
if (ip != null && ip.indexOf(",") > 0)
{
final String[] ips = ip.trim().split(",");
for (String subIp : ips)
{
if (false == isUnknown(subIp))
{
ip = subIp;
break;
}
}
}
return ip;
}
/**
* 检测给定字符串是否为未知多用于检测HTTP请求相关
*
* @param checkString 被检测的字符串
* @return 是否未知
*/
public static boolean isUnknown(String checkString)
{
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
}
}

View File

@ -20,11 +20,16 @@ public class PageUtils extends PageHelper
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
/**
* 清理分页的线程变量
*/
public static void clearPage()
{
PageHelper.clearPage();
}
}

View File

@ -1,12 +1,16 @@
package com.ruoyi.common.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.Convert;
/**
@ -173,4 +177,40 @@ public class ServletUtils
}
return flag;
}
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str)
{
try
{
return URLEncoder.encode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str)
{
try
{
return URLDecoder.decode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
}

View File

@ -324,6 +324,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return list;
}
/**
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
*
* @param set 给定的集合
* @param array 给定的数组
* @return boolean 结果
*/
public static boolean containsAny(Collection<String> collection, String... array)
{
if (isEmpty(collection) || isEmpty(array))
{
return false;
}
else
{
for (String str : array)
{
if (collection.contains(str))
{
return true;
}
}
return false;
}
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*

View File

@ -1,87 +0,0 @@
package com.ruoyi.common.utils;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import com.ruoyi.common.utils.StringUtils;
/**
* 配置处理工具类
*
* @author yml
*/
public class YamlUtil
{
public static Map<?, ?> loadYaml(String fileName) throws FileNotFoundException
{
InputStream in = YamlUtil.class.getClassLoader().getResourceAsStream(fileName);
return StringUtils.isNotEmpty(fileName) ? (LinkedHashMap<?, ?>) new Yaml().load(in) : null;
}
public static void dumpYaml(String fileName, Map<?, ?> map) throws IOException
{
if (StringUtils.isNotEmpty(fileName))
{
FileWriter fileWriter = new FileWriter(YamlUtil.class.getResource(fileName).getFile());
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
yaml.dump(map, fileWriter);
}
}
public static Object getProperty(Map<?, ?> map, Object qualifiedKey)
{
if (map != null && !map.isEmpty() && qualifiedKey != null)
{
String input = String.valueOf(qualifiedKey);
if (!"".equals(input))
{
if (input.contains("."))
{
int index = input.indexOf(".");
String left = input.substring(0, index);
String right = input.substring(index + 1, input.length());
return getProperty((Map<?, ?>) map.get(left), right);
}
else if (map.containsKey(input))
{
return map.get(input);
}
else
{
return null;
}
}
}
return null;
}
@SuppressWarnings("unchecked")
public static void setProperty(Map<?, ?> map, Object qualifiedKey, Object value)
{
if (map != null && !map.isEmpty() && qualifiedKey != null)
{
String input = String.valueOf(qualifiedKey);
if (!input.equals(""))
{
if (input.contains("."))
{
int index = input.indexOf(".");
String left = input.substring(0, index);
String right = input.substring(index + 1, input.length());
setProperty((Map<?, ?>) map.get(left), right, value);
}
else
{
((Map<Object, Object>) map).put(qualifiedKey, value);
}
}
}
}
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.common.utils.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
@ -101,8 +102,8 @@ public class FileUploadUtils
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
@ -111,8 +112,8 @@ public class FileUploadUtils
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}

View File

@ -11,6 +11,7 @@ import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.config.RuoYiConfig;
@ -115,8 +116,7 @@ public class FileUtils
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists())
{
file.delete();
flag = true;
flag = file.delete();
}
return flag;
}
@ -255,7 +255,7 @@ public class FileUtils
}
/**
* 获取名称
* 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
*
* @param fileName 路径名称
* @return 没有文件路径的名称
@ -271,4 +271,21 @@ public class FileUtils
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
/**
* 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi
*
* @param fileName 路径名称
* @return 没有文件路径和后缀的名称
*/
public static String getNameNotSuffix(String fileName)
{
if (fileName == null)
{
return null;
}
String baseName = FilenameUtils.getBaseName(fileName);
return baseName;
}
}

View File

@ -7,12 +7,14 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@ -22,6 +24,9 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
@ -43,6 +48,7 @@ import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
@ -88,6 +94,8 @@ public class ExcelUtil<T>
{
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
@ -145,6 +153,26 @@ public class ExcelUtil<T>
*/
private short maxHeight;
/**
* 合并后最后行数
*/
private int subMergedLastRowNum = 0;
/**
* 合并后开始行数
*/
private int subMergedFirstRowNum = 1;
/**
* 对象的子列表方法
*/
private Method subMethod;
/**
* 对象的子列表属性
*/
private List<Field> subFields;
/**
* 统计列表
*/
@ -160,11 +188,27 @@ public class ExcelUtil<T>
*/
public Class<T> clazz;
/**
* 需要排除列属性
*/
public String[] excludeFields;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
/**
* 隐藏Excel中列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
* @throws Exception
*/
public void hideColumn(String... fields)
{
this.excludeFields = fields;
}
public void init(List<T> list, String sheetName, String title, Type type)
{
if (list == null)
@ -178,6 +222,7 @@ public class ExcelUtil<T>
createExcelField();
createWorkbook();
createTitle();
createSubHead();
}
/**
@ -187,13 +232,48 @@ public class ExcelUtil<T>
{
if (StringUtils.isNotEmpty(title))
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
titleLastCol = titleLastCol + subFields.size() - 1;
}
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(),
this.fields.size() - 1));
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
}
}
/**
* 创建对象的子列表名称
*/
public void createSubHead()
{
if (isSubList())
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum);
int excelNum = 0;
for (Object[] objects : fields)
{
Excel attr = (Excel) objects[1];
Cell headCell1 = subRow.createCell(excelNum);
headCell1.setCellValue(attr.name());
headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
excelNum++;
}
int headFirstRow = excelNum - 1;
int headLastRow = headFirstRow + subFields.size() - 1;
if (headLastRow > headFirstRow)
{
sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
}
rownum++;
}
}
@ -316,7 +396,7 @@ public class ExcelUtil<T>
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
if (StringUtils.isNotEmpty(dateFormat))
{
val = parseDateToStr(dateFormat, (Date) val);
val = parseDateToStr(dateFormat, val);
}
else
{
@ -328,7 +408,7 @@ public class ExcelUtil<T>
{
val = Convert.toInt(val);
}
else if (Long.TYPE == fieldType || Long.class == fieldType)
else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
{
val = Convert.toLong(val);
}
@ -573,8 +653,20 @@ public class ExcelUtil<T>
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
if (Collection.class.isAssignableFrom(field.getType()))
{
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++);
}
}
else
{
this.createHeadCell(excel, row, column++);
}
}
if (Type.EXPORT.equals(type))
{
@ -590,21 +682,67 @@ public class ExcelUtil<T>
* @param index 序号
* @param row 单元格行
*/
@SuppressWarnings("unchecked")
public void fillExcelData(int index, Row row)
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
int rowNo = (1 + rownum) - startNo;
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 + rownum - startNo);
rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0;
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.addCell(excel, row, vo, field, column++);
if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
{
boolean subFirst = false;
for (Object obj : subList)
{
if (subFirst)
{
rowNo++;
row = sheet.createRow(rowNo);
}
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
}
subIndex++;
}
subFirst = true;
}
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
}
else
{
this.addCell(excel, row, vo, field, column++);
}
}
}
}
@ -646,20 +784,6 @@ public class ExcelUtil<T>
style.setFont(dataFont);
styles.put("data", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
@ -669,35 +793,105 @@ public class ExcelUtil<T>
style.setFont(totalFont);
styles.put("total", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
styles.putAll(annotationHeaderStyles(wb, styles));
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
styles.putAll(annotationDataStyles(wb));
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
return styles;
}
/**
* 根据Excel注解创建表格头样式
*
* @param wb 工作薄对象
* @return 自定义样式列表
*/
private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
{
Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
if (!headerStyles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setFillForegroundColor(excel.headerBackgroundColor().index);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(excel.headerColor().index);
style.setFont(headerFont);
headerStyles.put(key, style);
}
}
return headerStyles;
}
/**
* 根据Excel注解创建表格列样式
*
* @param wb 工作薄对象
* @return 自定义样式列表
*/
private Map<String, CellStyle> annotationDataStyles(Workbook wb)
{
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style.setAlignment(excel.align());
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
dataFont.setColor(excel.color().index);
style.setFont(dataFont);
styles.put(key, style);
}
}
return styles;
}
/**
* 创建单元格
*/
public Cell createCell(Excel attr, Row row, int column)
public Cell createHeadCell(Excel attr, Row row, int column)
{
// 创建列
Cell cell = row.createCell(column);
// 写入列信息
cell.setCellValue(attr.name());
setDataValidation(attr, row, column);
cell.setCellStyle(styles.get("header"));
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
}
}
return cell;
}
@ -714,9 +908,13 @@ public class ExcelUtil<T>
{
String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入。
if (StringUtils.containsAny(cellValue, FORMULA_STR))
if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
{
cellValue = StringUtils.replaceEach(cellValue, FORMULA_STR, new String[] { "\t=", "\t-", "\t+", "\t@" });
cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
}
if (value instanceof Collection && StringUtils.equals("[]", cellValue))
{
cellValue = StringUtils.EMPTY;
}
cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
}
@ -783,17 +981,18 @@ public class ExcelUtil<T>
// 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
}
// 如果设置了提示信息则鼠标放上去提示.
if (StringUtils.isNotEmpty(attr.prompt()))
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
{
// 这里默认设了2-101列提示.
setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
}
// 如果设置了combo属性则本列只能选择不能输入
if (attr.combo().length > 0)
{
// 这里默认设了2-101列只能选择不能输入.
setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
{
// 如果下拉数大于15或字符串长度大于255则使用一个新sheet存储避免生成的模板下拉值获取不到
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
}
else
{
// 提示信息或只能选择不能输入的列内容.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
}
}
}
@ -812,8 +1011,12 @@ public class ExcelUtil<T>
{
// 创建cell
cell = row.createCell(column);
int align = attr.align().value();
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
}
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
@ -823,7 +1026,7 @@ public class ExcelUtil<T>
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
cell.setCellValue(parseDateToStr(dateFormat, (Date) value));
cell.setCellValue(parseDateToStr(dateFormat, value));
}
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{
@ -835,7 +1038,7 @@ public class ExcelUtil<T>
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
@ -857,48 +1060,78 @@ public class ExcelUtil<T>
}
/**
* 设置 POI XSSFSheet 单元格提示
* 设置 POI XSSFSheet 单元格提示或选择框
*
* @param sheet 表单
* @param promptTitle 提示标题
* @param textlist 下拉框显示的内容
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
*/
public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
int firstCol, int endCol)
{
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
DataValidation dataValidation = helper.createValidation(constraint, regions);
dataValidation.createPromptBox(promptTitle, promptContent);
dataValidation.setShowPromptBox(true);
if (StringUtils.isNotEmpty(promptContent))
{
// 如果设置了提示信息则鼠标放上去提示
dataValidation.createPromptBox("", promptContent);
dataValidation.setShowPromptBox(true);
}
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation)
{
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
}
else
{
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
}
/**
* 设置某些列的值只能输入预制的数据,显示下拉框.
* 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框).
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public void setXSSFValidation(Sheet sheet, String[] textlist, 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;
Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
Name name = wb.createName();
name.setNameName(hideSheetName + "_data");
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容
DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, regions);
if (StringUtils.isNotEmpty(promptContent))
{
// 如果设置了提示信息则鼠标放上去提示
dataValidation.createPromptBox("", promptContent);
dataValidation.setShowPromptBox(true);
}
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation)
{
@ -911,6 +1144,8 @@ public class ExcelUtil<T>
}
sheet.addValidationData(dataValidation);
// 设置hiddenSheet隐藏
wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
}
/**
@ -928,7 +1163,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@ -965,7 +1200,7 @@ public class ExcelUtil<T>
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
if (StringUtils.containsAny(propertyValue, separator))
{
for (String value : propertyValue.split(separator))
{
@ -1178,29 +1413,39 @@ public class ExcelUtil<T>
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
}
}
}
@ -1429,4 +1674,61 @@ public class ExcelUtil<T>
}
return str;
}
/**
* 是否有对象的子列表
*/
public boolean isSubList()
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0;
}
/**
* 是否有对象的子列表,集合不为空
*/
public boolean isSubListValue(T vo)
{
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
}
/**
* 获取集合的值
*/
public Collection<?> getListCellValue(Object obj)
{
Object value;
try
{
value = subMethod.invoke(obj, new Object[] {});
}
catch (Exception e)
{
return new ArrayList<Object>();
}
return (Collection<?>) value;
}
/**
* 获取对象的子列表方法
*
* @param name 名称
* @param pojoClass 类对象
* @return 子列表方法
*/
public Method getSubMethod(String name, Class<?> pojoClass)
{
StringBuffer getMethodName = new StringBuffer("get");
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
Method method = null;
try
{
method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
}
catch (Exception e)
{
log.error("获取对象异常{}", e.getMessage());
}
return method;
}
}

View File

@ -1,146 +1,159 @@
package com.ruoyi.common.utils.spring;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
/**
* spring工具类 方便在非spring管理环境中获取bean
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到将会抛出一个异常NoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
}
/**
* 获取当前的环境配置无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile()
{
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}
package com.ruoyi.common.utils.spring;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
/**
* spring工具类 方便在非spring管理环境中获取bean
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到将会抛出一个异常NoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
}
/**
* 获取当前的环境配置无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile()
{
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
/**
* 获取配置文件中的值
*
* @param key 配置文件的key
* @return 当前的配置文件的值
*
*/
public static String getRequiredProperty(String key)
{
return applicationContext.getEnvironment().getRequiredProperty(key);
}
}

View File

@ -13,7 +13,7 @@ public class SqlUtil
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.3</version>
<version>4.7.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -17,8 +17,8 @@
<dependencies>
<!-- SpringBoot Web容器 -->
<dependency>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
@ -37,7 +37,7 @@
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<exclusions>
<exclusion>

View File

@ -1,13 +1,17 @@
package com.ruoyi.framework.aspectj;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.context.PermissionContextHolder;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
@ -66,8 +70,9 @@ public class DataScopeAspect
// 如果是超级管理员,则不过滤数据
if (!currentUser.isAdmin())
{
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias());
controllerDataScope.userAlias(), permission);
}
}
}
@ -79,14 +84,25 @@ public class DataScopeAspect
* @param user 用户
* @param deptAlias 部门别名
* @param userAlias 用户别名
* @param permission 权限字符
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
{
StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<String>();
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
{
continue;
}
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
@ -117,9 +133,10 @@ public class DataScopeAspect
else
{
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 ");
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
}
}
conditions.add(dataScope);
}
if (StringUtils.isNotBlank(sqlString.toString()))

View File

@ -82,7 +82,7 @@ public class LogAspect
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
if (currentUser != null)
{
operLog.setOperName(currentUser.getLoginName());

View File

@ -0,0 +1,30 @@
package com.ruoyi.framework.aspectj;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.context.PermissionContextHolder;
import com.ruoyi.common.utils.StringUtils;
/**
* 自定义权限拦截器,将权限字符串放到当前请求中以便用于多个角色匹配符合要求的权限
*
* @author ruoyi
*/
@Aspect
@Component
public class PermissionsAspect
{
@Before("@annotation(controllerRequiresPermissions)")
public void doBefore(JoinPoint point, RequiresPermissions controllerRequiresPermissions) throws Throwable
{
handleRequiresPermissions(point, controllerRequiresPermissions);
}
protected void handleRequiresPermissions(final JoinPoint joinPoint, RequiresPermissions requiresPermissions)
{
PermissionContextHolder.setContext(StringUtils.join(requiresPermissions.value(), ","));
}
}

View File

@ -28,6 +28,7 @@ import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
import com.ruoyi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
@ -266,7 +267,7 @@ public class ShiroConfig
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
// Shiro的核心安全接口,这个属性是必须的
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 身份认证失败,则跳转到登录页面的配置

View File

@ -1,10 +1,13 @@
package com.ruoyi.framework.shiro.service;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.user.CaptchaException;
@ -19,6 +22,7 @@ import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysUserService;
/**
@ -35,6 +39,9 @@ public class SysLoginService
@Autowired
private ISysUserService userService;
@Autowired
private ISysMenuService menuService;
/**
* 登录
*/
@ -104,6 +111,7 @@ public class SysLoginService
passwordService.validate(user, password);
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
setRolePermission(user);
recordLoginInfo(user.getUserId());
return user;
}
@ -128,6 +136,25 @@ public class SysLoginService
}
*/
/**
* 设置角色权限
*
* @param user 用户信息
*/
public void setRolePermission(SysUser user)
{
List<SysRole> roles = user.getRoles();
if (!roles.isEmpty() && roles.size() > 1)
{
// 多角色设置permissions属性以便数据权限匹配权限
for (SysRole role : roles)
{
Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
}
}
}
/**
* 记录登录信息
*

View File

@ -58,7 +58,7 @@ public class SysRegisterService
{
msg = "账户长度必须在2到20个字符之间";
}
else if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(loginName)))
else if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user)))
{
msg = "保存用户'" + loginName + "'失败,注册账号已存在";
}
@ -67,7 +67,7 @@ public class SysRegisterService
user.setPwdUpdateDate(DateUtils.getNowDate());
user.setUserName(loginName);
user.setSalt(ShiroUtils.randomSalt());
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
user.setPassword(passwordService.encryptPassword(loginName, password, user.getSalt()));
boolean regFlag = userService.registerUser(user);
if (!regFlag)
{

View File

@ -7,7 +7,6 @@ import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.web.session.mgt.WebSessionContext;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.IpUtils;
import com.ruoyi.common.utils.ServletUtils;
import eu.bitwalker.useragentutils.UserAgent;
/**
@ -28,7 +27,7 @@ public class OnlineSessionFactory implements SessionFactory
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
if (request != null)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器

View File

@ -0,0 +1,85 @@
package com.ruoyi.framework.shiro.web;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.InvalidRequestFilter;
import org.apache.shiro.web.filter.mgt.DefaultFilter;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.beans.factory.BeanInitializationException;
import javax.servlet.Filter;
import java.util.Map;
/**
* 自定义ShiroFilterFactoryBean解决资源中文路径问题
*
* @author ruoyi
*/
public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean
{
@Override
public Class<MySpringShiroFilter> getObjectType()
{
return MySpringShiroFilter.class;
}
@Override
protected AbstractShiroFilter createInstance() throws Exception
{
SecurityManager securityManager = getSecurityManager();
if (securityManager == null)
{
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager))
{
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
// Expose the constructed FilterChainManager by first wrapping it in a
// FilterChainResolver implementation. The AbstractShiroFilter implementations
// do not know about FilterChainManagers - only resolvers:
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
Map<String, Filter> filterMap = manager.getFilters();
Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
if (invalidRequestFilter instanceof InvalidRequestFilter)
{
// 此处是关键,设置false跳过URL携带中文400servletPath中文校验bug
((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
}
// Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
// FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
// here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
// injection of the SecurityManager and FilterChainResolver:
return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
private static final class MySpringShiroFilter extends AbstractShiroFilter
{
protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver)
{
if (webSecurityManager == null)
{
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
else
{
this.setSecurityManager(webSecurityManager);
if (resolver != null)
{
this.setFilterChainResolver(resolver);
}
}
}
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.3</version>
<version>4.7.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -222,7 +222,7 @@ public class GenController extends BaseController
catch (Exception e)
{
logger.error(e.getMessage(), e);
return AjaxResult.error("创建表结构异常[" + e.getMessage() + "]");
return AjaxResult.error("创建表结构异常");
}
}

View File

@ -63,7 +63,7 @@ public class GenTableColumn extends BaseEntity
private String htmlType;
/** 字典类型 */
private String dictType;
private String dictType = "";
/** 排序 */
private Integer sort;

View File

@ -130,9 +130,9 @@ public class GenTableServiceImpl implements IGenTableService
int row = genTableMapper.updateGenTable(genTable);
if (row > 0)
{
for (GenTableColumn cenTableColumn : genTable.getColumns())
for (GenTableColumn genTableColumn : genTable.getColumns())
{
genTableColumnMapper.updateGenTableColumn(cenTableColumn);
genTableColumnMapper.updateGenTableColumn(genTableColumn);
}
}
}

View File

@ -289,6 +289,7 @@
$(function() {
var options = {
url: prefix + "/column/list",
sidePagination: "client",
sortName: "sort",
sortOrder: "desc",
height: $(window).height() - 166,

View File

@ -160,8 +160,8 @@
<h4 class="form-header h4">${subTable.functionName}信息</h4>
<div class="row">
<div class="col-sm-12">
<button type="button" class="btn btn-white btn-sm" onclick="addColumn()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delColumn()"><i class="fa fa-minus"> 删除</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
@ -334,9 +334,7 @@
var name = $.common.sprintf("${subclassName}List[%s].${javaField}", index);
return $.common.dictToSelect(${javaField}Datas, value, name);
}
#if($foreach.count != $subTable.columns.size())
},
#end
#else
{
field: '${javaField}',
@ -346,34 +344,34 @@
var html = $.common.sprintf("<input class='form-control' type='text' name='${subclassName}List[%s].${javaField}' value='%s'>", index, value);
return html;
}
#if($foreach.count != $subTable.columns.size())
},
#end
#end
#end
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
}
}]
};
$.table.init(options);
});
function addColumn() {
function addRow() {
var count = $("#" + table.options.id).bootstrapTable('getData').length;
sub.editColumn();
$("#" + table.options.id).bootstrapTable('insertRow', {
index: count,
row: {
index: $.table.serialNumber(count),
var row = {
index: $.table.serialNumber(count),
#foreach($column in $subTable.columns)
#set($javaField=$column.javaField)
#if($column.pk || $javaField == ${subTableFkclassName})
#else
${javaField}: ""#if($foreach.count != $subTable.columns.size()),#end
${javaField}: "",
#end
#end
}
});
}
sub.addRow(row);
}
#end
</script>

View File

@ -160,8 +160,8 @@
<h4 class="form-header h4">${subTable.functionName}信息</h4>
<div class="row">
<div class="col-sm-12">
<button type="button" class="btn btn-white btn-sm" onclick="addColumn()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delColumn()"><i class="fa fa-minus"> 删除</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="addRow()"><i class="fa fa-plus"> 增加</i></button>
<button type="button" class="btn btn-white btn-sm" onclick="sub.delRow()"><i class="fa fa-minus"> 删除</i></button>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
@ -345,9 +345,7 @@
var name = $.common.sprintf("${subclassName}List[%s].${javaField}", index);
return $.common.dictToSelect(${javaField}Datas, value, name);
}
#if($foreach.count != $subTable.columns.size())
},
#end
#else
{
field: '${javaField}',
@ -357,34 +355,35 @@
var html = $.common.sprintf("<input class='form-control' type='text' name='${subclassName}List[%s].${javaField}' value='%s'>", index, value);
return html;
}
#if($foreach.count != $subTable.columns.size())
},
#end
#end
#end
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var value = $.common.isNotEmpty(row.index) ? row.index : $.table.serialNumber(index);
return '<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="sub.delRowByIndex(\'' + value + '\')"><i class="fa fa-remove"></i>删除</a>';
}
}]
};
$.table.init(options);
});
function addColumn() {
function addRow() {
var count = $("#" + table.options.id).bootstrapTable('getData').length;
sub.editColumn();
$("#" + table.options.id).bootstrapTable('insertRow', {
index: count,
row: {
index: $.table.serialNumber(count),
var row = {
index: $.table.serialNumber(count),
#foreach($column in $subTable.columns)
#set($javaField=$column.javaField)
#if($column.pk || $javaField == ${subTableFkclassName})
#else
${javaField}: ""#if($foreach.count != $subTable.columns.size()),#end
${javaField}: "",
#end
#end
}
});
}
sub.addRow(row);
}
#end
</script>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.3</version>
<version>4.7.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -111,8 +111,8 @@ public class SysJobController extends BaseController
@ResponseBody
public AjaxResult run(SysJob job) throws SchedulerException
{
jobService.run(job);
return success();
boolean result = jobService.run(job);
return result ? success() : error("任务不存在或已过期!");
}
/**

View File

@ -74,7 +74,7 @@ public interface ISysJobService
* @param job 调度信息
* @return 结果
*/
public void run(SysJob job) throws SchedulerException;
public boolean run(SysJob job) throws SchedulerException;
/**
* 新增任务

View File

@ -177,14 +177,21 @@ public class SysJobServiceImpl implements ISysJobService
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void run(SysJob job) throws SchedulerException
public boolean run(SysJob job) throws SchedulerException
{
boolean result = false;
Long jobId = job.getJobId();
SysJob tmpObj = selectJobById(job.getJobId());
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES, tmpObj);
scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, tmpObj.getJobGroup()), dataMap);
JobKey jobKey = ScheduleUtils.getJobKey(jobId, tmpObj.getJobGroup());
if (scheduler.checkExists(jobKey))
{
result = true;
scheduler.triggerJob(jobKey, dataMap);
}
return result;
}
/**

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