70 Commits

Author SHA1 Message Date
6d3c988768 若依 v4.7.1 2021-11-10 09:12:31 +08:00
618b81bc93 增加sendGet无参请求方法 2021-11-09 16:52:38 +08:00
16248b6e12 添加新群号:264355400 2021-11-09 09:03:21 +08:00
ceba6a91f0 表格实例切换event不能为空 2021-11-08 15:32:57 +08:00
d005057c98 !341 update ruoyi-admin/src/main/resources/static/ruoyi/js/common.js.
Merge pull request !341 from Hacker/N/A
2021-11-01 07:28:19 +00:00
e4738da6fa !340 update ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js.
Merge pull request !340 from Hacker/N/A
2021-11-01 07:22:39 +00:00
ed8834075e update ruoyi-admin/src/main/resources/static/ruoyi/js/common.js.
input 数字输入框无法删除内容
2021-11-01 07:22:37 +00:00
13bba13d6a update ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js. 2021-11-01 07:21:20 +00:00
e0b7910d5e 修复无法被反转义问题 2021-10-30 10:58:58 +08:00
086458b89d 多表格切换表单查询参数 2021-10-30 10:28:20 +08:00
775d77ee6d 任务屏蔽违规字符 2021-10-30 10:27:07 +08:00
7c1fa482ba 页签关闭右侧清除iframe元素 2021-10-28 15:45:37 +08:00
7be993eb8d 升级spring-boot到最新版本2.5.6 2021-10-27 15:10:28 +08:00
5a9e87c60d 替换自定义验证注解 2021-10-26 16:44:18 +08:00
5f836d249c update ry.sh. 2021-10-22 14:49:41 +08:00
1d0175fb87 !337 修正别字
Merge pull request !337 from 网游之鱼/N/A
2021-10-22 03:24:05 +00:00
774cff9c52 修正别字 2021-10-16 06:49:37 +00:00
51251331cf 升级oshi到最新版本v5.8.2 2021-10-14 11:58:31 +08:00
2b1c90d249 !335 修改阿里云 Maven 仓库地址为新版地址
Merge pull request !335 from 网游之鱼/N/A
2021-10-14 03:57:24 +00:00
14ca1e5c40 注释掉前端传到后端的排序字段 2021-10-13 15:43:13 +08:00
0efa04946b 升级spring-boot-mybatis到最新版2.2.0 2021-10-12 09:57:23 +08:00
96286d5836 升级pagehelper到最新版1.4.0 2021-10-12 09:57:05 +08:00
07e933de5c 升级spring-boot到最新版本2.5.5 2021-10-12 09:56:25 +08:00
2ec5eab7bb 调整表单向导文字描述 2021-10-12 09:01:44 +08:00
601cc1060c 修改阿里云 Maven 仓库地址为新版地址 2021-10-11 01:10:58 +00:00
a6bc8e342d Excel导入支持@Excels注解 2021-10-10 16:04:51 +08:00
30c603a733 升级druid到最新版1.2.8 2021-10-10 09:43:16 +08:00
a10d09f293 修复select2回退键被禁止问题 2021-10-09 09:39:38 +08:00
5493e21bfd 导入模板添加默认参数 2021-10-09 09:39:26 +08:00
59217e59d0 !334 增加 sendGet 无参判断
Merge pull request !334 from 网游之鱼/N/A
2021-10-09 01:29:52 +00:00
03b977f5cb 增加 sendGet 无参判断 2021-10-08 03:41:22 +00:00
b8a8583598 修复apple/webkit浏览器时间无法格式化 2021-10-03 20:04:38 +08:00
4f50365ac1 设置mybatis默认的执行器 2021-10-03 20:04:21 +08:00
ee9ff26594 修复新窗口打开页面关闭弹窗报错 2021-09-30 15:58:21 +08:00
af7339f3b0 优化导入Excel 2021-09-30 15:57:30 +08:00
0224f58e52 修复拖拽行数据错位问题 2021-09-30 15:55:38 +08:00
05ee2d0bf4 修正swagger没有指定dataTypeClass导致启动出现warn日志 2021-09-29 18:58:30 +08:00
54d338807e 优化代码生成创建表结构功能 2021-09-29 18:57:52 +08:00
4b6ed674b3 !333 update ruoyi-generator/src/main/resources/templates/tool/gen/edit.html.
Merge pull request !333 from 偶滴神啊/N/A
2021-09-29 10:56:19 +00:00
32ec900f87 !332 启动脚本中参数[-jar]和参数值[AppName]对应写到一起
Merge pull request !332 from lixifun/启动脚本修改
2021-09-29 10:54:21 +00:00
5b160a275b !331 代码生成的模块增加创建表功能。
Merge pull request !331 from 刘宗奇/master
2021-09-29 10:35:37 +00:00
c6b6295b26 update ruoyi-generator/src/main/resources/templates/tool/gen/edit.html.
我本地碰到了  undefined 的时候 
var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].dictType' value='%s' id='columns_dict_%s'>", index, value, row.columnId);
不生效
2021-09-29 03:41:26 +00:00
c11ac2e565 启动脚本中的 参数 [-jar] 和参数值 [AppName] 对应写到一起 2021-09-27 14:13:26 +08:00
912366563b 代码生成功能,增加创建表的功能。 2021-09-26 16:04:44 +08:00
61007b2905 Excel注解支持导入导出标题信息 2021-09-26 09:00:36 +08:00
db83718aa6 修复树表代码生成短字段无法识别问题 2021-09-25 09:57:40 +08:00
4c46e41525 !329 🔥 Remove code. 移除无用代码
Merge pull request !329 from Hacker/N/A
2021-09-25 01:54:25 +00:00
69d31e301f 优化记录登录信息,防止不必要的修改 2021-09-24 14:47:25 +08:00
314f0e94da 🔥 Remove code. 移除无用代码
Remove code. 移除无用代码
2021-09-24 03:22:59 +00:00
ff3d2134a5 新增是否开启页签功能 2021-09-24 09:22:43 +08:00
4a6194274a 升级fastjson到最新版1.2.78 2021-09-24 08:52:30 +08:00
bf222b392b 升级thymeleaf-extras-shiro到最新版本v2.1.0 2021-09-23 15:34:58 +08:00
7aebe466d9 Excel注解支持自定义数据处理器 2021-09-22 09:02:39 +08:00
777b05ce6a 防重提交注解支持配置间隔时间/提示消息 2021-09-20 18:43:55 +08:00
9046b96941 reset dataSourceAspect 2021-09-20 18:41:13 +08:00
eb6f4c7f92 优化aop语法,使用spring自动注入注解 2021-09-19 08:50:44 +08:00
d3899a8d9e 防止Excel导入图片可能出现的异常 2021-09-19 08:50:31 +08:00
4315c0983d 修复富文本回退键被禁止&控制台报错问题 2021-09-18 20:09:01 +08:00
3ea3edc6ba update year 2021-09-18 09:51:04 +08:00
dc18ca2274 修复后端主子表代码模板方法名生成错误问题 2021-09-18 09:50:18 +08:00
8fadbef031 日志注解新增是否保存响应参数 2021-09-16 08:58:19 +08:00
7187161621 禁止后退键(Backspace) 2021-09-14 17:07:38 +08:00
17afe54f6f 升级bootstrap-fileinput到最新版本v5.2.4 2021-09-10 15:38:29 +08:00
8ed485c28f !328 update ruoyi-admin/src/main/resources/static/ruoyi/login.js.
Merge pull request !328 from 孙鹏/N/A
2021-09-10 07:31:32 +00:00
b307655251 update ruoyi-admin/src/main/resources/static/ruoyi/login.js.
修改了在IntelliJ IDEA中 ‘空格’ 展示为 ‘NBSP’ 的问题。
2021-09-10 06:40:51 +00:00
38f7ecb671 实例演示中增加多层窗口获取值 2021-09-06 16:44:29 +08:00
f51b4f40f1 弹出层openOptions增加动画属性 2021-09-06 16:44:05 +08:00
1530644de5 !327 小写不起作用,大写后功能正常
Merge pull request !327 from yangyang/N/A
2021-09-06 08:19:35 +00:00
79fee39b2a 小写不起作用,大写后功能正常 2021-09-06 03:39:26 +00:00
c44c9187a9 代码生成导入表按创建时间排序 2021-09-03 09:54:57 +08:00
77 changed files with 2131 additions and 1518 deletions

View File

@ -88,4 +88,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群 [![加入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)

24
pom.xml
View File

@ -5,29 +5,29 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>4.7.0</version> <version>4.7.1</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依管理系统</description> <description>若依管理系统</description>
<properties> <properties>
<ruoyi.version>4.7.0</ruoyi.version> <ruoyi.version>4.7.1</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<shiro.version>1.8.0</shiro.version> <shiro.version>1.8.0</shiro.version>
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version> <thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
<druid.version>1.2.6</druid.version> <druid.version>1.2.8</druid.version>
<bitwalker.version>1.21</bitwalker.version> <bitwalker.version>1.21</bitwalker.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<swagger.version>3.0.0</swagger.version> <swagger.version>3.0.0</swagger.version>
<mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version> <mybatis-spring-boot.version>2.2.0</mybatis-spring-boot.version>
<pagehelper.boot.version>1.3.1</pagehelper.boot.version> <pagehelper.boot.version>1.4.0</pagehelper.boot.version>
<fastjson.version>1.2.76</fastjson.version> <fastjson.version>1.2.78</fastjson.version>
<oshi.version>5.8.0</oshi.version> <oshi.version>5.8.2</oshi.version>
<jna.version>5.8.0</jna.version> <jna.version>5.9.0</jna.version>
<commons.io.version>2.11.0</commons.io.version> <commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version> <commons.fileupload.version>1.4</commons.fileupload.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
@ -42,7 +42,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>
<version>2.2.13.RELEASE</version> <version>2.5.6</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -255,7 +255,7 @@
<repository> <repository>
<id>public</id> <id>public</id>
<name>aliyun nexus</name> <name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> <url>https://maven.aliyun.com/repository/public</url>
<releases> <releases>
<enabled>true</enabled> <enabled>true</enabled>
</releases> </releases>
@ -266,7 +266,7 @@
<pluginRepository> <pluginRepository>
<id>public</id> <id>public</id>
<name>aliyun nexus</name> <name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> <url>https://maven.aliyun.com/repository/public</url>
<releases> <releases>
<enabled>true</enabled> <enabled>true</enabled>
</releases> </releases>

View File

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

View File

@ -77,4 +77,22 @@ public class DemoDialogController
{ {
return prefix + "/table/parent"; return prefix + "/table/parent";
} }
/**
* 多层窗口frame1
*/
@GetMapping("/frame1")
public String frame1()
{
return prefix + "/table/frame1";
}
/**
* 多层窗口frame2
*/
@GetMapping("/frame2")
public String frame2()
{
return prefix + "/table/frame2";
}
} }

View File

@ -55,7 +55,11 @@ public class SysIndexController extends BaseController
mmap.put("user", user); mmap.put("user", user);
mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme")); mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName")); mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
mmap.put("ignoreFooter", configService.selectConfigByKey("sys.index.ignoreFooter")); Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true);
Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true);
mmap.put("footer", footer);
mmap.put("tagsView", tagsView);
mmap.put("mainClass", contentMainClass(footer, tagsView));
mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear()); mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear());
mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled()); mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled());
mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate())); mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
@ -98,7 +102,7 @@ public class SysIndexController extends BaseController
SysUser user = getSysUser(); SysUser user = getSysUser();
if (StringUtils.isNull(user)) if (StringUtils.isNull(user))
{ {
return AjaxResult.error("服务器超时,请重新登"); return AjaxResult.error("服务器超时,请重新登");
} }
if (passwordService.matches(user, password)) if (passwordService.matches(user, password))
{ {
@ -130,6 +134,24 @@ public class SysIndexController extends BaseController
return "main"; return "main";
} }
// content-main class
public String contentMainClass(Boolean footer, Boolean tagsView)
{
if (!footer && !tagsView)
{
return "tagsview-footer-hide";
}
else if (!footer)
{
return "footer-hide";
}
else if (!tagsView)
{
return "tagsview-hide";
}
return StringUtils.EMPTY;
}
// 检查初始密码是否提醒修改 // 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate) public boolean initPasswordIsModify(Date pwdUpdateDate)
{ {

View File

@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.ConfigService; import com.ruoyi.framework.web.service.ConfigService;
@ -47,7 +48,7 @@ public class SysLoginController extends BaseController
// 是否开启记住我 // 是否开启记住我
mmap.put("isRemembered", rememberMe); mmap.put("isRemembered", rememberMe);
// 是否开启用户注册 // 是否开启用户注册
mmap.put("isAllowRegister", configService.getKey("sys.account.registerUser")); mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false));
return "login"; return "login";
} }

