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

View File

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

View File

@ -77,4 +77,22 @@ public class DemoDialogController
{
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("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
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("demoEnabled", RuoYiConfig.isDemoEnabled());
mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
@ -98,7 +102,7 @@ public class SysIndexController extends BaseController
SysUser user = getSysUser();
if (StringUtils.isNull(user))
{
return AjaxResult.error("服务器超时,请重新登");
return AjaxResult.error("服务器超时,请重新登");
}
if (passwordService.matches(user, password))
{
@ -130,6 +134,24 @@ public class SysIndexController extends BaseController
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)
{

View File

@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController;
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.StringUtils;
import com.ruoyi.framework.web.service.ConfigService;
@ -47,7 +48,7 @@ public class SysLoginController extends BaseController
// 是否开启记住我
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";
}

View File

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

View File

@ -47,7 +47,7 @@ public class TestController extends BaseController
}
@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}")
public AjaxResult getUser(@PathVariable Integer userId)
{
@ -63,10 +63,10 @@ public class TestController extends BaseController
@ApiOperation("新增用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
})
@PostMapping("/save")
public AjaxResult save(UserEntity user)
@ -95,7 +95,7 @@ public class TestController extends BaseController
}
@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}")
public AjaxResult delete(@PathVariable Integer userId)
{

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/*!
* bootstrap-fileinput v5.2.3
* bootstrap-fileinput v5.2.4
* http://plugins.krajee.com/file-input
*
* 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
$h = {
FRAMES: '.kv-preview-thumb',
SORT_CSS: 'file-sortable',
INIT_FLAG: 'init-',
ZOOM_VAR: getLoadingUrl() + '?kvTemp__2873389129__=', // used to prevent 404 errors in URL parsing
OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
'<param name="allowFullScreen" value="true" />\n' +
'<param name="allowScriptAccess" value="always" />\n' +
@ -2972,7 +2976,7 @@
slideIn = 'slideIn' + dir, slideOut = 'slideOut' + dir, parsed, zoomData = $frame.data('zoom');
if (zoomData) {
zoomData = decodeURIComponent(zoomData);
parsed = $zoomPreview.html().setTokens({zoomData: zoomData});
parsed = $zoomPreview.html().replace($h.ZOOM_VAR, '').setTokens({zoomData: zoomData});
$zoomPreview.html(parsed);
$frame.data('zoom', '');
$zoomPreview.attr('data-zoom', zoomData);
@ -4231,7 +4235,8 @@
'fileid': fileId || '',
'typeCss': typeCss,
'footer': footer,
'data': zoom && vZoomData ? '{zoomData}' : vData,
'data': vData,
// 'data': zoom && vZoomData ? $h.ZOOM_VAR + '{zoomData}' : vData,
'template': templ || cat,
'style': styleAttribs ? 'style="' + styleAttribs + '"' : '',
'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(index, 0, draggingRow)
this.initSearch()
// Call the user defined function
this.options.onReorderRowsDrop(droppedRow)
// Call the event reorder-row
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;
}
.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 {
height: calc(100% - 80px);
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>';
$('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
$.modal.loading("数据加载中,请稍...");
$.modal.loading("数据加载中,请稍...");
$('.mainContent iframe:visible').on('load', function() {
$.modal.closeLoading();
@ -601,7 +601,7 @@ $(function() {
callback: function(key, opt) {
setActiveTab(this);
this.nextAll('.menuTab').each(function() {
$('.menuTab[data-id="' + $(this).data('id') + '"]').remove();
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
$(this).remove();
});
}
@ -630,7 +630,7 @@ $(function() {
setActiveTab(this);
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
var url = target.attr('src');
$.modal.loading("数据加载中,请稍...");
$.modal.loading("数据加载中,请稍...");
target.attr('src', url).on('load', function() {
$.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>';
$('.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() {
window.parent.$.modal.closeLoading();
});
@ -351,8 +351,10 @@ function calSumWidth(elements) {
function activeWindow() {
var topWindow = $(window.parent.document);
var currentId = $('.page-tabs-content', topWindow).find('.active').attr('data-id');
var activeWindow = $('.RuoYi_iframe[data-id="' + currentId + '"]', topWindow)[0].contentWindow;
return activeWindow;
if (!currentId) {
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);
}
// 禁止后退键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处理 */
$.ajaxSetup({
complete: function(XMLHttpRequest, textStatus) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,49 +24,97 @@
<h5>弹层框</h5>
</div>
<div class="ibox-content" id="test">
<p>弹出复选框表格及单选框表格(点击提交后得到数据并回显到父窗体</p>
<button type="button" class="btn btn-info" onclick="selectUsersToParent()">弹出表格(复选框</button>
<button type="button" class="btn btn-warning" onclick="selectUsersToParentCallBack()">弹出表格(复选框)- 回调形式</button>
<p>弹出层,点击提交后得到数据并回显到父窗体。 </p>
<button type="button" class="btn btn-primary" onclick="selectUsersToParent()">弹出表格(方式一</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>
</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>
<th:block th:include="include :: footer" />
<script type="text/javascript">
var prefix = ctx + "demo/modal";
function selectCheckUser(){
$.modal.open("选择用户", prefix + "/check");
}
function selectRadioUser(){
$.modal.open("选择用户", prefix + "/radio");
}
// 根据当前激活的选项卡获取(方式一)
function selectUsersToParent(){
$.modal.open("选择用户", prefix + "/parent");
}
function selectUsersToParentCallBack(){
// callBack获取父窗口方法方式二
function selectUsersToParentCallBack2(){
var options = {
title: '选择用户',
url: prefix + "/parent",
callBack: doSubmit
callBack: doSubmit2
};
$.modal.openOptions(options);
}
// callBack获取父窗口值方式三
function selectUsersToParentCallBack3(){
var options = {
title: '选择用户',
url: prefix + "/parent",
callBack: doSubmit3
};
$.modal.openOptions(options);
}
function doSubmit(index, layero){
// 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();
if (rows.length == 0) {
$.modal.alertWarning("请至少选择一条记录");
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);
}
function selectUsers(){
alert(1);

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('表格传值给父页面')" />
</head>
<body class="gray-bg">
<input type="hidden" id="rowIds">
<div class="container-div">
<div class="row">
<div class="col-sm-12 select-table table-striped">
@ -81,15 +82,21 @@
}
$.modal.close();
// 父页面的方法
// parent.selectUsers();
// activeWindow().selectUsers();
// 父页面的变量
parent.$('#userids').html(rows.join());
activeWindow().$('#userids').html('我是通过方式一来的:' + rows.join());
}
/* 添加用户-选择用户-提交(回调形式-父页面调用子页面) */
function getSelections() {
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>
</body>
</html>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css?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>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper">
@ -279,7 +279,7 @@
</ul>
</nav>
</div>
<div class="row content-tabs">
<div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
<button class="roll-nav roll-left tabLeft">
<i class="fa fa-backward"></i>
</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>
<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}"
th:src="@{/system/main}" frameborder="0" seamless></iframe>
th:src="@{/system/main}" frameborder="0" seamless></iframe>
</div>
<div th:if="${ignoreFooter}" class="footer">
<div th:if="${footer}" class="footer">
<div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
</div>
</div>
@ -315,8 +315,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script>
<script th:src="@{/ruoyi/js/common.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.1}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:src="@{/js/resize-tabs.js}"></script>

View File

@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.0}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.1}" rel="stylesheet"/>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper">
@ -226,7 +226,7 @@
</ul>
</nav>
</div>
<div class="row content-tabs">
<div class="row content-tabs" th:classappend="${#bools.isFalse(tagsView)} ? |hide|">
<button class="roll-nav roll-left tabLeft">
<i class="fa fa-backward"></i>
</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>
<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}"
th:src="@{/system/main}" frameborder="0" seamless></iframe>
th:src="@{/system/main}" frameborder="0" seamless></iframe>
</div>
<div th:if="${ignoreFooter}" class="footer">
<div th:if="${footer}" class="footer">
<div class="pull-right">© [[${copyrightYear}]] RuoYi Copyright </div>
</div>
</div>
@ -262,8 +262,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script>
<script th:src="@{/ruoyi/js/common.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.1}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:inline="javascript">

View File

@ -29,16 +29,16 @@
</form>
</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">
<a th:href="@{logout}">退出重新登</a>
<a th:href="@{logout}">退出重新登</a>
</div>
</div>
<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/three.min.js" th:src="@{/js/three.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.0}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.1}"></script>
</body>
<script th:inline="javascript">
var ctx = [[@{/}]];

View File

@ -9,7 +9,7 @@
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.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浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@ -59,7 +59,7 @@
<div class="checkbox-custom" th:if="${isRemembered}" th:classappend="${captchaEnabled==false} ? 'm-t'">
<input type="checkbox" id="rememberme" name="rememberme"> <label for="rememberme">记住我</label>
</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>
</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/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.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>
</body>
</html>

View File

@ -79,7 +79,7 @@
<div class="ibox-content">
<p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
</p>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <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><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
</p>
@ -96,13 +96,67 @@
<div class="ibox-content no-padding">
<div class="panel-body">
<div class="panel-group" id="version">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#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-heading">
<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>
</h5>
</div>
<div id="v470" class="panel-collapse collapse in">
<div id="v470" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<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/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.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浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@ -58,13 +58,13 @@
<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>
</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>
</div>
</div>
<div class="signup-footer">
<div class="pull-left">
&copy; 2019 All Rights Reserved. RuoYi <br>
&copy; 2018-2021 All Rights Reserved. RuoYi <br>
</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/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.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>
</body>
</html>

View File

@ -140,7 +140,7 @@
</ul>
</body>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.1}"></script>
<script type="text/javascript">
//皮肤样式列表
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) {
if (!croppable) {
$.modal.alertWarning("裁剪框加载中,请稍...");
$.modal.alertWarning("裁剪框加载中,请稍...");
return;
}
var data = {
@ -214,7 +214,7 @@ $(window).on('load', function() {
function submitHandler() {
if (!croppable) {
$.modal.alertWarning("裁剪框加载中,请稍...");
$.modal.alertWarning("裁剪框加载中,请稍...");
return
}
cropper.getCroppedCanvas().toBlob(function(img) {

View File

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

View File

@ -5,6 +5,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/**
* 自定义导出Excel数据注解
@ -108,7 +109,17 @@ public @interface Excel
/**
* 导出字段对齐方式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
{

View File

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

View File

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

View File

@ -116,4 +116,10 @@ public class Constants
* 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)
{
int len;
if ((text == null) || ((len = text.length()) == 0))
if (StringUtils.isEmpty(text))
{
return StringUtils.EMPTY;
}
StringBuilder buffer = new StringBuilder(len + (len >> 2));
final StringBuilder tmp = new StringBuilder(text.length() * 6);
char c;
for (int i = 0; i < len; i++)
for (int i = 0; i < text.length(); 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
{
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)
{
String html = "<script>alert(1);</script>";
String escape = EscapeUtil.escape(html);
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123";
// String html = "123>";
System.out.println(EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html));
System.out.println(EscapeUtil.unescape(html));
System.out.println("clean: " + EscapeUtil.clean(html));
System.out.println("escape: " + escape);
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.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
/**
* 通用http发送方法
@ -29,6 +30,17 @@ public class HttpUtils
{
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方法的请求
*
@ -55,7 +67,7 @@ public class HttpUtils
BufferedReader in = null;
try
{
String urlNameString = url + "?" + param;
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
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.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
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.Workbook;
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.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
@ -124,6 +126,16 @@ public class ExcelUtil<T>
*/
private List<Object[]> fields;
/**
* 当前行号
*/
private int rownum;
/**
* 标题
*/
private String title;
/**
* 最大高度
*/
@ -149,7 +161,7 @@ public class ExcelUtil<T>
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)
{
@ -158,8 +170,27 @@ public class ExcelUtil<T>
this.list = list;
this.sheetName = sheetName;
this.type = type;
this.title = title;
createExcelField();
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
{
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
*
* @param sheetName 表格索引名
* @param titleNum 标题占用行数
* @param is 输入流
* @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.wb = WorkbookFactory.create(is);
@ -209,7 +253,7 @@ public class ExcelUtil<T>
// 定义一个map用于存放excel列的序号和field.
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++)
{
Cell cell = heard.getCell(i);
@ -224,25 +268,18 @@ public class ExcelUtil<T>
}
}
// 有数据时才处理 得到类的所有field.
Field[] allFields = clazz.getDeclaredFields();
// 定义一个map用于存放列的序号和field.
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
for (int col = 0; col < allFields.length; col++)
List<Object[]> fields = this.getFields();
Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
for (Object[] objects : fields)
{
Field field = allFields[col];
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
Excel attr = (Excel) objects[1];
Integer column = cellMap.get(attr.name());
if (column != null)
{
// 设置类的私有字段属性可访问.
field.setAccessible(true);
Integer column = cellMap.get(attr.name());
if (column != null)
{
fieldsMap.put(column, field);
}
fieldsMap.put(column, objects);
}
}
for (int i = 1; i <= rows; i++)
for (int i = titleNum + 1; i <= rows; i++)
{
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
@ -252,14 +289,15 @@ public class ExcelUtil<T>
continue;
}
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());
// 如果不存在实例则新建.
entity = (entity == null ? clazz.newInstance() : entity);
// 从map中得到对应列的field.
Field field = fieldsMap.get(entry.getKey());
Field field = (Field) entry.getValue()[0];
Excel attr = (Excel) entry.getValue()[1];
// 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType();
if (String.class == fieldType)
@ -319,7 +357,6 @@ public class ExcelUtil<T>
}
if (StringUtils.isNotNull(fieldType))
{
Excel attr = field.getAnnotation(Excel.class);
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr()))
{
@ -333,6 +370,10 @@ public class ExcelUtil<T>
{
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))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
@ -340,8 +381,11 @@ public class ExcelUtil<T>
{
val = "";
}
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
else
{
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
}
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
@ -361,7 +405,20 @@ public class ExcelUtil<T>
*/
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();
}
@ -374,11 +431,26 @@ public class ExcelUtil<T>
* @return 结果
* @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.setCharacterEncoding("utf-8");
this.init(list, sheetName, Type.EXPORT);
this.init(list, sheetName, title, Type.EXPORT);
exportExcel(response.getOutputStream());
}
@ -390,7 +462,19 @@ public class ExcelUtil<T>
*/
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();
}
@ -401,10 +485,22 @@ public class ExcelUtil<T>
* @return 结果
*/
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.setCharacterEncoding("utf-8");
this.init(null, sheetName, Type.IMPORT);
this.init(null, sheetName, title, Type.IMPORT);
exportExcel(response.getOutputStream());
}
@ -465,13 +561,13 @@ public class ExcelUtil<T>
public void writeSheet()
{
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++)
int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
for (int index = 0; index < sheetNo; index++)
{
createSheet(sheetNo, index);
// 产生一行
Row row = sheet.createRow(0);
Row row = sheet.createRow(rownum);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
@ -499,7 +595,7 @@ public class ExcelUtil<T>
int endNo = Math.min(startNo + sheetSize, list.size());
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);
int column = 0;
@ -507,8 +603,6 @@ public class ExcelUtil<T>
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
// 设置实体类私有属性可访问
field.setAccessible(true);
this.addCell(excel, row, vo, field, column++);
}
}
@ -527,6 +621,16 @@ public class ExcelUtil<T>
CellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.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.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
@ -726,6 +830,10 @@ public class ExcelUtil<T>
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
cell.setCellValue(dataFormatHandlerAdapter(value, attr));
}
else
{
// 设置列类型
@ -898,6 +1006,28 @@ public class ExcelUtil<T>
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()
{
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<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
@ -1034,7 +1174,12 @@ public class ExcelUtil<T>
// 单注解
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);
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);
}
/**
* 放到字段集合中
*/
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()
{
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 index 序号
*/
public void createSheet(double sheetNo, int index)
public void createSheet(int sheetNo, int index)
{
this.sheet = wb.createSheet();
this.styles = createStyles(wb);
// 设置工作表的名称.
if (sheetNo == 0)
{
wb.setSheetName(index, sheetName);
}
else
if (sheetNo > 1 && index > 0)
{
this.sheet = wb.createSheet();
this.createTitle();
wb.setSheetName(index, sheetName + index);
}
}

View File

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

View File

@ -1,12 +1,8 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity;
@ -54,27 +50,15 @@ public class DataScopeAspect
*/
public static final String DATA_SCOPE = "dataScope";
// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)")
public void dataScopePointCut()
{
}
@Before("dataScopePointCut()")
public void doBefore(JoinPoint point) throws Throwable
@Before("@annotation(controllerDataScope)")
public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
{
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();
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参数防止注入
*/

View File

@ -1,18 +1,14 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
@ -56,10 +51,10 @@ public class LogAspect
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "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 e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e)
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "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
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser();
@ -94,12 +82,6 @@ public class LogAspect
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
// 返回参数
if (StringUtils.isNotNull(jsonResult))
{
operLog.setJsonResult(StringUtils.substring(JSON.marshal(jsonResult), 0, 2000));
}
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (currentUser != null)
{
@ -123,7 +105,7 @@ public class LogAspect
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 保存数据库
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
}
@ -143,7 +125,7 @@ public class LogAspect
* @param operLog 操作日志
* @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动作
operLog.setBusinessType(log.businessType().ordinal());
@ -157,6 +139,11 @@ public class LogAspect
// 获取参数的信息,传入到数据库中。
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,12 +187,18 @@ public class LogAspect
String params = "";
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());
params += jsonObj.toString() + " ";
try
{
Object jsonObj = JSONObject.toJSONString(o, excludePropertyPreFilter());
params += jsonObj.toString() + " ";
}
catch (Exception e)
{
}
}
}
}
@ -245,17 +222,17 @@ public class LogAspect
else if (Collection.class.isAssignableFrom(clazz))
{
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))
{
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;
}
}

