Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2deb14284 | ||
|
|
2ebedeb5df | ||
|
|
e4585f5dcb | ||
|
|
62db29627a | ||
|
|
b15106d139 | ||
|
|
d7a2e80bf6 | ||
|
|
e405becf9a | ||
|
|
e8d8325ead | ||
|
|
c21eb3507b | ||
|
|
c92059d356 | ||
|
|
b36ba5a16c | ||
|
|
cc74bde7be | ||
|
|
7358a2027d | ||
|
|
21ea871ada | ||
|
|
1207052749 | ||
|
|
6f8a388e8e |
@@ -17,7 +17,7 @@
|
||||
<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.10.1</shiro.version>
|
||||
<shiro.version>1.12.0</shiro.version>
|
||||
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
|
||||
<druid.version>1.2.16</druid.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
@@ -25,7 +25,7 @@
|
||||
<swagger.version>3.0.0</swagger.version>
|
||||
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<oshi.version>6.4.1</oshi.version>
|
||||
<oshi.version>6.4.3</oshi.version>
|
||||
<commons.io.version>2.11.0</commons.io.version>
|
||||
<poi.version>4.1.2</poi.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
@@ -39,7 +39,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>2.5.15</version>
|
||||
<configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
</configuration>
|
||||
|
||||
@@ -58,15 +58,15 @@ spring:
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
profiles:
|
||||
profiles:
|
||||
active: druid
|
||||
# 文件上传
|
||||
servlet:
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
@@ -75,18 +75,18 @@ spring:
|
||||
|
||||
# MyBatis
|
||||
mybatis:
|
||||
# 搜索指定包别名
|
||||
typeAliasesPackage: com.ruoyi.**.domain
|
||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 加载全局的配置文件
|
||||
configLocation: classpath:mybatis/mybatis-config.xml
|
||||
# 搜索指定包别名
|
||||
typeAliasesPackage: com.ruoyi.**.domain
|
||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 加载全局的配置文件
|
||||
configLocation: classpath:mybatis/mybatis-config.xml
|
||||
|
||||
# PageHelper分页插件
|
||||
pagehelper:
|
||||
pagehelper:
|
||||
helperDialect: mysql
|
||||
supportMethodsArguments: true
|
||||
params: count=countSql
|
||||
params: count=countSql
|
||||
|
||||
# Shiro
|
||||
shiro:
|
||||
@@ -99,11 +99,11 @@ shiro:
|
||||
indexUrl: /index
|
||||
# 验证码开关
|
||||
captchaEnabled: true
|
||||
# 验证码类型 math 数组计算 char 字符
|
||||
# 验证码类型 math 数字计算 char 字符验证
|
||||
captchaType: math
|
||||
cookie:
|
||||
# 设置Cookie的域名 默认空,即当前访问的域名
|
||||
domain:
|
||||
domain:
|
||||
# 设置cookie的有效访问路径
|
||||
path: /
|
||||
# 设置HttpOnly属性
|
||||
@@ -111,7 +111,7 @@ shiro:
|
||||
# 设置Cookie的过期时间,天为单位
|
||||
maxAge: 30
|
||||
# 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效)
|
||||
cipherKey:
|
||||
cipherKey:
|
||||
session:
|
||||
# Session超时时间,-1代表永不过期(默认30分钟)
|
||||
expireTime: 30
|
||||
@@ -128,7 +128,7 @@ shiro:
|
||||
enabled: true
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
xss:
|
||||
# 过滤开关
|
||||
enabled: true
|
||||
# 排除链接(多个用逗号分隔)
|
||||
|
||||
+13
-2
@@ -1,7 +1,7 @@
|
||||
/*! X-editable - v1.5.1
|
||||
/*! X-editable - v1.5.3
|
||||
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
||||
* http://github.com/vitalets/x-editable
|
||||
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
||||
* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */
|
||||
.editableform {
|
||||
margin-bottom: 0; /* overwrites bootstrap margin */
|
||||
}
|
||||
@@ -12,6 +12,16 @@
|
||||
line-height: 20px; /* overwriting bootstrap line-height. See #133 */
|
||||
}
|
||||
|
||||
/*
|
||||
BS3 fix: stop css from breaking when the form is inside a popup and inside a form with the class .form-horizontal
|
||||
See: https://github.com/vitalets/x-editable/issues/682
|
||||
*/
|
||||
.form-horizontal .editable-popup .editableform .form-group {
|
||||
margin-left:0;
|
||||
margin-right:0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
BS3 width:1005 for inputs breaks editable form in popup
|
||||
See: https://github.com/vitalets/x-editable/issues/393
|
||||
@@ -145,6 +155,7 @@
|
||||
.editable-pre-wrapped {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.editable-container.editable-popup {
|
||||
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
||||
}
|
||||
|
||||
+5
-5
File diff suppressed because one or more lines are too long
+7
-5
@@ -26,7 +26,7 @@ $.extend($.fn.bootstrapTable.columnDefaults, {
|
||||
alwaysUseFormatter: false
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
$.extend($.fn.bootstrapTable.events, {
|
||||
'editable-init.bs.table': 'onEditableInit',
|
||||
'editable-save.bs.table': 'onEditableSave',
|
||||
'editable-shown.bs.table': 'onEditableShown',
|
||||
@@ -63,7 +63,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
column.formatter = column.formatter || (value => value)
|
||||
column._formatter = column._formatter ? column._formatter : column.formatter
|
||||
column.formatter = (value, row, index) => {
|
||||
column.formatter = (value, row, index, field) => {
|
||||
let result = Utils.calculateObjectValue(column, column._formatter, [value, row, index], value)
|
||||
|
||||
result = typeof result === 'undefined' || result === null ? this.options.undefinedText : result
|
||||
@@ -86,7 +86,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
column.editable, [index, row], {})
|
||||
|
||||
if (editableOpts.hasOwnProperty('noEditFormatter')) {
|
||||
noEditFormatter = editableOpts.noEditFormatter(value, row, index)
|
||||
noEditFormatter = editableOpts.noEditFormatter(value, row, index, field)
|
||||
}
|
||||
|
||||
if (noEditFormatter === false) {
|
||||
@@ -177,11 +177,13 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
if (params && params.escape) {
|
||||
for (const row of data) {
|
||||
for (const [key, value] of Object.entries(row)) {
|
||||
row[key] = Utils.unescapeHTML(value)
|
||||
if (typeof(value) !== "number") {
|
||||
row[key] = Utils.unescapeHTML(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -217,6 +217,8 @@
|
||||
if (!data || data.length <= 0) {
|
||||
var _empty = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">没有找到匹配的记录</div></td></tr>'
|
||||
$tbody.html(_empty);
|
||||
options.pageNumber = 1;
|
||||
initPagination(0, 0);
|
||||
return;
|
||||
}
|
||||
// 缓存并格式化数据
|
||||
@@ -272,6 +274,9 @@
|
||||
if (pageTo > target.totalRows) {
|
||||
pageTo = target.totalRows;
|
||||
}
|
||||
if (pageFrom > pageTo) {
|
||||
pageFrom = pageTo;
|
||||
}
|
||||
html.push('<div class="pull-left pagination-detail">');
|
||||
html.push('<span class="pagination-info">' + formatShowingRows(pageFrom, pageTo, target.totalRows) + '</span>');
|
||||
var pageList = false;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -694,9 +694,7 @@ var table = {
|
||||
var tableId = $.common.isEmpty(tableId) ? table.options.id : tableId;
|
||||
if (table.options.type == table_type.bootstrapTable) {
|
||||
var params = $("#" + tableId).bootstrapTable('getOptions');
|
||||
if ($.common.isNotEmpty(pageNumber)) {
|
||||
params.pageNumber = pageNumber;
|
||||
}
|
||||
params.pageNumber = 1;
|
||||
if ($.common.isNotEmpty(pageSize)) {
|
||||
params.pageSize = pageSize;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">参数键值:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="configValue" name="configValue" class="form-control" type="text" required>
|
||||
<textarea id="configValue" name="configValue" class="form-control" rows="4" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -87,26 +87,30 @@
|
||||
field: 'configName',
|
||||
title: '参数名称',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value);
|
||||
return $.table.tooltip(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'configKey',
|
||||
title: '参数键名',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value);
|
||||
return $.table.tooltip(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'configValue',
|
||||
title: '参数键值'
|
||||
title: '参数键值',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value, 10, "open");
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'configType',
|
||||
title: '系统内置',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -114,7 +118,7 @@
|
||||
title: '备注',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value, 10, "open");
|
||||
return $.table.tooltip(value, 10, "open");
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">参数键值:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="configValue" name="configValue" th:field="*{configValue}" class="form-control" type="text" required>
|
||||
<textarea id="configValue" name="configValue" class="form-control" rows="4" required>[[*{configValue}]]</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -59,12 +59,12 @@ public @interface Excel
|
||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||
|
||||
/**
|
||||
* 导出时在excel中每个列的高度 单位为字符
|
||||
* 导出时在excel中每个列的高度
|
||||
*/
|
||||
public double height() default 14;
|
||||
|
||||
/**
|
||||
* 导出时在excel中每个列的宽 单位为字符
|
||||
* 导出时在excel中每个列的宽度
|
||||
*/
|
||||
public double width() default 16;
|
||||
|
||||
@@ -114,7 +114,7 @@ public @interface Excel
|
||||
public ColumnType cellType() default ColumnType.STRING;
|
||||
|
||||
/**
|
||||
* 导出列头背景色
|
||||
* 导出列头背景颜色
|
||||
*/
|
||||
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
|
||||
|
||||
@@ -124,7 +124,7 @@ public @interface Excel
|
||||
public IndexedColors headerColor() default IndexedColors.WHITE;
|
||||
|
||||
/**
|
||||
* 导出单元格背景色
|
||||
* 导出单元格背景颜色
|
||||
*/
|
||||
public IndexedColors backgroundColor() default IndexedColors.WHITE;
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ public class DynamicDataSourceContextHolder
|
||||
|
||||
/**
|
||||
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
*/
|
||||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||
|
||||
|
||||
@@ -188,7 +188,17 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return !isError();
|
||||
return Objects.equals(Type.SUCCESS.value, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为警告消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isWarn()
|
||||
{
|
||||
return Objects.equals(Type.WARN.value, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -147,7 +147,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
||||
/**
|
||||
* 计算时间差
|
||||
*
|
||||
* @param endTime 最后时间
|
||||
* @param endDate 最后时间
|
||||
* @param startTime 开始时间
|
||||
* @return 时间差(天/小时/分钟)
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,11 @@ public class SqlUtil
|
||||
*/
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
||||
|
||||
/**
|
||||
* 限制orderBy最大长度
|
||||
*/
|
||||
private static final int ORDER_BY_MAX_LENGTH = 500;
|
||||
|
||||
/**
|
||||
* 检查字符,防止注入绕过
|
||||
*/
|
||||
@@ -29,6 +34,10 @@ public class SqlUtil
|
||||
{
|
||||
throw new UtilException("参数不符合规范,不能进行查询");
|
||||
}
|
||||
if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
|
||||
{
|
||||
throw new UtilException("参数已超过最大限制,不能进行查询");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public class SysLoginService
|
||||
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked")));
|
||||
throw new UserBlockedException();
|
||||
}
|
||||
|
||||
|
||||
+25
@@ -6,8 +6,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MissingPathVariableException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.DemoModeException;
|
||||
@@ -94,6 +96,29 @@ public class GlobalExceptionHandler
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求路径中缺少必需的路径变量
|
||||
*/
|
||||
@ExceptionHandler(MissingPathVariableException.class)
|
||||
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
|
||||
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求参数类型不匹配
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e,
|
||||
HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
|
||||
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义验证异常
|
||||
*/
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ public class PermissionService
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个权限,无权限返回hidden用于隐藏(如需返回Boolean使用hasAnyPermissions)
|
||||
*
|
||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||
* @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
|
||||
* @return 用户是否具有以下任意一个权限
|
||||
*/
|
||||
public String hasAnyPermi(String permissions)
|
||||
@@ -129,7 +129,7 @@ public class PermissionService
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个权限。
|
||||
*
|
||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||
* @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
|
||||
* @return 用户是否具有以下任意一个权限
|
||||
*/
|
||||
public boolean hasAnyPermissions(String permissions)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
# 代码生成
|
||||
gen:
|
||||
gen:
|
||||
# 作者
|
||||
author: ruoyi
|
||||
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
|
||||
|
||||
@@ -716,7 +716,7 @@
|
||||
<div class="tab-pane" id="tabDay">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="rdoDay" id="day_all"> 每小时 允许的通配符[, - * /]
|
||||
<input type="radio" name="rdoDay" id="day_all"> 每日 允许的通配符[, - * /]
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
@@ -1169,4 +1169,4 @@ $('#checkCron').click(function() {
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -695,7 +695,7 @@ create table gen_table (
|
||||
drop table if exists gen_table_column;
|
||||
create table gen_table_column (
|
||||
column_id bigint(20) not null auto_increment comment '编号',
|
||||
table_id varchar(64) comment '归属表编号',
|
||||
table_id bigint(20) comment '归属表编号',
|
||||
column_name varchar(200) comment '列名称',
|
||||
column_comment varchar(500) comment '列描述',
|
||||
column_type varchar(100) comment '列类型',
|
||||
Reference in New Issue
Block a user