View File

@ -2,13 +2,13 @@ package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.shiro.service.SysRegisterService; import com.ruoyi.framework.shiro.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;

View File

@ -47,7 +47,7 @@ public class TestController extends BaseController
} }
@ApiOperation("获取用户详细") @ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@GetMapping("/{userId}") @GetMapping("/{userId}")
public AjaxResult getUser(@PathVariable Integer userId) public AjaxResult getUser(@PathVariable Integer userId)
{ {
@ -63,10 +63,10 @@ public class TestController extends BaseController
@ApiOperation("新增用户") @ApiOperation("新增用户")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"), @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"), @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"), @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String") @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
}) })
@PostMapping("/save") @PostMapping("/save")
public AjaxResult save(UserEntity user) public AjaxResult save(UserEntity user)
@ -95,7 +95,7 @@ public class TestController extends BaseController
} }
@ApiOperation("删除用户信息") @ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@DeleteMapping("/{userId}") @DeleteMapping("/{userId}")
public AjaxResult delete(@PathVariable Integer userId) public AjaxResult delete(@PathVariable Integer userId)
{ {

View File

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

View File

@ -3,13 +3,18 @@
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <configuration>
<!-- 全局参数 -->
<settings> <settings>
<setting name="cacheEnabled" value="true" /> <!-- 全局映射器启用缓存 --> <!-- 使全局映射器启用或禁用缓存 -->
<setting name="useGeneratedKeys" value="true" /> <!-- 允许 JDBC 支持自动生成主键 --> <setting name="cacheEnabled" value="true" />
<setting name="defaultExecutorType" value="REUSE" /> <!-- 配置默认的执行器 --> <!-- 允许JDBC 支持自动生成主键 -->
<setting name="logImpl" value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 --> <setting name="useGeneratedKeys" value="true" />
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> 驼峰式命名 --> <!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
</settings> </settings>
</configuration> </configuration>

View File

@ -1,5 +1,5 @@
/*! /*!
* bootstrap-fileinput v5.2.3 * bootstrap-fileinput v5.2.4
* http://plugins.krajee.com/file-input * http://plugins.krajee.com/file-input
* *
* Krajee default styling for bootstrap-fileinput. * Krajee default styling for bootstrap-fileinput.
@ -179,15 +179,15 @@ input[type=file].file-loading {
} }
.file-caption.icon-visible .file-caption-name { .file-caption.icon-visible .file-caption-name {
padding-left: 1.875rem; padding-left: 25px;
} }
.file-caption.icon-visible > .input-group-lg .file-caption-name { .file-caption.icon-visible > .input-group-lg .file-caption-name {
padding-left: 2.1rem; padding-left: 30px;
} }
.file-caption.icon-visible > .input-group-sm .file-caption-name { .file-caption.icon-visible > .input-group-sm .file-caption-name {
padding-left: 1.5rem; padding-left: 22px;
} }
.file-caption-name:not(.file-caption-disabled) { .file-caption-name:not(.file-caption-disabled) {
@ -201,7 +201,7 @@ input[type=file].file-loading {
} }
.file-caption-icon { .file-caption-icon {
padding: 0.5rem; padding: 7px 5px;
left: 4px; left: 4px;
} }

View File

@ -1,5 +1,5 @@
/*! /*!
* bootstrap-fileinput v5.2.3 * bootstrap-fileinput v5.2.4
* http://plugins.krajee.com/file-input * http://plugins.krajee.com/file-input
* *
* Author: Kartik Visweswaran * Author: Kartik Visweswaran
@ -45,13 +45,17 @@
}; };
} }
var $h, FileInput; var $h, FileInput, getLoadingUrl = function () {
var src = document.currentScript.src, srcPath = src.substring(0, src.lastIndexOf("/"));
return srcPath + '/loading.gif'
};
// fileinput helper object for all global variables and internal helper methods // fileinput helper object for all global variables and internal helper methods
$h = { $h = {
FRAMES: '.kv-preview-thumb', FRAMES: '.kv-preview-thumb',
SORT_CSS: 'file-sortable', SORT_CSS: 'file-sortable',
INIT_FLAG: 'init-', INIT_FLAG: 'init-',
ZOOM_VAR: getLoadingUrl() + '?kvTemp__2873389129__=', // used to prevent 404 errors in URL parsing
OBJECT_PARAMS: '<param name="controller" value="true" />\n' + OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
'<param name="allowFullScreen" value="true" />\n' + '<param name="allowFullScreen" value="true" />\n' +
'<param name="allowScriptAccess" value="always" />\n' + '<param name="allowScriptAccess" value="always" />\n' +
@ -2972,7 +2976,7 @@
slideIn = 'slideIn' + dir, slideOut = 'slideOut' + dir, parsed, zoomData = $frame.data('zoom'); slideIn = 'slideIn' + dir, slideOut = 'slideOut' + dir, parsed, zoomData = $frame.data('zoom');
if (zoomData) { if (zoomData) {
zoomData = decodeURIComponent(zoomData); zoomData = decodeURIComponent(zoomData);
parsed = $zoomPreview.html().setTokens({zoomData: zoomData}); parsed = $zoomPreview.html().replace($h.ZOOM_VAR, '').setTokens({zoomData: zoomData});
$zoomPreview.html(parsed); $zoomPreview.html(parsed);
$frame.data('zoom', ''); $frame.data('zoom', '');
$zoomPreview.attr('data-zoom', zoomData); $zoomPreview.attr('data-zoom', zoomData);
@ -4231,7 +4235,8 @@
'fileid': fileId || '', 'fileid': fileId || '',
'typeCss': typeCss, 'typeCss': typeCss,
'footer': footer, 'footer': footer,
'data': zoom && vZoomData ? '{zoomData}' : vData, 'data': vData,
// 'data': zoom && vZoomData ? $h.ZOOM_VAR + '{zoomData}' : vData,
'template': templ || cat, 'template': templ || cat,
'style': styleAttribs ? 'style="' + styleAttribs + '"' : '', 'style': styleAttribs ? 'style="' + styleAttribs + '"' : '',
'zoomData': vZoomData ? encodeURIComponent(vZoomData) : '' 'zoomData': vZoomData ? encodeURIComponent(vZoomData) : ''

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -93,10 +93,26 @@ $.BootstrapTable = class extends $.BootstrapTable {
this.options.data.splice(this.options.data.indexOf(draggingRow), 1) this.options.data.splice(this.options.data.indexOf(draggingRow), 1)
this.options.data.splice(index, 0, draggingRow) this.options.data.splice(index, 0, draggingRow)
this.initSearch()
// Call the user defined function // Call the user defined function
this.options.onReorderRowsDrop(droppedRow) this.options.onReorderRowsDrop(droppedRow)
// Call the event reorder-row // Call the event reorder-row
this.trigger('reorder-row', newData, draggingRow, droppedRow) this.trigger('reorder-row', newData, draggingRow, droppedRow)
} }
initSearch () {
this.ignoreInitSort = true
super.initSearch()
}
initSort () {
if (this.ignoreInitSort) {
this.ignoreInitSort = false
return
}
super.initSort()
}
} }

File diff suppressed because one or more lines are too long

View File

@ -3344,6 +3344,21 @@ nav.page-tabs .page-tabs-content {
overflow: hidden; overflow: hidden;
} }
.tagsview-hide#content-main {
height: calc(100% - 88px);
overflow: hidden;
}
.footer-hide#content-main {
height: calc(100% - 91px);
overflow: hidden;
}
.tagsview-footer-hide#content-main {
height: calc(100% - 52px);
overflow: hidden;
}
.fixed-nav #content-main { .fixed-nav #content-main {
height: calc(100% - 80px); height: calc(100% - 80px);
overflow: hidden; overflow: hidden;

File diff suppressed because one or more lines are too long

View File

@ -309,7 +309,7 @@ $(function() {
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 + '" seamless></iframe>';
$('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1); $('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
$.modal.loading("数据加载中,请稍..."); $.modal.loading("数据加载中,请稍...");
$('.mainContent iframe:visible').on('load', function() { $('.mainContent iframe:visible').on('load', function() {
$.modal.closeLoading(); $.modal.closeLoading();
@ -601,7 +601,7 @@ $(function() {
callback: function(key, opt) { callback: function(key, opt) {
setActiveTab(this); setActiveTab(this);
this.nextAll('.menuTab').each(function() { this.nextAll('.menuTab').each(function() {
$('.menuTab[data-id="' + $(this).data('id') + '"]').remove(); $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
$(this).remove(); $(this).remove();
}); });
} }
@ -630,7 +630,7 @@ $(function() {
setActiveTab(this); setActiveTab(this);
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
var url = target.attr('src'); var url = target.attr('src');
$.modal.loading("数据加载中,请稍..."); $.modal.loading("数据加载中,请稍...");
target.attr('src', url).on('load', function() { target.attr('src', url).on('load', function() {
$.modal.closeLoading(); $.modal.closeLoading();
}); });
@ -645,5 +645,5 @@ $(function() {
} }
}, },
} }
}) });
}); });

View File

@ -289,7 +289,7 @@ function createMenuItem(dataUrl, menuName, isRefresh) {
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-panel="' + panelUrl + '" seamless></iframe>'; var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-panel="' + panelUrl + '" seamless></iframe>';
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1); $('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
window.parent.$.modal.loading("数据加载中,请稍..."); window.parent.$.modal.loading("数据加载中,请稍...");
$('.mainContent iframe:visible', topWindow).on('load', function() { $('.mainContent iframe:visible', topWindow).on('load', function() {
window.parent.$.modal.closeLoading(); window.parent.$.modal.closeLoading();
}); });
@ -351,8 +351,10 @@ function calSumWidth(elements) {
function activeWindow() { function activeWindow() {
var topWindow = $(window.parent.document); var topWindow = $(window.parent.document);
var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id'); var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
var activeWindow = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow; if (!currentId) {
return activeWindow; return window.parent;
}
return $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow;
} }
/** 密码规则范围验证 */ /** 密码规则范围验证 */
@ -490,6 +492,44 @@ function loadJs(file, headElem) {
else document.getElementsByTagName('head')[0].appendChild(script); else document.getElementsByTagName('head')[0].appendChild(script);
} }
// 禁止后退键Backspace
window.onload = function() {
document.getElementsByTagName("body")[0].onkeydown = function() {
// 获取事件对象
var elem = event.relatedTarget || event.srcElement || event.target || event.currentTarget;
// 判断按键为backSpace键
if (event.keyCode == 8) {
// 判断是否需要阻止按下键盘的事件默认传递
var name = elem.nodeName;
var className = elem.className;
// 屏蔽特定的样式名称
if (className.indexOf('note-editable') != -1)
{
return true;
}
if (name != 'INPUT' && name != 'TEXTAREA') {
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')) {
return _stopIt(event);
}
if (name == 'INPUT' && (elem.readOnly == true || elem.disabled == true)) {
return _stopIt(event);
}
}
};
};
function _stopIt(e) {
if (e.returnValue) {
e.returnValue = false;
}
if (e.preventDefault) {
e.preventDefault();
}
return false;
}
/** 设置全局ajax处理 */ /** 设置全局ajax处理 */
$.ajaxSetup({ $.ajaxSetup({
complete: function(XMLHttpRequest, textStatus) { complete: function(XMLHttpRequest, textStatus) {

View File

@ -10,7 +10,7 @@ var table = {
options: {}, options: {},
// 设置实例配置 // 设置实例配置
set: function(id) { set: function(id) {
if($.common.getLength(table.config) > 1) { 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; var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") : id;
if ($.common.isNotEmpty(tableId)) { if ($.common.isNotEmpty(tableId)) {
table.options = table.get(tableId); table.options = table.get(tableId);
@ -73,7 +73,7 @@ var table = {
fixedNumber: 0, fixedNumber: 0,
fixedRightNumber: 0, fixedRightNumber: 0,
queryParams: $.table.queryParams, queryParams: $.table.queryParams,
rowStyle: undefined, rowStyle: undefined
}; };
var options = $.extend(defaults, options); var options = $.extend(defaults, options);
table.options = options; table.options = options;
@ -163,6 +163,7 @@ var table = {
}, },
// 查询条件 // 查询条件
queryParams: function(params) { queryParams: function(params) {
table.set();
var curParams = { var curParams = {
// 传递参数查询参数 // 传递参数查询参数
pageSize: params.limit, pageSize: params.limit,
@ -373,7 +374,7 @@ var table = {
var dataParam = $("#" + currentId).serializeArray(); var dataParam = $("#" + currentId).serializeArray();
dataParam.push({ "name": "orderByColumn", "value": params.sortName }); dataParam.push({ "name": "orderByColumn", "value": params.sortName });
dataParam.push({ "name": "isAsc", "value": params.sortOrder }); dataParam.push({ "name": "isAsc", "value": params.sortOrder });
$.modal.loading("正在导出数据,请稍..."); $.modal.loading("正在导出数据,请稍...");
$.post(table.options.exportUrl, dataParam, function(result) { $.post(table.options.exportUrl, dataParam, function(result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true; window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true;
@ -447,6 +448,9 @@ var table = {
$.modal.enable(); $.modal.enable();
$.modal.alertError(result.msg); $.modal.alertError(result.msg);
} }
},
complete: function () {
layero.find('#file').val('');
} }
}); });
} }
@ -889,6 +893,8 @@ var table = {
} }
} }
var index = top.layer.open($.extend({ var index = top.layer.open($.extend({
id: options.id, // 唯一id
anim: options.anim, // 弹出动画 0-6
type: 2, type: 2,
maxmin: $.common.isEmpty(options.maxmin) ? true : options.maxmin, maxmin: $.common.isEmpty(options.maxmin) ? true : options.maxmin,
shade: 0.3, shade: 0.3,
@ -906,7 +912,7 @@ var table = {
} }
}, btnCallback)); }, btnCallback));
if ($.common.isNotEmpty(options.full) && options.full === true) { if ($.common.isNotEmpty(options.full) && options.full === true) {
layer.full(index); top.layer.full(index);
} }
}, },
// 弹出层全屏 // 弹出层全屏
@ -999,7 +1005,7 @@ var table = {
dataType: dataType, dataType: dataType,
data: data, data: data,
beforeSend: function () { beforeSend: function () {
$.modal.loading("正在处理中,请稍..."); $.modal.loading("正在处理中,请稍...");
}, },
success: function(result) { success: function(result) {
if (typeof callback == "function") { if (typeof callback == "function") {
@ -1174,7 +1180,7 @@ var table = {
dataType: "json", dataType: "json",
data: data, data: data,
beforeSend: function () { beforeSend: function () {
$.modal.loading("正在处理中,请稍..."); $.modal.loading("正在处理中,请稍...");
$.modal.disable(); $.modal.disable();
}, },
success: function(result) { success: function(result) {
@ -1194,7 +1200,7 @@ var table = {
dataType: "json", dataType: "json",
data: data, data: data,
beforeSend: function () { beforeSend: function () {
$.modal.loading("正在处理中,请稍..."); $.modal.loading("正在处理中,请稍...");
}, },
success: function(result) { success: function(result) {
if (typeof callback == "function") { if (typeof callback == "function") {
@ -1220,7 +1226,7 @@ var table = {
dataType: "json", dataType: "json",
data: data, data: data,
beforeSend: function () { beforeSend: function () {
$.modal.loading("正在处理中,请稍..."); $.modal.loading("正在处理中,请稍...");
}, },
success: function(result) { success: function(result) {
if (typeof callback == "function") { if (typeof callback == "function") {
@ -1423,7 +1429,6 @@ var table = {
}, },
// 隐藏所有节点 // 隐藏所有节点
hideAllNode: function(nodes) { hideAllNode: function(nodes) {
var tree = $.fn.zTree.getZTreeObj("tree");
var nodes = $._tree.transformToArray(nodes); var nodes = $._tree.transformToArray(nodes);
for (var i = nodes.length - 1; i >= 0; i--) { for (var i = nodes.length - 1; i >= 0; i--) {
$._tree.hideNode(nodes[i]); $._tree.hideNode(nodes[i]);
@ -1582,7 +1587,7 @@ var table = {
if (!format) format = "yyyy-MM-dd"; if (!format) format = "yyyy-MM-dd";
switch (typeof date) { switch (typeof date) {
case "string": case "string":
date = new Date(date.replace(/-/, "/")); date = new Date(date.replace(/-/g, "/"));
break; break;
case "number": case "number":
date = new Date(date); date = new Date(date);

View File

@ -76,11 +76,11 @@ function validateKickout() {
if (top != self) { if (top != self) {
top.location = self.location; top.location = self.location;
} else { } else {
var url  =  location.search; var url = location.search;
if (url) { if (url) {
var oldUrl  = window.location.href; var oldUrl = window.location.href;
var newUrl  = oldUrl.substring(0,  oldUrl.indexOf('?')); var newUrl = oldUrl.substring(0, oldUrl.indexOf('?'));
self.location  = newUrl; self.location = newUrl;
} }
} }
}); });

View File

@ -17,7 +17,7 @@
<h2>若依后台管理系统</h2> <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>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> <p>
<b>当前版本:</b>v4.7.0 <b>当前版本:</b>v4.7.1
</p> </p>
<p> <p>
<span class="label label-warning">免费开源</span> <span class="label label-warning">免费开源</span>
@ -56,7 +56,7 @@
<h3>你好,若依 </h3> <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>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> <p>
<b>当前版本:</b>v4.7.0 <b>当前版本:</b>v4.7.1
</p> </p>
<p> <p>
<span class="label label-warning">开源免费</span> <span class="label label-warning">开源免费</span>

View File

@ -161,8 +161,8 @@
</div> </div>
<div id="step-3" class="tab-pane" role="tabpanel" aria-labelledby="step-3"> <div id="step-3" class="tab-pane" role="tabpanel" aria-labelledby="step-3">
<div class="m-t-md"> <div class="m-t-md">
<p>1、如果需要工具栏在页面底部显示, 将style中下面的部分取消注释<blockquote>.sw>.toolbar-bottom </blockquote></p> <p>1、如果需要工具栏固定在页面底部, 将style中下面的部分取消注释<blockquote>.sw>.toolbar-bottom </blockquote></p>
<p>2、如果设置了自动调节高度为false, 将style中下面的部分取消注释<blockquote>.sw>.tab-content </blockquote></p> <p>2、如果设置了自动调节高度(autoAdjustHeight)为true, 将style中下面的部分取消注释<blockquote>.sw>.tab-content </blockquote></p>
<p>3、工具栏的按钮样式会被表单插件中.btn样式覆盖导致bootstrap中的按钮样式无效, 如果需要改变按钮样式可以自己定义并提高优先级</blockquote></p> <p>3、工具栏的按钮样式会被表单插件中.btn样式覆盖导致bootstrap中的按钮样式无效, 如果需要改变按钮样式可以自己定义并提高优先级</blockquote></p>
</div> </div>
</div> </div>

View File

@ -147,7 +147,7 @@
}) })
$("#button-msgReload").click(function(){ $("#button-msgReload").click(function(){
$.modal.msgReload("保存成功,正在刷新数据请稍……", modal_status.SUCCESS); $.modal.msgReload("保存成功,正在刷新数据请稍……", modal_status.SUCCESS);
}) })
$("#button-open-1").click(function(){ $("#button-open-1").click(function(){

View File

@ -24,13 +24,26 @@
<h5>弹层框</h5> <h5>弹层框</h5>
</div> </div>
<div class="ibox-content" id="test"> <div class="ibox-content" id="test">
<p>弹出复选框表格及单选框表格(点击提交后得到数据并回显到父窗体</p> <p>弹出层,点击提交后得到数据并回显到父窗体。 </p>
<button type="button" class="btn btn-info" onclick="selectUsersToParent()">弹出表格(复选框</button> <button type="button" class="btn btn-primary" onclick="selectUsersToParent()">弹出表格(方式一</button>
<button type="button" class="btn btn-warning" onclick="selectUsersToParentCallBack()">弹出表格(复选框)- 回调形式</button> <button type="button" class="btn btn-success" onclick="selectUsersToParentCallBack2()">弹出表格(方式二)</button>
<button type="button" class="btn btn-info" onclick="selectUsersToParentCallBack3()">弹出表格(方式三)</button>
<p id="userids"> </p> <p id="userids"> </p>
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-12">
<div class="ibox">
<div class="ibox-title">
<h5>弹层框</h5>
</div>
<div class="ibox-content" id="test">
<p>多层弹出,点击提交后得到数据并回显到父窗体。 </p>
<button type="button" class="btn btn-primary" onclick="selectUsersToParent4()">弹出窗口(方式四)</button>
<p id="username"> </p>
</div>
</div>
</div>
</div> </div>
</div> </div>
<th:block th:include="include :: footer" /> <th:block th:include="include :: footer" />
@ -45,26 +58,61 @@
$.modal.open("选择用户", prefix + "/radio"); $.modal.open("选择用户", prefix + "/radio");
} }
// 根据当前激活的选项卡获取(方式一)
function selectUsersToParent(){ function selectUsersToParent(){
$.modal.open("选择用户", prefix + "/parent"); $.modal.open("选择用户", prefix + "/parent");
} }
function selectUsersToParentCallBack(){ // callBack获取父窗口方法方式二
function selectUsersToParentCallBack2(){
var options = { var options = {
title: '选择用户', title: '选择用户',
url: prefix + "/parent", url: prefix + "/parent",
callBack: doSubmit callBack: doSubmit2
}; };
$.modal.openOptions(options); $.modal.openOptions(options);
} }
function doSubmit(index, layero){ // callBack获取父窗口值方式三
function selectUsersToParentCallBack3(){
var options = {
title: '选择用户',
url: prefix + "/parent",
callBack: doSubmit3
};
$.modal.openOptions(options);
}
// callBack获取父窗口值方式四
function selectUsersToParent4(){
var prefix = ctx + "demo/modal";
var options = {
title: '多层窗口A',
url: prefix + "/frame1",
callBack: doSubmit4
};
$.modal.openOptions(options);
}
function doSubmit2(index, layero){
var rows = layero.find("iframe")[0].contentWindow.getSelections(); var rows = layero.find("iframe")[0].contentWindow.getSelections();
if (rows.length == 0) { if (rows.length == 0) {
$.modal.alertWarning("请至少选择一条记录"); $.modal.alertWarning("请至少选择一条记录");
return; return;
} }
$('#userids').html(rows.join()) $('#userids').html('我是通过方式二来的:' + rows.join())
$.modal.close(index);
}
function doSubmit3(index, layero){
var body = $.modal.getChildFrame(index);
$("#userids").html('我是通过方式三来的:' + body.find('#rowIds').val());
$.modal.close(index);
}
function doSubmit4(index, layero){
var body = $.modal.getChildFrame(index);
$("#username").html('我是通过方式四来的:' + body.find('#name').val());
$.modal.close(index); $.modal.close(index);
} }

View File

@ -0,0 +1,53 @@
<!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('多层窗口A')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<form id="form-user-add" class="form-horizontal">
<div class="row">
<div class="col-sm-12" style="margin-top: 50px">
<div class="form-group">
<label class="col-sm-4 control-label">用户名称:</label>
<div class="col-sm-4">
<input id="name" placeholder="请输入用户名称" class="form-control" type="text">
</div>
<button type="button" class="btn btn-primary" onclick="selectUserToParentId()">选择</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div th:include="include :: footer"></div>
<script th:inline="javascript">
/* 提交 */
function submitHandler() {
var name = $("#name").val();
activeWindow().$('#username').html(name);
$.modal.close();
}
// 根据父窗口ID获取
function selectUserToParentId(){
var prefix = ctx + "demo/modal";
var options = {
width: '100px',
height: '100px',
title: '多层窗口B',
url: prefix + "/frame2",
callBack: doSubmit
};
$.modal.openOptions(options);
}
function doSubmit(index, layero){
var body = $.modal.getChildFrame(index);
$("#name").val(body.find('#name').val());
$.modal.close(index);
}
</script>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!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('多层窗口B')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<form id="form-user-add" class="form-horizontal">
<div class="row">
<div class="col-sm-12" style="margin-top: 20px">
<div class="form-group">
<label class="col-sm-4 control-label">用户名称:</label>
<div class="col-sm-4">
<input id="name" placeholder="请输入用户名称" class="form-control" type="text">
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</body>
</html>

View File

@ -4,6 +4,7 @@
<th:block th:include="include :: header('表格传值给父页面')" /> <th:block th:include="include :: header('表格传值给父页面')" />
</head> </head>
<body class="gray-bg"> <body class="gray-bg">
<input type="hidden" id="rowIds">
<div class="container-div"> <div class="container-div">
<div class="row"> <div class="row">
<div class="col-sm-12 select-table table-striped"> <div class="col-sm-12 select-table table-striped">
@ -81,15 +82,21 @@
} }
$.modal.close(); $.modal.close();
// 父页面的方法 // 父页面的方法
// parent.selectUsers(); // activeWindow().selectUsers();
// 父页面的变量 // 父页面的变量
parent.$('#userids').html(rows.join()); activeWindow().$('#userids').html('我是通过方式一来的:' + rows.join());
} }
/* 添加用户-选择用户-提交(回调形式-父页面调用子页面) */ /* 添加用户-选择用户-提交(回调形式-父页面调用子页面) */
function getSelections() { function getSelections() {
return $.table.selectFirstColumns(); return $.table.selectFirstColumns();
} }
$("#bootstrap-table").on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rowsAfter, rowsBefore) {
var rows = $.common.equals("uncheck-all", e.type) ? rowsBefore : rowsAfter;
var rowIds = $.table.affectedRowIds(rows);
$("#rowIds").val(rowIds);
});
</script> </script>
</body> </body>
</html> </html>

View File

@ -59,7 +59,7 @@
type: "post", type: "post",
success: function(result) { success: function(result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
layer.msg("保存成功,正在刷新数据请稍……", { layer.msg("保存成功,正在刷新数据请稍……", {
icon: 1, icon: 1,
time: 500, time: 500,
shade: [0.1, '#8F8F8F'] shade: [0.1, '#8F8F8F']

View File

@ -42,7 +42,7 @@
function ajaxColumns() { function ajaxColumns() {
var url = prefix + "/ajaxColumns"; var url = prefix + "/ajaxColumns";
var dataParam = $.common.formToJSON("table-form"); var dataParam = $.common.formToJSON("table-form");
$.modal.loading("正在查询中,请稍..."); $.modal.loading("正在查询中,请稍...");
$.post(url, dataParam, function(result) { $.post(url, dataParam, function(result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
setColumns(result.data); setColumns(result.data);

View File

@ -86,6 +86,7 @@
$(function() { $(function() {
var options = { var options = {
id: "bootstrap-table1", id: "bootstrap-table1",
formId: "form1",
toolbar: "toolbar1", toolbar: "toolbar1",
url: prefix + "/list", url: prefix + "/list",
createUrl: prefix + "/add", createUrl: prefix + "/add",
@ -145,6 +146,7 @@
$(function() { $(function() {
var options = { var options = {
id: "bootstrap-table2", id: "bootstrap-table2",
formId: "form2",
toolbar: "toolbar2", toolbar: "toolbar2",
url: prefix + "/list", url: prefix + "/list",
createUrl: prefix + "/add", createUrl: prefix + "/add",

View File

@ -5,6 +5,11 @@
</head> </head>
<body class="gray-bg"> <body class="gray-bg">
<div class="container-div"> <div class="container-div">
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-primary" onclick="getData()">
<i class="fa fa-search"></i> 查询所有数据
</a>
</div>
<div class="row"> <div class="row">
<div class="col-sm-12 select-table table-striped"> <div class="col-sm-12 select-table table-striped">
<p class="select-title">按住表格行拖拽</p> <p class="select-title">按住表格行拖拽</p>
@ -29,7 +34,9 @@
showColumns: false, showColumns: false,
onReorderRow: function (data) { onReorderRow: function (data) {
//当拖拽结束后data为整个表格的数据 //当拖拽结束后data为整个表格的数据
console.log('拖拽结束' + JSON.stringify(data)) console.table(data)
// 当sidePagination: "server"时,拖拽行后顺序错乱,需要重新调用加载数据方法
$("#" + table.options.id).bootstrapTable('load', data);
return false; return false;
}, },
columns: [{ columns: [{
@ -70,6 +77,12 @@
}; };
$.table.init(options); $.table.init(options);
}); });
/* 查询表格所有数据值 */
function getData(){
var data = $("#" + table.options.id).bootstrapTable('getData');
alert(JSON.stringify(data.map( item => { return item.userId })))
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -7,12 +7,12 @@
<meta name="description" content=""> <meta name="description" content="">
<title th:text="${title}"></title> <title th:text="${title}"></title>
<link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/> <link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/>
<link th:href="@{/css/font-awesome.min.css?v=4.7.0}" rel="stylesheet"/> <link th:href="@{/css/font-awesome.min.css?v=4.7.1}" rel="stylesheet"/>
<!-- bootstrap-table 表格插件样式 --> <!-- bootstrap-table 表格插件样式 -->
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.18.3}" rel="stylesheet"/> <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/animate.min.css?v=20210831}" rel="stylesheet"/>
<link th:href="@{/css/style.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.0}" rel="stylesheet"/> <link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
</head> </head>
<!-- 通用JS --> <!-- 通用JS -->
@ -36,8 +36,8 @@
<script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></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/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="@{/ajax/libs/layui/layui.min.js?v=2.6.8}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/common.js?v=4.7.1}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
</div> </div>
<!-- ztree树插件 --> <!-- ztree树插件 -->
@ -108,10 +108,10 @@
<!-- fileinput文件上传插件 --> <!-- fileinput文件上传插件 -->
<div th:fragment="bootstrap-fileinput-css"> <div th:fragment="bootstrap-fileinput-css">
<link th:href="@{/ajax/libs/bootstrap-fileinput/fileinput.min.css?v=5.2.3}" rel="stylesheet"/> <link th:href="@{/ajax/libs/bootstrap-fileinput/fileinput.min.css?v=5.2.4}" rel="stylesheet"/>
</div> </div>
<div th:fragment="bootstrap-fileinput-js"> <div th:fragment="bootstrap-fileinput-js">
<script th:src="@{/ajax/libs/bootstrap-fileinput/fileinput.min.js?v=5.2.3}"></script> <script th:src="@{/ajax/libs/bootstrap-fileinput/fileinput.min.js?v=5.2.4}"></script>
</div> </div>
<!-- duallistbox双列表框插件 --> <!-- duallistbox双列表框插件 -->

View File

@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/> <link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.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="@{/css/skins.css?v=20200902}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.0}" rel="stylesheet"/> <link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
</head> </head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden"> <body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper"> <div id="wrapper">
@ -279,7 +279,7 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<div class="row content-tabs"> <div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
<button class="roll-nav roll-left tabLeft"> <button class="roll-nav roll-left tabLeft">
<i class="fa fa-backward"></i> <i class="fa fa-backward"></i>
</button> </button>
@ -296,12 +296,12 @@
<a id="ax_close_max" class="ax_close_max" href="#" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a> <a id="ax_close_max" class="ax_close_max" href="#" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a>
<div class="row mainContent" id="content-main" th:style="${#bools.isFalse(ignoreFooter)} ? |height: calc(100% - 91px)|"> <div class="row mainContent" id="content-main" th:classappend="${mainClass}">
<iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}" <iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}"
th:src="@{/system/main}" frameborder="0" seamless></iframe> th:src="@{/system/main}" frameborder="0" seamless></iframe>
</div> </div>
<div th:if="${ignoreFooter}" class="footer"> <div th:if="${footer}" class="footer">
<div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div> <div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
</div> </div>
</div> </div>
@ -315,8 +315,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script> <script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.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="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/common.js?v=4.7.1}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script> <script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script> <script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:src="@{/js/resize-tabs.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/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/> <link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css}" rel="stylesheet"/> <link th:href="@{/css/skins.css}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.0}" rel="stylesheet"/> <link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
</head> </head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden"> <body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper"> <div id="wrapper">
@ -226,7 +226,7 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<div class="row content-tabs"> <div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
<button class="roll-nav roll-left tabLeft"> <button class="roll-nav roll-left tabLeft">
<i class="fa fa-backward"></i> <i class="fa fa-backward"></i>
</button> </button>
@ -243,12 +243,12 @@
<a id="ax_close_max" class="ax_close_max" href="#" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a> <a id="ax_close_max" class="ax_close_max" href="#" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a>
<div class="row mainContent" id="content-main" th:style="${#bools.isFalse(ignoreFooter)} ? |height: calc(100% - 91px)|"> <div class="row mainContent" id="content-main" th:classappend="${mainClass}">
<iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}" <iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}"
th:src="@{/system/main}" frameborder="0" seamless></iframe> th:src="@{/system/main}" frameborder="0" seamless></iframe>
</div> </div>
<div th:if="${ignoreFooter}" class="footer"> <div th:if="${footer}" class="footer">
<div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div> <div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
</div> </div>
</div> </div>
@ -262,8 +262,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script> <script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.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="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/common.js?v=4.7.1}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script> <script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script> <script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:inline="javascript"> <script th:inline="javascript">

View File

@ -29,16 +29,16 @@
</form> </form>
</div> </div>
<div class="help-block text-center" style="margin-top: 50px;">系统锁屏,请输入密码登!</div> <div class="help-block text-center" style="margin-top: 50px;">系统锁屏,请输入密码登!</div>
<div class="text-center"> <div class="text-center">
<a th:href="@{logout}">退出重新登</a> <a th:href="@{logout}">退出重新登</a>
</div> </div>
</div> </div>
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script> <script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
<script src="../static/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script> <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/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/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.0}"></script> <script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
</body> </body>
<script th:inline="javascript"> <script th:inline="javascript">
var ctx = [[@{/}]]; 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/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/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/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.0}" rel="stylesheet"/> <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
<!-- 360浏览器急速模式 --> <!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 --> <!-- 避免IE使用兼容模式 -->
@ -59,7 +59,7 @@
<div class="checkbox-custom" th:if="${isRemembered}" th:classappend="${captchaEnabled==false} ? 'm-t'"> <div class="checkbox-custom" th:if="${isRemembered}" th:classappend="${captchaEnabled==false} ? 'm-t'">
<input type="checkbox" id="rememberme" name="rememberme"> <label for="rememberme">记住我</label> <input type="checkbox" id="rememberme" name="rememberme"> <label for="rememberme">记住我</label>
</div> </div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍...">登录</button> <button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍...">登录</button>
</form> </form>
</div> </div>
</div> </div>
@ -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/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/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/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.0}"></script> <script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script> <script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
</body> </body>
</html> </html>

View File

@ -79,7 +79,7 @@
<div class="ibox-content"> <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><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
</p> </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> <a href="https://jq.qq.com/?_wv=1027&k=0ARRrO9V" target="_blank">101526938</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> <a href="https://jq.qq.com/?_wv=1027&k=up9k3ZXJ" target="_blank">264355400</a>
</p> </p>
<p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a> <p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
</p> </p>
@ -96,13 +96,67 @@
<div class="ibox-content no-padding"> <div class="ibox-content no-padding">
<div class="panel-body"> <div class="panel-body">
<div class="panel-group" id="version"> <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="#v471">v4.7.1</a><code class="pull-right">2021.11.10</code>
</h5>
</div>
<div id="v471" class="panel-collapse collapse in">
<div class="panel-body">
<ol>
<li>新增是否开启页签功能</li>
<li>代码生成的模块增加创建表功能</li>
<li>Excel导入支持@Excels注解</li>
<li>Excel注解支持导入导出标题信息</li>
<li>Excel注解支持自定义数据处理器</li>
<li>日志注解新增是否保存响应参数</li>
<li>防重提交注解支持配置间隔时间/提示消息</li>
<li>网页部分操作禁止使用后退键Backspace</li>
<li>实例演示中增加多层窗口获取值</li>
<li>弹出层openOptions增加动画属性</li>
<li>升级spring-boot到最新版本2.5.6</li>
<li>升级spring-boot-mybatis到最新版2.2.0</li>
<li>升级pagehelper到最新版1.4.0</li>
<li>升级oshi到最新版本v5.8.2</li>
<li>升级druid到最新版1.2.8</li>
<li>升级fastjson到最新版1.2.78</li>
<li>升级thymeleaf-extras-shiro到最新版本v2.1.0</li>
<li>升级bootstrap-fileinput到最新版本v5.2.4</li>
<li>修改阿里云maven仓库地址为新版地址</li>
<li>定时任务屏蔽违规字符</li>
<li>增加sendGet无参请求方法</li>
<li>代码生成去掉多余的排序字段</li>
<li>优化启动脚本参数优化</li>
<li>优化页签关闭右侧清除iframe元素</li>
<li>优化多表格切换表单查询参数</li>
<li>优化表格实例切换event不能为空</li>
<li>优化mybatis全局默认的执行器</li>
<li>优化导入Excel数据关闭时清理file</li>
<li>优化Excel导入图片可能出现的异常</li>
<li>优化记录登录信息,防止不必要的修改</li>
<li>优化aop语法使用spring自动注入注解</li>
<li>修复无法被反转义问题</li>
<li>修复拖拽行数据错位问题</li>
<li>修复新窗口打开页面关闭弹窗报错</li>
<li>修复富文本回退键被禁止&控制台报错问题</li>
<li>修复自定义弹出层全屏参数无效问题</li>
<li>修复树表代码生成短字段无法识别问题</li>
<li>修复apple/webkit浏览器时间无法格式化</li>
<li>修复后端主子表代码模板方法名生成错误问题</li>
<li>修复swagger没有指定dataTypeClass导致启动出现warn日志</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h5 class="panel-title"> <h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v470">v4.7.0</a><code class="pull-right">2021.09.01</code> <a data-toggle="collapse" data-parent="#version" href="#v470">v4.7.0</a><code class="pull-right">2021.09.01</code>
</h5> </h5>
</div> </div>
<div id="v470" class="panel-collapse collapse in"> <div id="v470" class="panel-collapse collapse">
<div class="panel-body"> <div class="panel-body">
<ol> <ol>
<li>优化弹出层显示在顶层窗口</li> <li>优化弹出层显示在顶层窗口</li>

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/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/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/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.0}" rel="stylesheet"/> <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
<!-- 360浏览器急速模式 --> <!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 --> <!-- 避免IE使用兼容模式 -->
@ -58,13 +58,13 @@
<input type="checkbox" id="acceptTerm" name="acceptTerm"> <label for="acceptTerm">我已阅读并同意</label> <input type="checkbox" id="acceptTerm" name="acceptTerm"> <label for="acceptTerm">我已阅读并同意</label>
<a href="https://gitee.com/y_project/RuoYi/blob/master/README.md" target="_blank">使用条款</a> <a href="https://gitee.com/y_project/RuoYi/blob/master/README.md" target="_blank">使用条款</a>
</div> </div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍...">注册</button> <button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍...">注册</button>
</form> </form>
</div> </div>
</div> </div>
<div class="signup-footer"> <div class="signup-footer">
<div class="pull-left"> <div class="pull-left">
&copy; 2019 All Rights Reserved. RuoYi <br> &copy; 2018-2021 All Rights Reserved. RuoYi <br>
</div> </div>
</div> </div>
</div> </div>
@ -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/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/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/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.0}"></script> <script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
<script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script> <script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script>
</body> </body>
</html> </html>

View File

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

View File

@ -198,7 +198,7 @@ $(window).on('load', function() {
$('.btn-custom').on('click',function (e) { $('.btn-custom').on('click',function (e) {
if (!croppable) { if (!croppable) {
$.modal.alertWarning("裁剪框加载中,请稍..."); $.modal.alertWarning("裁剪框加载中,请稍...");
return; return;
} }
var data = { var data = {
@ -214,7 +214,7 @@ $(window).on('load', function() {
function submitHandler() { function submitHandler() {
if (!croppable) { if (!croppable) {
$.modal.alertWarning("裁剪框加载中,请稍..."); $.modal.alertWarning("裁剪框加载中,请稍...");
return return
} }
cropper.getCroppedCanvas().toBlob(function(img) { cropper.getCroppedCanvas().toBlob(function(img) {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>4.7.0</version> <version>4.7.1</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -49,8 +49,8 @@
<!-- 自定义验证注解 --> <!-- 自定义验证注解 -->
<dependency> <dependency>
<groupId>javax.validation</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>validation-api</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<!--常用工具类 --> <!--常用工具类 -->

View File

@ -5,6 +5,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal; import java.math.BigDecimal;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/** /**
* 自定义导出Excel数据注解 * 自定义导出Excel数据注解
@ -108,7 +109,17 @@ public @interface Excel
/** /**
* 导出字段对齐方式0默认1靠左2居中3靠右 * 导出字段对齐方式0默认1靠左2居中3靠右
*/ */
Align align() default Align.AUTO; public Align align() default Align.AUTO;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default {};
public enum Align public enum Align
{ {

View File

@ -37,4 +37,9 @@ public @interface Log
* 是否保存请求的参数 * 是否保存请求的参数
*/ */
public boolean isSaveRequestData() default true; public boolean isSaveRequestData() default true;
/**
* 是否保存响应的参数
*/
public boolean isSaveResponseData() default true;
} }

View File

@ -17,5 +17,13 @@ import java.lang.annotation.Target;
@Documented @Documented
public @interface RepeatSubmit public @interface RepeatSubmit
{ {
/**
* 间隔时间(ms),小于此时间视为重复提交
*/
public int interval() default 5000;
/**
* 提示消息
*/
public String message() default "不允许重复提交,请稍后再试";
} }

View File

@ -116,4 +116,10 @@ public class Constants
* LDAP 远程方法调用 * LDAP 远程方法调用
*/ */
public static final String LOOKUP_LDAP = "ldap://"; public static final String LOOKUP_LDAP = "ldap://";
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework.jndi" };
} }

View File

@ -69,26 +69,37 @@ public class EscapeUtil
*/ */
private static String encode(String text) private static String encode(String text)
{ {
int len; if (StringUtils.isEmpty(text))
if ((text == null) || ((len = text.length()) == 0))
{ {
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
StringBuilder buffer = new StringBuilder(len + (len >> 2));
final StringBuilder tmp = new StringBuilder(text.length() * 6);
char c; char c;
for (int i = 0; i < len; i++) for (int i = 0; i < text.length(); i++)
{ {
c = text.charAt(i); c = text.charAt(i);
if (c < 64) if (c < 256)
{ {
buffer.append(TEXT[c]); tmp.append("%");
if (c < 16)
{
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
} }
else else
{ {
buffer.append(c); tmp.append("%u");
if (c <= 0xfff)
{
// issue#I49JU8@Gitee
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
} }
} }
return buffer.toString(); return tmp.toString();
} }
/** /**
@ -145,11 +156,12 @@ public class EscapeUtil
public static void main(String[] args) public static void main(String[] args)
{ {
String html = "<script>alert(1);</script>"; String html = "<script>alert(1);</script>";
String escape = EscapeUtil.escape(html);
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>"; // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123"; // String html = "<123";
// String html = "123>"; // String html = "123>";
System.out.println(EscapeUtil.clean(html)); System.out.println("clean: " + EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html)); System.out.println("escape: " + escape);
System.out.println(EscapeUtil.unescape(html)); System.out.println("unescape: " + EscapeUtil.unescape(escape));
} }
} }

View File

@ -19,6 +19,7 @@ import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
/** /**
* 通用http发送方法 * 通用http发送方法
@ -29,6 +30,17 @@ public class HttpUtils
{ {
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url)
{
return sendGet(url, StringUtils.EMPTY);
}
/** /**
* 向指定 URL 发送GET方法的请求 * 向指定 URL 发送GET方法的请求
* *
@ -55,7 +67,7 @@ public class HttpUtils
BufferedReader in = null; BufferedReader in = null;
try try
{ {
String urlNameString = url + "?" + param; String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString); log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString); URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection(); URLConnection connection = realUrl.openConnection();

View File

@ -0,0 +1,19 @@
package com.ruoyi.common.utils.poi;
/**
* Excel数据格式处理适配器
*
* @author ruoyi
*/
public interface ExcelHandlerAdapter
{
/**
* 格式化
*
* @param value 单元格数据值
* @param args excel注解args参数组
*
* @return 处理后的值
*/
Object format(Object value, String[] args);
}

View File

@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -46,6 +47,7 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook;
@ -124,6 +126,16 @@ public class ExcelUtil<T>
*/ */
private List<Object[]> fields; private List<Object[]> fields;
/**
* 当前行号
*/
private int rownum;
/**
* 标题
*/
private String title;
/** /**
* 最大高度 * 最大高度
*/ */
@ -149,7 +161,7 @@ public class ExcelUtil<T>
this.clazz = clazz; this.clazz = clazz;
} }
public void init(List<T> list, String sheetName, Type type) public void init(List<T> list, String sheetName, String title, Type type)
{ {
if (list == null) if (list == null)
{ {
@ -158,8 +170,27 @@ public class ExcelUtil<T>
this.list = list; this.list = list;
this.sheetName = sheetName; this.sheetName = sheetName;
this.type = type; this.type = type;
this.title = title;
createExcelField(); createExcelField();
createWorkbook(); createWorkbook();
createTitle();
}
/**
* 创建excel第一行标题
*/
public void createTitle()
{
if (StringUtils.isNotEmpty(title))
{
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));
}
} }
/** /**
@ -170,17 +201,30 @@ public class ExcelUtil<T>
*/ */
public List<T> importExcel(InputStream is) throws Exception public List<T> importExcel(InputStream is) throws Exception
{ {
return importExcel(StringUtils.EMPTY, is); return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
} }
/** /**
* 对excel表单指定表格索引名转换成list * 对excel表单指定表格索引名转换成list
* *
* @param sheetName 表格索引名 * @param sheetName 表格索引名
* @param titleNum 标题占用行数
* @param is 输入流 * @param is 输入流
* @return 转换后集合 * @return 转换后集合
*/ */
public List<T> importExcel(String sheetName, InputStream is) throws Exception public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
{ {
this.type = Type.IMPORT; this.type = Type.IMPORT;
this.wb = WorkbookFactory.create(is); this.wb = WorkbookFactory.create(is);
@ -209,7 +253,7 @@ public class ExcelUtil<T>
// 定义一个map用于存放excel列的序号和field. // 定义一个map用于存放excel列的序号和field.
Map<String, Integer> cellMap = new HashMap<String, Integer>(); Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头 // 获取表头
Row heard = sheet.getRow(0); Row heard = sheet.getRow(titleNum);
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
{ {
Cell cell = heard.getCell(i); Cell cell = heard.getCell(i);
@ -224,25 +268,18 @@ public class ExcelUtil<T>
} }
} }
// 有数据时才处理 得到类的所有field. // 有数据时才处理 得到类的所有field.
Field[] allFields = clazz.getDeclaredFields(); List<Object[]> fields = this.getFields();
// 定义一个map用于存放列的序号和field. Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>(); for (Object[] objects : fields)
for (int col = 0; col < allFields.length; col++)
{ {
Field field = allFields[col]; Excel attr = (Excel) objects[1];
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
// 设置类的私有字段属性可访问.
field.setAccessible(true);
Integer column = cellMap.get(attr.name()); Integer column = cellMap.get(attr.name());
if (column != null) if (column != null)
{ {
fieldsMap.put(column, field); fieldsMap.put(column, objects);
} }
} }
} for (int i = titleNum + 1; i <= rows; i++)
for (int i = 1; i <= rows; i++)
{ {
// 从第2行开始取数据,默认第一行是表头. // 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i); Row row = sheet.getRow(i);
@ -252,14 +289,15 @@ public class ExcelUtil<T>
continue; continue;
} }
T entity = null; T entity = null;
for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet()) for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
{ {
Object val = this.getCellValue(row, entry.getKey()); Object val = this.getCellValue(row, entry.getKey());
// 如果不存在实例则新建. // 如果不存在实例则新建.
entity = (entity == null ? clazz.newInstance() : entity); entity = (entity == null ? clazz.newInstance() : entity);
// 从map中得到对应列的field. // 从map中得到对应列的field.
Field field = fieldsMap.get(entry.getKey()); Field field = (Field) entry.getValue()[0];
Excel attr = (Excel) entry.getValue()[1];
// 取得类型,并根据对象类型设置值. // 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType(); Class<?> fieldType = field.getType();
if (String.class == fieldType) if (String.class == fieldType)
@ -319,7 +357,6 @@ public class ExcelUtil<T>
} }
if (StringUtils.isNotNull(fieldType)) if (StringUtils.isNotNull(fieldType))
{ {
Excel attr = field.getAnnotation(Excel.class);
String propertyName = field.getName(); String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr())) if (StringUtils.isNotEmpty(attr.targetAttr()))
{ {
@ -333,6 +370,10 @@ public class ExcelUtil<T>
{ {
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
} }
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
val = dataFormatHandlerAdapter(val, attr);
}
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{ {
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
@ -340,9 +381,12 @@ public class ExcelUtil<T>
{ {
val = ""; val = "";
} }
else
{
byte[] data = image.getData(); byte[] data = image.getData();
val = FileUtils.writeImportBytes(data); val = FileUtils.writeImportBytes(data);
} }
}
ReflectUtils.invokeSetter(entity, propertyName, val); ReflectUtils.invokeSetter(entity, propertyName, val);
} }
} }
@ -361,7 +405,20 @@ public class ExcelUtil<T>
*/ */
public AjaxResult exportExcel(List<T> list, String sheetName) public AjaxResult exportExcel(List<T> list, String sheetName)
{ {
this.init(list, sheetName, Type.EXPORT); return exportExcel(list, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName, String title)
{
this.init(list, sheetName, title, Type.EXPORT);
return exportExcel(); return exportExcel();
} }
@ -375,10 +432,25 @@ public class ExcelUtil<T>
* @throws IOException * @throws IOException
*/ */
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)throws IOException public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)throws IOException
{
exportExcel(response, list, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
* @throws IOException
*/
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title) throws IOException
{ {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
this.init(list, sheetName, Type.EXPORT); this.init(list, sheetName, title, Type.EXPORT);
exportExcel(response.getOutputStream()); exportExcel(response.getOutputStream());
} }
@ -390,7 +462,19 @@ public class ExcelUtil<T>
*/ */
public AjaxResult importTemplateExcel(String sheetName) public AjaxResult importTemplateExcel(String sheetName)
{ {
this.init(null, sheetName, Type.IMPORT); return importTemplateExcel(sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult importTemplateExcel(String sheetName, String title)
{
this.init(null, sheetName, title, Type.IMPORT);
return exportExcel(); return exportExcel();
} }
@ -401,10 +485,22 @@ public class ExcelUtil<T>
* @return 结果 * @return 结果
*/ */
public void importTemplateExcel(HttpServletResponse response, String sheetName) throws IOException public void importTemplateExcel(HttpServletResponse response, String sheetName) throws IOException
{
importTemplateExcel(response, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) throws IOException
{ {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
this.init(null, sheetName, Type.IMPORT); this.init(null, sheetName, title, Type.IMPORT);
exportExcel(response.getOutputStream()); exportExcel(response.getOutputStream());
} }
@ -465,13 +561,13 @@ public class ExcelUtil<T>
public void writeSheet() public void writeSheet()
{ {
// 取出一共有多少个sheet. // 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize); int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
for (int index = 0; index <= sheetNo; index++) for (int index = 0; index < sheetNo; index++)
{ {
createSheet(sheetNo, index); createSheet(sheetNo, index);
// 产生一行 // 产生一行
Row row = sheet.createRow(0); Row row = sheet.createRow(rownum);
int column = 0; int column = 0;
// 写入各个字段的列头名称 // 写入各个字段的列头名称
for (Object[] os : fields) for (Object[] os : fields)
@ -499,7 +595,7 @@ public class ExcelUtil<T>
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
row = sheet.createRow(i + 1 - startNo); row = sheet.createRow(i + 1 + rownum - startNo);
// 得到导出对象. // 得到导出对象.
T vo = (T) list.get(i); T vo = (T) list.get(i);
int column = 0; int column = 0;
@ -507,8 +603,6 @@ public class ExcelUtil<T>
{ {
Field field = (Field) os[0]; Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
// 设置实体类私有属性可访问
field.setAccessible(true);
this.addCell(excel, row, vo, field, column++); this.addCell(excel, row, vo, field, column++);
} }
} }
@ -527,6 +621,16 @@ public class ExcelUtil<T>
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER);
Font titleFont = wb.createFont();
titleFont.setFontName("Arial");
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true);
style.setFont(titleFont);
styles.put("title", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN);
@ -726,6 +830,10 @@ public class ExcelUtil<T>
{ {
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
} }
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
cell.setCellValue(dataFormatHandlerAdapter(value, attr));
}
else else
{ {
// 设置列类型 // 设置列类型
@ -898,6 +1006,28 @@ public class ExcelUtil<T>
return DictUtils.getDictValue(dictType, dictLabel, separator); return DictUtils.getDictValue(dictType, dictLabel, separator);
} }
/**
* 数据处理器
*
* @param value 数据值
* @param excel 数据注解
* @return
*/
public String dataFormatHandlerAdapter(Object value, Excel excel)
{
try
{
Object instance = excel.handler().newInstance();
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class });
value = formatMethod.invoke(instance, value, excel.args());
}
catch (Exception e)
{
log.error("不能格式化数据 " + excel.handler(), e.getMessage());
}
return Convert.toStr(value);
}
/** /**
* 合计统计信息 * 合计统计信息
*/ */
@ -1025,7 +1155,17 @@ public class ExcelUtil<T>
*/ */
private void createExcelField() private void createExcelField()
{ {
this.fields = new ArrayList<Object[]>(); this.fields = getFields();
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
this.maxHeight = getRowHeight();
}
/**
* 获取字段注解信息
*/
public List<Object[]> getFields()
{
List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
@ -1034,7 +1174,12 @@ public class ExcelUtil<T>
// 单注解 // 单注解
if (field.isAnnotationPresent(Excel.class)) if (field.isAnnotationPresent(Excel.class))
{ {
putToField(field, field.getAnnotation(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 });
}
} }
// 多注解 // 多注解
@ -1042,14 +1187,17 @@ public class ExcelUtil<T>
{ {
Excels attrs = field.getAnnotation(Excels.class); Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value(); Excel[] excels = attrs.value();
for (Excel excel : excels) for (Excel attr : excels)
{ {
putToField(field, excel); if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
} }
} }
} }
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); }
this.maxHeight = getRowHeight(); return fields;
} }
/** /**
@ -1066,23 +1214,15 @@ public class ExcelUtil<T>
return (short) (maxHeight * 20); return (short) (maxHeight * 20);
} }
/**
* 放到字段集合中
*/
private void putToField(Field field, Excel attr)
{
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
this.fields.add(new Object[] { field, attr });
}
}
/** /**
* 创建一个工作簿 * 创建一个工作簿
*/ */
public void createWorkbook() public void createWorkbook()
{ {
this.wb = new SXSSFWorkbook(500); this.wb = new SXSSFWorkbook(500);
this.sheet = wb.createSheet();
wb.setSheetName(0, sheetName);
this.styles = createStyles(wb);
} }
/** /**
@ -1091,17 +1231,13 @@ public class ExcelUtil<T>
* @param sheetNo sheet数量 * @param sheetNo sheet数量
* @param index 序号 * @param index 序号
*/ */
public void createSheet(double sheetNo, int index) public void createSheet(int sheetNo, int index)
{
// 设置工作表的名称.
if (sheetNo > 1 && index > 0)
{ {
this.sheet = wb.createSheet(); this.sheet = wb.createSheet();
this.styles = createStyles(wb); this.createTitle();
// 设置工作表的名称.
if (sheetNo == 0)
{
wb.setSheetName(index, sheetName);
}
else
{
wb.setSheetName(index, sheetName + index); wb.setSheetName(index, sheetName + index);
} }
} }

View File

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

View File

@ -1,12 +1,8 @@
package com.ruoyi.framework.aspectj; package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
@ -54,27 +50,15 @@ public class DataScopeAspect
*/ */
public static final String DATA_SCOPE = "dataScope"; public static final String DATA_SCOPE = "dataScope";
// 配置织入点 @Before("@annotation(controllerDataScope)")
@Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
public void dataScopePointCut()
{
}
@Before("dataScopePointCut()")
public void doBefore(JoinPoint point) throws Throwable
{ {
clearDataScope(point); clearDataScope(point);
handleDataScope(point); handleDataScope(point, controllerDataScope);
} }
protected void handleDataScope(final JoinPoint joinPoint) protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
{ {
// 获得注解
DataScope controllerDataScope = getAnnotationLog(joinPoint);
if (controllerDataScope == null)
{
return;
}
// 获取当前的用户 // 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser(); SysUser currentUser = ShiroUtils.getSysUser();
if (currentUser != null) if (currentUser != null)
@ -149,22 +133,6 @@ public class DataScopeAspect
} }
} }
/**
* 是否存在注解,如果存在就获取
*/
private DataScope getAnnotationLog(JoinPoint joinPoint)
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(DataScope.class);
}
return null;
}
/** /**
* 拼接权限sql前先清空params.dataScope参数防止注入 * 拼接权限sql前先清空params.dataScope参数防止注入
*/ */

View File

@ -1,18 +1,14 @@
package com.ruoyi.framework.aspectj; package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,7 +19,6 @@ import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessStatus; import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@ -56,10 +51,10 @@ public class LogAspect
* *
* @param joinPoint 切点 * @param joinPoint 切点
*/ */
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
{ {
handleLog(joinPoint, null, jsonResult); handleLog(joinPoint, controllerLog, null, jsonResult);
} }
/** /**
@ -68,23 +63,16 @@ public class LogAspect
* @param joinPoint 切点 * @param joinPoint 切点
* @param e 异常 * @param e 异常
*/ */
@AfterThrowing(value = "logPointCut()", throwing = "e") @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
{ {
handleLog(joinPoint, e, null); handleLog(joinPoint, controllerLog, e, null);
} }
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
{ {
try try
{ {
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户 // 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser(); SysUser currentUser = ShiroUtils.getSysUser();
@ -94,12 +82,6 @@ public class LogAspect
// 请求的地址 // 请求的地址
String ip = ShiroUtils.getIp(); String ip = ShiroUtils.getIp();
operLog.setOperIp(ip); operLog.setOperIp(ip);
// 返回参数
if (StringUtils.isNotNull(jsonResult))
{
operLog.setJsonResult(StringUtils.substring(JSON.marshal(jsonResult), 0, 2000));
}
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (currentUser != null) if (currentUser != null)
{ {
@ -123,7 +105,7 @@ public class LogAspect
// 设置请求方式 // 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数 // 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog); getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 保存数据库 // 保存数据库
AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
} }
@ -143,7 +125,7 @@ public class LogAspect
* @param operLog 操作日志 * @param operLog 操作日志
* @throws Exception * @throws Exception
*/ */
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
{ {
// 设置action动作 // 设置action动作
operLog.setBusinessType(log.businessType().ordinal()); operLog.setBusinessType(log.businessType().ordinal());
@ -157,6 +139,11 @@ public class LogAspect
// 获取参数的信息,传入到数据库中。 // 获取参数的信息,传入到数据库中。
setRequestValue(joinPoint, operLog); setRequestValue(joinPoint, operLog);
} }
// 是否需要保存response参数和值
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
{
operLog.setJsonResult(StringUtils.substring(JSONObject.toJSONString(jsonResult), 0, 2000));
}
} }
/** /**
@ -184,22 +171,6 @@ public class LogAspect
} }
} }
/**
* 是否存在注解,如果存在就获取
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(Log.class);
}
return null;
}
/** /**
* 忽略敏感属性 * 忽略敏感属性
*/ */
@ -216,13 +187,19 @@ public class LogAspect
String params = ""; String params = "";
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (int i = 0; i < paramsArray.length; i++) for (Object o : paramsArray)
{ {
if (StringUtils.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i])) if (StringUtils.isNotNull(o) && !isFilterObject(o))
{ {
Object jsonObj = JSONObject.toJSONString(paramsArray[i], excludePropertyPreFilter()); try
{
Object jsonObj = JSONObject.toJSONString(o, excludePropertyPreFilter());
params += jsonObj.toString() + " "; params += jsonObj.toString() + " ";
} }
catch (Exception e)
{
}
}
} }
} }
return params.trim(); return params.trim();
@ -245,17 +222,17 @@ public class LogAspect
else if (Collection.class.isAssignableFrom(clazz)) else if (Collection.class.isAssignableFrom(clazz))
{ {
Collection collection = (Collection) o; Collection collection = (Collection) o;
for (Iterator iter = collection.iterator(); iter.hasNext();) for (Object value : collection)
{ {
return iter.next() instanceof MultipartFile; return value instanceof MultipartFile;
} }
} }
else if (Map.class.isAssignableFrom(clazz)) else if (Map.class.isAssignableFrom(clazz))
{ {
Map map = (Map) o; Map map = (Map) o;
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) for (Object value : map.entrySet())
{ {
Map.Entry entry = (Map.Entry) iter.next(); Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile; return entry.getValue() instanceof MultipartFile;
} }
} }

View File

@ -5,10 +5,10 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import org.springframework.web.servlet.HandlerInterceptor;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
/** /**
@ -17,7 +17,7 @@ import com.ruoyi.common.utils.ServletUtils;
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
{ {
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
@ -29,9 +29,9 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
if (annotation != null) if (annotation != null)
{ {
if (this.isRepeatSubmit(request)) if (this.isRepeatSubmit(request, annotation))
{ {
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试"); AjaxResult ajaxResult = AjaxResult.error(annotation.message());
ServletUtils.renderString(response, JSON.marshal(ajaxResult)); ServletUtils.renderString(response, JSON.marshal(ajaxResult));
return false; return false;
} }
@ -40,16 +40,16 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
} }
else else
{ {
return super.preHandle(request, response, handler); return true;
} }
} }
/** /**
* 验证是否重复提交由子类实现具体的防重复提交的规则 * 验证是否重复提交由子类实现具体的防重复提交的规则
* *
* @param request * @param request 请求对象
* @return * @param annotation 防复注解
* @throws Exception * @return 结果
*/ */
public abstract boolean isRepeatSubmit(HttpServletRequest request) throws Exception; public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception;
} }

View File

@ -5,6 +5,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.json.JSON; import com.ruoyi.common.json.JSON;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
@ -23,21 +24,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
public final String SESSION_REPEAT_KEY = "repeatData"; public final String SESSION_REPEAT_KEY = "repeatData";
/**
* 间隔时间,单位:秒 默认10秒
*
* 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
*/
private int intervalTime = 10;
public void setIntervalTime(int intervalTime)
{
this.intervalTime = intervalTime;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public boolean isRepeatSubmit(HttpServletRequest request) throws Exception public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception
{ {
// 本次参数及系统时间 // 本次参数及系统时间
String nowParams = JSON.marshal(request.getParameterMap()); String nowParams = JSON.marshal(request.getParameterMap());
@ -56,7 +45,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
if (sessionMap.containsKey(url)) if (sessionMap.containsKey(url))
{ {
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url); Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
{ {
return true; return true;
} }
@ -81,11 +70,11 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
/** /**
* 判断两次间隔时间 * 判断两次间隔时间
*/ */
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap) private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
{ {
long time1 = (Long) nowMap.get(REPEAT_TIME); long time1 = (Long) nowMap.get(REPEAT_TIME);
long time2 = (Long) preMap.get(REPEAT_TIME); long time2 = (Long) preMap.get(REPEAT_TIME);
if ((time1 - time2) < (this.intervalTime * 1000)) if ((time1 - time2) < interval)
{ {
return true; return true;
} }

View File

@ -2,7 +2,6 @@ package com.ruoyi.framework.shiro.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants; import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
@ -17,6 +16,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -104,7 +104,7 @@ public class SysLoginService
passwordService.validate(user, password); passwordService.validate(user, password);
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
recordLoginInfo(user); recordLoginInfo(user.getUserId());
return user; return user;
} }
@ -130,9 +130,13 @@ public class SysLoginService
/** /**
* 记录登录信息 * 记录登录信息
*
* @param userId 用户ID
*/ */
public void recordLoginInfo(SysUser user) public void recordLoginInfo(Long userId)
{ {
SysUser user = new SysUser();
user.setUserId(userId);
user.setLoginIp(ShiroUtils.getIp()); user.setLoginIp(ShiroUtils.getIp());
user.setLoginDate(DateUtils.getNowDate()); user.setLoginDate(DateUtils.getNowDate());
userService.updateUserInfo(user); userService.updateUserInfo(user);

View File

@ -2,7 +2,6 @@ package com.ruoyi.framework.shiro.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants; import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
@ -11,6 +10,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -36,7 +36,7 @@ public class SysRegisterService
{ {
String msg = "", loginName = user.getLoginName(), password = user.getPassword(); String msg = "", loginName = user.getLoginName(), password = user.getPassword();
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) if (ShiroConstants.CAPTCHA_ERROR.equals(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
{ {
msg = "验证码错误"; msg = "验证码错误";
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>4.7.0</version> <version>4.7.1</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -29,6 +29,12 @@
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
</dependency> </dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -7,6 +7,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
@ -16,6 +17,10 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
@ -106,6 +111,15 @@ public class GenController extends BaseController
return prefix + "/importTable"; return prefix + "/importTable";
} }
/**
* 创建表结构
*/
@GetMapping("/createTable")
public String createTable()
{
return prefix + "/createTable";
}
/** /**
* 导入表结构(保存) * 导入表结构(保存)
*/ */
@ -118,7 +132,7 @@ public class GenController extends BaseController
String[] tableNames = Convert.toStrArray(tables); String[] tableNames = Convert.toStrArray(tables);
// 查询表信息 // 查询表信息
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames); List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
String operName = (String) PermissionUtils.getPrincipalProperty("loginName"); String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
genTableService.importGenTable(tableList, operName); genTableService.importGenTable(tableList, operName);
return AjaxResult.success(); return AjaxResult.success();
} }
@ -175,6 +189,39 @@ public class GenController extends BaseController
return AjaxResult.success(); return AjaxResult.success();
} }
@RequiresRoles("admin")
@Log(title = "创建表", businessType = BusinessType.OTHER)
@PostMapping("/createTable")
@ResponseBody
public AjaxResult create(String sql)
{
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
List<String> tableNames = new ArrayList<>();
for (SQLStatement sqlStatement : sqlStatements)
{
if (sqlStatement instanceof MySqlCreateTableStatement)
{
MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
String tableName = createTableStatement.getTableName();
tableName = tableName.replaceAll("`", "");
int msg = genTableService.createTable(createTableStatement.toString());
if (msg == 0)
{
tableNames.add(tableName);
}
}
else
{
return AjaxResult.error("请输入建表语句");
}
}
List<GenTable> tableList = genTableService.selectDbTableListByNames((tableNames.toArray(new String[tableNames.size()])));
String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
genTableService.importGenTable(tableList, operName);
return AjaxResult.success();
}
/** /**
* 预览代码 * 预览代码
*/ */

View File

@ -80,4 +80,12 @@ public interface GenTableMapper
* @return 结果 * @return 结果
*/ */
public int deleteGenTableByIds(Long[] ids); public int deleteGenTableByIds(Long[] ids);
/**
* 创建表
*
* @param sql
* @return 结果
*/
public int createTable(String sql);
} }

View File

@ -66,6 +66,14 @@ public interface IGenTableService
*/ */
public void deleteGenTableByIds(String ids); public void deleteGenTableByIds(String ids);
/**
* 创建表
*
* @param sql 创建表语句
* @return 结果
*/
public int createTable(String sql);
/** /**
* 导入表结构 * 导入表结构
* *

View File

@ -150,6 +150,18 @@ public class GenTableServiceImpl implements IGenTableService
genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids)); genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
} }
/**
* 创建表
*
* @param sql 创建表语句
* @return 结果
*/
@Override
public int createTable(String sql)
{
return genTableMapper.createTable(sql);
}
/** /**
* 导入表结构 * 导入表结构
* *
@ -313,7 +325,7 @@ public class GenTableServiceImpl implements IGenTableService
} }
/** /**
* 批量生成代码 * 批量生成代码(下载方式)
* *
* @param tableNames 表数组 * @param tableNames 表数组
* @return 数据 * @return 数据

View File

@ -72,7 +72,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult"> <select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables select table_name, table_comment, create_time, update_time from information_schema.tables
where table_schema = (select database()) where table_schema = (select database())
AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%' AND table_name NOT LIKE 'QRTZ_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT IN (select table_name from gen_table) AND table_name NOT IN (select table_name from gen_table)
<if test="tableName != null and tableName != ''"> <if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%')) AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
@ -80,6 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''"> <if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%')) AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if> </if>
order by create_time desc
</select> </select>
<select id="selectDbTableListByNames" resultMap="GenTableResult"> <select id="selectDbTableListByNames" resultMap="GenTableResult">
@ -155,6 +156,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
) )
</insert> </insert>
<update id="createTable">
${sql}
</update>
<update id="updateGenTable" parameterType="GenTable"> <update id="updateGenTable" parameterType="GenTable">
update gen_table update gen_table
<set> <set>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('创建表结构')"/>
</head>
<body>
<div class="main-content">
<label class="col-sm-6 control-label">创建表语句(支持多个建表语句)</label>
<div class="col-sm-11 col">
<textarea class="form-control" id="text_create" name="" placeholder="请输入文本" rows="12" type="text"></textarea>
</div>
</div>
<th:block th:include="include :: footer"/>
<script type="text/javascript">
var prefix = ctx + "tool/gen";
/* 创建表结构 */
function submitHandler() {
var rows = $("#text_create").val();
if (rows.length == 0) {
$.modal.alertWarning("请输入建表语句");
return;
}
var data = {"sql": rows};
$.operate.save(prefix + "/createTable", data);
}
</script>
</body>
</html>

View File

@ -431,7 +431,7 @@
title: '字典类型', title: '字典类型',
width: "13%", width: "13%",
formatter: function (value, row, index) { formatter: function (value, row, index) {
var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].dictType' value='%s' id='columns_dict_%s'>", index, value, row.columnId); var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].dictType' value='%s' id='columns_dict_%s'>", index, (value === undefined ? '' : value), row.columnId);
return "<div class='input-group'>" + html + "<span class='input-group-addon input-sm' onclick='selectDictTree(" + row.columnId + ", this)'><i class='fa fa-search'></i></span></div>"; return "<div class='input-group'>" + html + "<span class='input-group-addon input-sm' onclick='selectDictTree(" + row.columnId + ", this)'><i class='fa fa-search'></i></span></div>";
}, },
cellStyle: function(value, row, index) { cellStyle: function(value, row, index) {

View File

@ -34,6 +34,9 @@
<div class="btn-group-sm" id="toolbar" role="group"> <div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code"> <a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
<i class="fa fa-download"></i> 生成 <i class="fa fa-download"></i> 生成
</a>
<a class="btn btn-success" onclick="createTable()">
<i class="fa fa-plus"></i> 创建
</a> </a>
<a class="btn btn-info" onclick="importTable()"> <a class="btn btn-info" onclick="importTable()">
<i class="fa fa-upload"></i> 导入 <i class="fa fa-upload"></i> 导入
@ -138,7 +141,7 @@
// 预览代码 // 预览代码
function preview(tableId) { function preview(tableId) {
var preViewUrl = prefix + "/preview/" + tableId; var preViewUrl = prefix + "/preview/" + tableId;
$.modal.loading("正在加载数据,请稍..."); $.modal.loading("正在加载数据,请稍...");
$.get(preViewUrl, function(result) { $.get(preViewUrl, function(result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
var items = []; var items = [];
@ -172,7 +175,7 @@
$.modal.confirm("确定要生成" + tableName + "表代码吗?", function() { $.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
if(genType === "0") { if(genType === "0") {
location.href = prefix + "/download/" + tableName; location.href = prefix + "/download/" + tableName;
layer.msg('执行成功,正在生成代码请稍…', { icon: 1 }); layer.msg('执行成功,正在生成代码请稍…', { icon: 1 });
} else if(genType === "1") { } else if(genType === "1") {
$.operate.get(prefix + "/genCode/" + tableName); $.operate.get(prefix + "/genCode/" + tableName);
} }
@ -195,7 +198,7 @@
} }
$.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() { $.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() {
location.href = prefix + "/batchGenCode?tables=" + rows; location.href = prefix + "/batchGenCode?tables=" + rows;
layer.msg('执行成功,正在生成代码请稍…', { icon: 1 }); layer.msg('执行成功,正在生成代码请稍…', { icon: 1 });
}); });
} }
@ -204,6 +207,12 @@
var importTableUrl = prefix + "/importTable"; var importTableUrl = prefix + "/importTable";
$.modal.open("导入表结构", importTableUrl); $.modal.open("导入表结构", importTableUrl);
} }
// 创建表结构
function createTable() {
var creatTableUrl = prefix + "/createTable";
$.modal.open("创建表结构", creatTableUrl);
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -37,8 +37,6 @@
$(function() { $(function() {
var options = { var options = {
url: prefix + "/db/list", url: prefix + "/db/list",
sortName: "createTime",
sortOrder: "desc",
showSearch: false, showSearch: false,
showRefresh: false, showRefresh: false,
showToggle: false, showToggle: false,
@ -59,7 +57,6 @@
{ {
field: 'tableName', field: 'tableName',
title: '表名称', title: '表名称',
sortable: true,
formatter: function(value, row, index) { formatter: function(value, row, index) {
return $.table.tooltip(value); return $.table.tooltip(value);
} }
@ -67,20 +64,17 @@
{ {
field: 'tableComment', field: 'tableComment',
title: '表描述', title: '表描述',
sortable: true,
formatter: function(value, row, index) { formatter: function(value, row, index) {
return $.table.tooltip(value); return $.table.tooltip(value);
} }
}, },
{ {
field: 'createTime', field: 'createTime',
title: '创建时间', title: '创建时间'
sortable: true
}, },
{ {
field: 'updateTime', field: 'updateTime',
title: '更新时间', title: '更新时间'
sortable: true
}] }]
}; };
$.table.init(options); $.table.init(options);

View File

@ -69,7 +69,7 @@ public interface ${ClassName}Mapper
* @param ${pkColumn.javaField}s 需要删除的数据主键集合 * @param ${pkColumn.javaField}s 需要删除的数据主键集合
* @return 结果 * @return 结果
*/ */
public int delete${subClassName}By${pkColumn.capJavaField}s(String[] ${pkColumn.javaField}s); public int delete${subClassName}By${subTableFkClassName}s(String[] ${pkColumn.javaField}s);
/** /**
* 批量新增${subTable.functionName} * 批量新增${subTable.functionName}
@ -86,6 +86,6 @@ public interface ${ClassName}Mapper
* @param ${pkColumn.javaField} ${functionName}ID * @param ${pkColumn.javaField} ${functionName}ID
* @return 结果 * @return 结果
*/ */
public int delete${subClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
#end #end
} }

View File

@ -157,9 +157,21 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
for (${ClassName} ${className} : ${className}List) for (${ClassName} ${className} : ${className}List)
{ {
Ztree ztree = new Ztree(); Ztree ztree = new Ztree();
#if($treeCode.length() > 2 && $treeCode.substring(1,2).matches("[A-Z]"))
#set($TreeCode=$treeCode)
#else
#set($TreeCode=$treeCode.substring(0,1).toUpperCase() + ${treeCode.substring(1)}) #set($TreeCode=$treeCode.substring(0,1).toUpperCase() + ${treeCode.substring(1)})
#end
#if($treeParentCode.length() > 2 && $treeParentCode.substring(1,2).matches("[A-Z]"))
#set($TreeParentCode=$treeParentCode)
#else
#set($TreeParentCode=$treeParentCode.substring(0,1).toUpperCase() + ${treeParentCode.substring(1)}) #set($TreeParentCode=$treeParentCode.substring(0,1).toUpperCase() + ${treeParentCode.substring(1)})
#end
#if($treeName.length() > 2 && $treeName.substring(1,2).matches("[A-Z]"))
#set($TreeName=$treeName)
#else
#set($TreeName=$treeName.substring(0,1).toUpperCase() + ${treeName.substring(1)}) #set($TreeName=$treeName.substring(0,1).toUpperCase() + ${treeName.substring(1)})
#end
ztree.setId(${className}.get${TreeCode}()); ztree.setId(${className}.get${TreeCode}());
ztree.setpId(${className}.get${TreeParentCode}()); ztree.setpId(${className}.get${TreeParentCode}());
ztree.setName(${className}.get${TreeName}()); ztree.setName(${className}.get${TreeName}());

View File

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

View File

@ -148,6 +148,11 @@ public class SysJobController extends BaseController
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规");
}
job.setCreateBy(getLoginName());
return toAjax(jobService.insertJob(job)); return toAjax(jobService.insertJob(job));
} }
@ -186,6 +191,10 @@ public class SysJobController extends BaseController
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规");
}
return toAjax(jobService.updateJob(job)); return toAjax(jobService.updateJob(job));
} }

View File

@ -1131,7 +1131,7 @@
<script th:src="@{/js/jquery.min.js}"></script> <script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script> <script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script> <script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script> <script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
<script th:src="@{/js/cron.js}"></script> <script th:src="@{/js/cron.js}"></script>
<script th:inline="javascript"> <script th:inline="javascript">
var prefix = [[@{/}]] + "monitor/job"; var prefix = [[@{/}]] + "monitor/job";

View File

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

4
ry.bat
View File

@ -4,7 +4,7 @@ rem jarƽ
set AppName=ruoyi-admin.jar set AppName=ruoyi-admin.jar
rem JVM<56><4D><EFBFBD><EFBFBD> rem JVM<56><4D><EFBFBD><EFBFBD>
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
ECHO. ECHO.
@ -33,7 +33,7 @@ PAUSE
PAUSE PAUSE
) )
start javaw -jar %JAVA_OPTS% ruoyi-admin.jar start javaw %JAVA_OPTS% -jar %AppName%
echo starting<6E><67><EFBFBD><EFBFBD> echo starting<6E><67><EFBFBD><EFBFBD>
echo Start %AppName% success... echo Start %AppName% success...

10
ry.sh
View File

@ -1,13 +1,9 @@
#!/bin/sh #!/bin/sh
# author ruoyi # ./ry.sh start 启动 stop 停止 restart 重启 status 状态
# ./ry.sh start 启动
# ./ry.sh stop 停止
# ./ry.sh restart 重启
# ./ry.sh status 状态
AppName=ruoyi-admin.jar AppName=ruoyi-admin.jar
# JVM参数 # JVM参数
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
APP_HOME=`pwd` APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log LOG_PATH=$APP_HOME/logs/$AppName.log
@ -30,7 +26,7 @@ function start()
if [ x"$PID" != x"" ]; then if [ x"$PID" != x"" ]; then
echo "$AppName is running..." echo "$AppName is running..."
else else
nohup java -jar $JVM_OPTS target/$AppName > /dev/null 2>&1 & nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 &
echo "Start $AppName success..." echo "Start $AppName success..."
fi fi
} }

View File

@ -543,7 +543,8 @@ insert into sys_config values(5, '用户管理-密码字符范围', 'sys
insert into sys_config values(6, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '0', 'Y', 'admin', sysdate(), '', null, '0初始密码修改策略关闭没有任何提示1提醒用户如果未修改初始密码则在登录时就会提醒修改密码对话框'); insert into sys_config values(6, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '0', 'Y', 'admin', sysdate(), '', null, '0初始密码修改策略关闭没有任何提示1提醒用户如果未修改初始密码则在登录时就会提醒修改密码对话框');
insert into sys_config values(7, '用户管理-账号密码更新周期', 'sys.account.passwordValidateDays', '0', 'Y', 'admin', sysdate(), '', null, '密码更新周期填写数字数据初始化值为0不限制若修改必须为大于0小于365的正整数如果超过这个周期登录系统时则在登录时就会提醒修改密码对话框'); insert into sys_config values(7, '用户管理-账号密码更新周期', 'sys.account.passwordValidateDays', '0', 'Y', 'admin', sysdate(), '', null, '密码更新周期填写数字数据初始化值为0不限制若修改必须为大于0小于365的正整数如果超过这个周期登录系统时则在登录时就会提醒修改密码对话框');
insert into sys_config values(8, '主框架页-菜单导航显示风格', 'sys.index.menuStyle', 'default', 'Y', 'admin', sysdate(), '', null, '菜单导航显示风格default为左侧导航菜单topnav为顶部导航菜单'); insert into sys_config values(8, '主框架页-菜单导航显示风格', 'sys.index.menuStyle', 'default', 'Y', 'admin', sysdate(), '', null, '菜单导航显示风格default为左侧导航菜单topnav为顶部导航菜单');
insert into sys_config values(9, '主框架页-是否开启页脚', 'sys.index.ignoreFooter', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启底部页脚显示true显示false隐藏'); insert into sys_config values(9, '主框架页-是否开启页脚', 'sys.index.footer', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启底部页脚显示true显示false隐藏');
insert into sys_config values(10, '主框架页-是否开启页签', 'sys.index.tagsView', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启菜单多页签显示true显示false隐藏');
-- ---------------------------- -- ----------------------------