View File

@ -5,19 +5,19 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
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.core.domain.AjaxResult;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.ServletUtils;
/**
* 防止重复提交拦截器
*
*
* @author ruoyi
*/
@Component
public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
{
@Override
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);
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));
return false;
}
@ -40,16 +40,16 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
}
else
{
return super.preHandle(request, response, handler);
return true;
}
}
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*
* @param request
* @return
* @throws Exception
*
* @param request 请求对象
* @param annotation 防复注解
* @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.HttpSession;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.json.JSON;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
@ -23,21 +24,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
public final String SESSION_REPEAT_KEY = "repeatData";
/**
* 间隔时间,单位:秒 默认10秒
*
* 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
*/
private int intervalTime = 10;
public void setIntervalTime(int intervalTime)
{
this.intervalTime = intervalTime;
}
@SuppressWarnings("unchecked")
@Override
public boolean isRepeatSubmit(HttpServletRequest request) throws Exception
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception
{
// 本次参数及系统时间
String nowParams = JSON.marshal(request.getParameterMap());
@ -56,7 +45,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
if (sessionMap.containsKey(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;
}
@ -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 time2 = (Long) preMap.get(REPEAT_TIME);
if ((time1 - time2) < (this.intervalTime * 1000))
if ((time1 - time2) < interval)
{
return true;
}

View File

@ -2,7 +2,6 @@ package com.ruoyi.framework.shiro.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
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.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysUserService;
@ -104,7 +104,7 @@ public class SysLoginService
passwordService.validate(user, password);
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
recordLoginInfo(user);
recordLoginInfo(user.getUserId());
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.setLoginDate(DateUtils.getNowDate());
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.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
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.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysUserService;
@ -36,7 +36,7 @@ public class SysRegisterService
{
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 = "验证码错误";
}

View File

@ -1,34 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-generator</artifactId>
<description>
generator代码生成
</description>
<dependencies>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.7.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-generator</artifactId>
<description>
generator代码生成
</description>
<dependencies>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -7,6 +7,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.RequestMapping;
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.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
@ -106,6 +111,15 @@ public class GenController extends BaseController
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);
// 查询表信息
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
String operName = (String) PermissionUtils.getPrincipalProperty("loginName");
String operName = Convert.toStr(PermissionUtils.getPrincipalProperty("loginName"));
genTableService.importGenTable(tableList, operName);
return AjaxResult.success();
}
@ -175,6 +189,39 @@ public class GenController extends BaseController
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

@ -1,83 +1,91 @@
package com.ruoyi.generator.mapper;
import java.util.List;
import com.ruoyi.generator.domain.GenTable;
/**
* 业务 数据层
*
* @author ruoyi
*/
public interface GenTableMapper
{
/**
* 查询业务列表
*
* @param genTable 业务信息
* @return 业务集合
*/
public List<GenTable> selectGenTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param genTable 业务信息
* @return 数据库表集合
*/
public List<GenTable> selectDbTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param tableNames 表名称组
* @return 数据库表集合
*/
public List<GenTable> selectDbTableListByNames(String[] tableNames);
/**
* 查询所有表信息
*
* @return 表信息集合
*/
public List<GenTable> selectGenTableAll();
/**
* 查询表ID业务信息
*
* @param id 业务ID
* @return 业务信息
*/
public GenTable selectGenTableById(Long id);
/**
* 查询表名称业务信息
*
* @param tableName 表名称
* @return 业务信息
*/
public GenTable selectGenTableByName(String tableName);
/**
* 新增业务
*
* @param genTable 业务信息
* @return 结果
*/
public int insertGenTable(GenTable genTable);
/**
* 修改业务
*
* @param genTable 业务信息
* @return 结果
*/
public int updateGenTable(GenTable genTable);
/**
* 批量删除业务
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteGenTableByIds(Long[] ids);
package com.ruoyi.generator.mapper;
import java.util.List;
import com.ruoyi.generator.domain.GenTable;
/**
* 业务 数据层
*
* @author ruoyi
*/
public interface GenTableMapper
{
/**
* 查询业务列表
*
* @param genTable 业务信息
* @return 业务集合
*/
public List<GenTable> selectGenTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param genTable 业务信息
* @return 数据库表集合
*/
public List<GenTable> selectDbTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param tableNames 表名称组
* @return 数据库表集合
*/
public List<GenTable> selectDbTableListByNames(String[] tableNames);
/**
* 查询所有表信息
*
* @return 表信息集合
*/
public List<GenTable> selectGenTableAll();
/**
* 查询表ID业务信息
*
* @param id 业务ID
* @return 业务信息
*/
public GenTable selectGenTableById(Long id);
/**
* 查询表名称业务信息
*
* @param tableName 表名称
* @return 业务信息
*/
public GenTable selectGenTableByName(String tableName);
/**
* 新增业务
*
* @param genTable 业务信息
* @return 结果
*/
public int insertGenTable(GenTable genTable);
/**
* 修改业务
*
* @param genTable 业务信息
* @return 结果
*/
public int updateGenTable(GenTable genTable);
/**
* 批量删除业务
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteGenTableByIds(Long[] ids);
/**
* 创建表
*
* @param sql
* @return 结果
*/
public int createTable(String sql);
}

View File

@ -1,121 +1,129 @@
package com.ruoyi.generator.service;
import java.util.List;
import java.util.Map;
import com.ruoyi.generator.domain.GenTable;
/**
* 业务 服务层
*
* @author ruoyi
*/
public interface IGenTableService
{
/**
* 查询业务列表
*
* @param genTable 业务信息
* @return 业务集合
*/
public List<GenTable> selectGenTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param genTable 业务信息
* @return 数据库表集合
*/
public List<GenTable> selectDbTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param tableNames 表名称组
* @return 数据库表集合
*/
public List<GenTable> selectDbTableListByNames(String[] tableNames);
/**
* 查询所有表信息
*
* @return 表信息集合
*/
public List<GenTable> selectGenTableAll();
/**
* 查询业务信息
*
* @param id 业务ID
* @return 业务信息
*/
public GenTable selectGenTableById(Long id);
/**
* 修改业务
*
* @param genTable 业务信息
* @return 结果
*/
public void updateGenTable(GenTable genTable);
/**
* 删除业务信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public void deleteGenTableByIds(String ids);
/**
* 导入表结构
*
* @param tableList 导入表列表
* @param operName 操作人员
*/
public void importGenTable(List<GenTable> tableList, String operName);
/**
* 预览代码
*
* @param tableId 表编号
* @return 预览数据列表
*/
public Map<String, String> previewCode(Long tableId);
/**
* 生成代码(下载方式)
*
* @param tableName 表名称
* @return 数据
*/
public byte[] downloadCode(String tableName);
/**
* 生成代码(自定义路径
*
* @param tableName 表名称
*/
public void generatorCode(String tableName);
/**
* 同步数据库
*
* @param tableName 表名称
*/
public void synchDb(String tableName);
/**
* 批量生成代码(下载方式)
*
* @param tableNames 表数组
* @return 数据
*/
public byte[] downloadCode(String[] tableNames);
/**
* 修改保存参数校验
*
* @param genTable 业务信息
*/
public void validateEdit(GenTable genTable);
}
package com.ruoyi.generator.service;
import java.util.List;
import java.util.Map;
import com.ruoyi.generator.domain.GenTable;
/**
* 业务 服务层
*
* @author ruoyi
*/
public interface IGenTableService
{
/**
* 查询业务列表
*
* @param genTable 业务信息
* @return 业务集合
*/
public List<GenTable> selectGenTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param genTable 业务信息
* @return 数据库表集合
*/
public List<GenTable> selectDbTableList(GenTable genTable);
/**
* 查询据库列表
*
* @param tableNames 表名称组
* @return 数据库表集合
*/
public List<GenTable> selectDbTableListByNames(String[] tableNames);
/**
* 查询所有表信息
*
* @return 表信息集合
*/
public List<GenTable> selectGenTableAll();
/**
* 查询业务信息
*
* @param id 业务ID
* @return 业务信息
*/
public GenTable selectGenTableById(Long id);
/**
* 修改业务
*
* @param genTable 业务信息
* @return 结果
*/
public void updateGenTable(GenTable genTable);
/**
* 删除业务信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public void deleteGenTableByIds(String ids);
/**
* 创建表
*
* @param sql 创建表语句
* @return 结果
*/
public int createTable(String sql);
/**
* 导入表结构
*
* @param tableList 导入表列表
* @param operName 操作人员
*/
public void importGenTable(List<GenTable> tableList, String operName);
/**
* 预览代码
*
* @param tableId 表编号
* @return 预览数据列表
*/
public Map<String, String> previewCode(Long tableId);
/**
* 生成代码(下载方式
*
* @param tableName 表名称
* @return 数据
*/
public byte[] downloadCode(String tableName);
/**
* 生成代码(自定义路径)
*
* @param tableName 表名称
*/
public void generatorCode(String tableName);
/**
* 同步数据库
*
* @param tableName 表名称
*/
public void synchDb(String tableName);
/**
* 批量生成代码(下载方式)
*
* @param tableNames 表数组
* @return 数据
*/
public byte[] downloadCode(String[] tableNames);
/**
* 修改保存参数校验
*
* @param genTable 业务信息
*/
public void validateEdit(GenTable genTable);
}

View File

@ -1,189 +1,194 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
<resultMap type="GenTable" id="GenTableResult">
<id property="tableId" column="table_id" />
<result property="tableName" column="table_name" />
<result property="tableComment" column="table_comment" />
<result property="subTableName" column="sub_table_name" />
<result property="subTableFkName" column="sub_table_fk_name" />
<result property="className" column="class_name" />
<result property="tplCategory" column="tpl_category" />
<result property="packageName" column="package_name" />
<result property="moduleName" column="module_name" />
<result property="businessName" column="business_name" />
<result property="functionName" column="function_name" />
<result property="functionAuthor" column="function_author" />
<result property="genType" column="gen_type" />
<result property="genPath" column="gen_path" />
<result property="options" column="options" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
</resultMap>
<resultMap type="GenTableColumn" id="GenTableColumnResult">
<id property="columnId" column="column_id" />
<result property="tableId" column="table_id" />
<result property="columnName" column="column_name" />
<result property="columnComment" column="column_comment" />
<result property="columnType" column="column_type" />
<result property="javaType" column="java_type" />
<result property="javaField" column="java_field" />
<result property="isPk" column="is_pk" />
<result property="isIncrement" column="is_increment" />
<result property="isRequired" column="is_required" />
<result property="isInsert" column="is_insert" />
<result property="isEdit" column="is_edit" />
<result property="isList" column="is_list" />
<result property="isQuery" column="is_query" />
<result property="queryType" column="query_type" />
<result property="htmlType" column="html_type" />
<result property="dictType" column="dict_type" />
<result property="sort" column="sort" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectGenTableVo">
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
</sql>
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
<include refid="selectGenTableVo"/>
<where>
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
</if>
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
</where>
</select>
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_schema = (select database())
AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT IN (select table_name from gen_table)
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
</if>
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
</select>
<select id="selectDbTableListByNames" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</select>
<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
and table_name = #{tableName}
</select>
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
where t.table_id = #{tableId} order by c.sort
</select>
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
where t.table_name = #{tableName} order by c.sort
</select>
<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
order by c.sort
</select>
<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
insert into gen_table (
<if test="tableName != null">table_name,</if>
<if test="tableComment != null and tableComment != ''">table_comment,</if>
<if test="className != null and className != ''">class_name,</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
<if test="packageName != null and packageName != ''">package_name,</if>
<if test="moduleName != null and moduleName != ''">module_name,</if>
<if test="businessName != null and businessName != ''">business_name,</if>
<if test="functionName != null and functionName != ''">function_name,</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
<if test="genType != null and genType != ''">gen_type,</if>
<if test="genPath != null and genPath != ''">gen_path,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
)values(
<if test="tableName != null">#{tableName},</if>
<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
<if test="className != null and className != ''">#{className},</if>
<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
<if test="packageName != null and packageName != ''">#{packageName},</if>
<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
<if test="businessName != null and businessName != ''">#{businessName},</if>
<if test="functionName != null and functionName != ''">#{functionName},</if>
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
<if test="genType != null and genType != ''">#{genType},</if>
<if test="genPath != null and genPath != ''">#{genPath},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate()
)
</insert>
<update id="updateGenTable" parameterType="GenTable">
update gen_table
<set>
<if test="tableName != null">table_name = #{tableName},</if>
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
<if test="subTableName != null">sub_table_name = #{subTableName},</if>
<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
<if test="className != null and className != ''">class_name = #{className},</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
<if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
<if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
<if test="options != null and options != ''">options = #{options},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="remark != null">remark = #{remark},</if>
update_time = sysdate()
</set>
where table_id = #{tableId}
</update>
<delete id="deleteGenTableByIds" parameterType="Long">
delete from gen_table where table_id in
<foreach collection="array" item="tableId" open="(" separator="," close=")">
#{tableId}
</foreach>
</delete>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
<resultMap type="GenTable" id="GenTableResult">
<id property="tableId" column="table_id" />
<result property="tableName" column="table_name" />
<result property="tableComment" column="table_comment" />
<result property="subTableName" column="sub_table_name" />
<result property="subTableFkName" column="sub_table_fk_name" />
<result property="className" column="class_name" />
<result property="tplCategory" column="tpl_category" />
<result property="packageName" column="package_name" />
<result property="moduleName" column="module_name" />
<result property="businessName" column="business_name" />
<result property="functionName" column="function_name" />
<result property="functionAuthor" column="function_author" />
<result property="genType" column="gen_type" />
<result property="genPath" column="gen_path" />
<result property="options" column="options" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
</resultMap>
<resultMap type="GenTableColumn" id="GenTableColumnResult">
<id property="columnId" column="column_id" />
<result property="tableId" column="table_id" />
<result property="columnName" column="column_name" />
<result property="columnComment" column="column_comment" />
<result property="columnType" column="column_type" />
<result property="javaType" column="java_type" />
<result property="javaField" column="java_field" />
<result property="isPk" column="is_pk" />
<result property="isIncrement" column="is_increment" />
<result property="isRequired" column="is_required" />
<result property="isInsert" column="is_insert" />
<result property="isEdit" column="is_edit" />
<result property="isList" column="is_list" />
<result property="isQuery" column="is_query" />
<result property="queryType" column="query_type" />
<result property="htmlType" column="html_type" />
<result property="dictType" column="dict_type" />
<result property="sort" column="sort" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectGenTableVo">
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
</sql>
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
<include refid="selectGenTableVo"/>
<where>
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
</if>
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
</where>
</select>
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_schema = (select database())
AND table_name NOT LIKE 'QRTZ_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT IN (select table_name from gen_table)
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
</if>
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
order by create_time desc
</select>
<select id="selectDbTableListByNames" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</select>
<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
and table_name = #{tableName}
</select>
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
where t.table_id = #{tableId} order by c.sort
</select>
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
where t.table_name = #{tableName} order by c.sort
</select>
<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
order by c.sort
</select>
<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
insert into gen_table (
<if test="tableName != null">table_name,</if>
<if test="tableComment != null and tableComment != ''">table_comment,</if>
<if test="className != null and className != ''">class_name,</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
<if test="packageName != null and packageName != ''">package_name,</if>
<if test="moduleName != null and moduleName != ''">module_name,</if>
<if test="businessName != null and businessName != ''">business_name,</if>
<if test="functionName != null and functionName != ''">function_name,</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
<if test="genType != null and genType != ''">gen_type,</if>
<if test="genPath != null and genPath != ''">gen_path,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
)values(
<if test="tableName != null">#{tableName},</if>
<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
<if test="className != null and className != ''">#{className},</if>
<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
<if test="packageName != null and packageName != ''">#{packageName},</if>
<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
<if test="businessName != null and businessName != ''">#{businessName},</if>
<if test="functionName != null and functionName != ''">#{functionName},</if>
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
<if test="genType != null and genType != ''">#{genType},</if>
<if test="genPath != null and genPath != ''">#{genPath},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate()
)
</insert>
<update id="createTable">
${sql}
</update>
<update id="updateGenTable" parameterType="GenTable">
update gen_table
<set>
<if test="tableName != null">table_name = #{tableName},</if>
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
<if test="subTableName != null">sub_table_name = #{subTableName},</if>
<if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
<if test="className != null and className != ''">class_name = #{className},</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
<if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
<if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
<if test="options != null and options != ''">options = #{options},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="remark != null">remark = #{remark},</if>
update_time = sysdate()
</set>
where table_id = #{tableId}
</update>
<delete id="deleteGenTableByIds" parameterType="Long">
delete from gen_table where table_id in
<foreach collection="array" item="tableId" open="(" separator="," close=")">
#{tableId}
</foreach>
</delete>
</mapper>

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: '字典类型',
width: "13%",
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>";
},
cellStyle: function(value, row, index) {

View File

@ -1,209 +1,218 @@
<!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('代码生成列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="gen-form">
<div class="select-list">
<ul>
<li>
表名称:<input type="text" name="tableName"/>
</li>
<li>
表描述:<input type="text" name="tableComment"/>
</li>
<li class="select-time">
<label>表时间: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
<span>-</span>
<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
<i class="fa fa-download"></i> 生成
</a>
<a class="btn btn-info" onclick="importTable()">
<i class="fa fa-upload"></i> 导入
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.editTab()" shiro:hasPermission="tool:gen:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="tool:gen:remove">
<i class="fa fa-remove"></i> 删除
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: bootstrap-table-export-js" />
<script th:src="@{/ajax/libs/highlight/highlight.min.js}"></script>
<script th:inline="javascript">
var prefix = ctx + "tool/gen";
var editFlag = [[${@permission.hasPermi('tool:gen:edit')}]];
var removeFlag = [[${@permission.hasPermi('tool:gen:remove')}]];
var previewFlag = [[${@permission.hasPermi('tool:gen:preview')}]];
var codeFlag = [[${@permission.hasPermi('tool:gen:code')}]];
$(function() {
var options = {
url: prefix + "/list",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
sortName: "createTime",
sortOrder: "desc",
showExport: true,
modalName: "生成配置",
rememberSelected: true,
uniqueId: "tableId",
columns: [{
field: 'state',
checkbox: true
},
{
field: 'tableId',
title: '编号',
visible: false
},
{
title: "序号",
formatter: function (value, row, index) {
return $.table.serialNumber(index);
}
},
{
field: 'tableName',
title: '表名称',
sortable: true,
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
field: 'tableComment',
title: '表描述',
sortable: true,
formatter: function(value, row, index) {
return $.table.tooltip(value, 15);
}
},
{
field: 'className',
title: '实体类名称',
sortable: true
},
{
field: 'createTime',
title: '创建时间',
sortable: true
},
{
field: 'updateTime',
title: '更新时间',
sortable: true
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs ' + previewFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.tableId + '\')"><i class="fa fa-search"></i>预览</a> ');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.tableId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.tableId + '\')"><i class="fa fa-remove"></i>删除</a> ');
actions.push('<a class="btn btn-warning btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="synchDb(\'' + row.tableName + '\')"><i class="fa fa-refresh"></i>同步</a> ');
actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\',\'' + row.genType + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
return actions.join('');
}
}]
};
$.table.init(options);
});
// 预览代码
function preview(tableId) {
var preViewUrl = prefix + "/preview/" + tableId;
$.modal.loading("正在加载数据,请稍后...");
$.get(preViewUrl, function(result) {
if (result.code == web_status.SUCCESS) {
var items = [];
$.each(result.data, function(index, value) {
var templateName = index.substring(index.lastIndexOf("/") + 1, index.length).replace(/\.vm/g, "");
if(!$.common.equals("sql", templateName) && !$.common.equals("tree.html", templateName) && !$.common.equals("sub-domain.java", templateName)){
var language = templateName.substring(templateName.lastIndexOf(".") + 1);
var highCode = hljs.highlight(language, value).value;
items.push({
title: templateName , content: "<pre class=\"layui-code\"><code>" + highCode + "</code></pre>"
})
}
});
top.layer.tab({
area: ['90%', '90%'],
shadeClose: true,
success: function(layero, index){
parent.loadCss(ctx + "ajax/libs/highlight/default.min.css");
},
tab: items
});
} else {
$.modal.alertError(result.msg);
}
$.modal.closeLoading();
});
}
// 生成代码
function genCode(tableName, genType) {
$.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
if(genType === "0") {
location.href = prefix + "/download/" + tableName;
layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
} else if(genType === "1") {
$.operate.get(prefix + "/genCode/" + tableName);
}
})
}
// 同步数据库
function synchDb(tableName){
$.modal.confirm("确认要强制同步" + tableName + "表结构吗?", function() {
$.operate.get(prefix + "/synchDb/" + tableName);
})
}
// 批量生成代码
function batchGenCode() {
var rows = $.table.selectColumns("tableName");
if (rows.length == 0) {
$.modal.alertWarning("请选择要生成的数据");
return;
}
$.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() {
location.href = prefix + "/batchGenCode?tables=" + rows;
layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
});
}
// 导入表结构
function importTable() {
var importTableUrl = prefix + "/importTable";
$.modal.open("导入表结构", importTableUrl);
}
</script>
</body>
<!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('代码生成列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="gen-form">
<div class="select-list">
<ul>
<li>
表名称:<input type="text" name="tableName"/>
</li>
<li>
表描述:<input type="text" name="tableComment"/>
</li>
<li class="select-time">
<label>表时间: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
<span>-</span>
<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
<i class="fa fa-download"></i> 生成
</a>
<a class="btn btn-success" onclick="createTable()">
<i class="fa fa-plus"></i> 创建
</a>
<a class="btn btn-info" onclick="importTable()">
<i class="fa fa-upload"></i> 导入
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.editTab()" shiro:hasPermission="tool:gen:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="tool:gen:remove">
<i class="fa fa-remove"></i> 删除
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: bootstrap-table-export-js" />
<script th:src="@{/ajax/libs/highlight/highlight.min.js}"></script>
<script th:inline="javascript">
var prefix = ctx + "tool/gen";
var editFlag = [[${@permission.hasPermi('tool:gen:edit')}]];
var removeFlag = [[${@permission.hasPermi('tool:gen:remove')}]];
var previewFlag = [[${@permission.hasPermi('tool:gen:preview')}]];
var codeFlag = [[${@permission.hasPermi('tool:gen:code')}]];
$(function() {
var options = {
url: prefix + "/list",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
sortName: "createTime",
sortOrder: "desc",
showExport: true,
modalName: "生成配置",
rememberSelected: true,
uniqueId: "tableId",
columns: [{
field: 'state',
checkbox: true
},
{
field: 'tableId',
title: '编号',
visible: false
},
{
title: "序号",
formatter: function (value, row, index) {
return $.table.serialNumber(index);
}
},
{
field: 'tableName',
title: '表名称',
sortable: true,
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
field: 'tableComment',
title: '表描述',
sortable: true,
formatter: function(value, row, index) {
return $.table.tooltip(value, 15);
}
},
{
field: 'className',
title: '实体类名称',
sortable: true
},
{
field: 'createTime',
title: '创建时间',
sortable: true
},
{
field: 'updateTime',
title: '更新时间',
sortable: true
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs ' + previewFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.tableId + '\')"><i class="fa fa-search"></i>预览</a> ');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.tableId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.tableId + '\')"><i class="fa fa-remove"></i>删除</a> ');
actions.push('<a class="btn btn-warning btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="synchDb(\'' + row.tableName + '\')"><i class="fa fa-refresh"></i>同步</a> ');
actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\',\'' + row.genType + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
return actions.join('');
}
}]
};
$.table.init(options);
});
// 预览代码
function preview(tableId) {
var preViewUrl = prefix + "/preview/" + tableId;
$.modal.loading("正在加载数据,请稍候...");
$.get(preViewUrl, function(result) {
if (result.code == web_status.SUCCESS) {
var items = [];
$.each(result.data, function(index, value) {
var templateName = index.substring(index.lastIndexOf("/") + 1, index.length).replace(/\.vm/g, "");
if(!$.common.equals("sql", templateName) && !$.common.equals("tree.html", templateName) && !$.common.equals("sub-domain.java", templateName)){
var language = templateName.substring(templateName.lastIndexOf(".") + 1);
var highCode = hljs.highlight(language, value).value;
items.push({
title: templateName , content: "<pre class=\"layui-code\"><code>" + highCode + "</code></pre>"
})
}
});
top.layer.tab({
area: ['90%', '90%'],
shadeClose: true,
success: function(layero, index){
parent.loadCss(ctx + "ajax/libs/highlight/default.min.css");
},
tab: items
});
} else {
$.modal.alertError(result.msg);
}
$.modal.closeLoading();
});
}
// 生成代码
function genCode(tableName, genType) {
$.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
if(genType === "0") {
location.href = prefix + "/download/" + tableName;
layer.msg('执行成功,正在生成代码请稍候…', { icon: 1 });
} else if(genType === "1") {
$.operate.get(prefix + "/genCode/" + tableName);
}
})
}
// 同步数据库
function synchDb(tableName){
$.modal.confirm("确认要强制同步" + tableName + "表结构吗?", function() {
$.operate.get(prefix + "/synchDb/" + tableName);
})
}
// 批量生成代码
function batchGenCode() {
var rows = $.table.selectColumns("tableName");
if (rows.length == 0) {
$.modal.alertWarning("请选择要生成的数据");
return;
}
$.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() {
location.href = prefix + "/batchGenCode?tables=" + rows;
layer.msg('执行成功,正在生成代码请稍候…', { icon: 1 });
});
}
// 导入表结构
function importTable() {
var importTableUrl = prefix + "/importTable";
$.modal.open("导入表结构", importTableUrl);
}
// 创建表结构
function createTable() {
var creatTableUrl = prefix + "/createTable";
$.modal.open("创建表结构", creatTableUrl);
}
</script>
</body>
</html>

View File

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

View File

@ -69,7 +69,7 @@ public interface ${ClassName}Mapper
* @param ${pkColumn.javaField}s 需要删除的数据主键集合
* @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}
@ -86,6 +86,6 @@ public interface ${ClassName}Mapper
* @param ${pkColumn.javaField} ${functionName}ID
* @return 结果
*/
public int delete${subClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
#end
}

View File

@ -157,9 +157,21 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
for (${ClassName} ${className} : ${className}List)
{
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)})
#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)})
#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)})
#end
ztree.setId(${className}.get${TreeCode}());
ztree.setpId(${className}.get${TreeParentCode}());
ztree.setName(${className}.get${TreeName}());

View File

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

View File

@ -148,6 +148,11 @@ public class SysJobController extends BaseController
{
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));
}
@ -186,6 +191,10 @@ public class SysJobController extends BaseController
{
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));
}

View File

@ -1131,7 +1131,7 @@
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.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:inline="javascript">
var prefix = [[@{/}]] + "monitor/job";

View File

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

26
ry.bat
View File

@ -4,36 +4,36 @@ rem jarƽ
set AppName=ruoyi-admin.jar
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.
ECHO. [1] <20><><EFBFBD><EFBFBD>%AppName%
ECHO. [2] <20>ر<EFBFBD>%AppName%
ECHO. [3] <20><><EFBFBD><EFBFBD>%AppName%
ECHO. [4] <20><><EFBFBD><EFBFBD>״̬ %AppName%
ECHO. [5] <20><> <20><>
ECHO.
ECHO. [5] <20><> <20><>
ECHO.
ECHO.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
set /p ID=
IF "%id%"=="1" GOTO start
IF "%id%"=="2" GOTO stop
IF "%id%"=="3" GOTO restart
IF "%id%"=="1" GOTO start
IF "%id%"=="2" GOTO stop
IF "%id%"=="3" GOTO restart
IF "%id%"=="4" GOTO status
IF "%id%"=="5" EXIT
PAUSE
PAUSE
:start
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
set pid=%%a
set image_name=%%b
)
if defined pid (
echo %%is running
PAUSE
)
echo %%is running
PAUSE
)
start javaw -jar %JAVA_OPTS% ruoyi-admin.jar
start javaw %JAVA_OPTS% -jar %AppName%
echo starting<6E><67><EFBFBD><EFBFBD>
echo Start %AppName% success...
@ -64,4 +64,4 @@ goto:eof
if not defined pid (echo process %AppName% is dead ) else (
echo %image_name% is running
)
goto:eof
goto:eof

12
ry.sh
View File

@ -1,13 +1,9 @@
#!/bin/sh
# author ruoyi
# ./ry.sh start 启动
# ./ry.sh stop 停止
# ./ry.sh restart 重启
# ./ry.sh status 状态
# ./ry.sh start 启动 stop 停止 restart 重启 status 状态
AppName=ruoyi-admin.jar
# 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`
LOG_PATH=$APP_HOME/logs/$AppName.log
@ -30,7 +26,7 @@ function start()
if [ x"$PID" != x"" ]; then
echo "$AppName is running..."
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..."
fi
}
@ -38,7 +34,7 @@ function start()
function stop()
{
echo "Stop $AppName"
PID=""
query(){
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`

View File

@ -535,15 +535,16 @@ create table sys_config (
primary key (config_id)
) engine=innodb auto_increment=100 comment = '参数配置表';
insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow');
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456');
insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深黑主题theme-dark浅色主题theme-light深蓝主题theme-blue');
insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能true开启false关闭');
insert into sys_config values(5, '用户管理-密码字符范围', 'sys.account.chrtype', '0', 'Y', 'admin', sysdate(), '', null, '默认任意字符范围0任意密码可以输入任意字符1数字密码只能为0-9数字2英文字母密码只能为a-z和A-Z字母3字母和数字密码必须包含字母数字,4字母数字和特殊字符目前支持的特殊字符包括~!@#$%^&*()-=_+');
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(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(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow');
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456');
insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深黑主题theme-dark浅色主题theme-light深蓝主题theme-blue');
insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能true开启false关闭');
insert into sys_config values(5, '用户管理-密码字符范围', 'sys.account.chrtype', '0', 'Y', 'admin', sysdate(), '', null, '默认任意字符范围0任意密码可以输入任意字符1数字密码只能为0-9数字2英文字母密码只能为a-z和A-Z字母3字母和数字密码必须包含字母数字,4字母数字和特殊字符目前支持的特殊字符包括~!@#$%^&*()-=_+');
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(8, '主框架页-菜单导航显示风格', 'sys.index.menuStyle', 'default', 'Y', 'admin', sysdate(), '', null, '菜单导航显示风格default为左侧导航菜单topnav为顶部导航菜单');
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隐藏');
-- ----------------------------