Merge remote-tracking branch 'origin/master'
commit
d1c5ec58df
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
若依参考后台模板。有需要可自行到群内下载。
|
若依参考后台模板。有需要可自行到群内下载。
|
||||||
|
|
||||||
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需其他版本,请移步 [项目扩展](http://doc.ruoyi.vip/#/standard/xmkz) `(不定时更新)`
|
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需其他版本,请移步 [项目扩展](http://doc.ruoyi.vip/ruoyi/document/xmkz.html) `(不定时更新)`
|
||||||
|
|
||||||
> 阿里云通用云产品1888优惠券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof) 腾讯云通用云产品2860优惠券 :[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) `(仅限新用户)`
|
> 阿里云通用云产品1888优惠券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof) 腾讯云通用云产品2860优惠券 :[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) `(仅限新用户)`
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
10. 登录日志:系统登录日志记录查询包含登录异常。
|
10. 登录日志:系统登录日志记录查询包含登录异常。
|
||||||
11. 在线用户:当前系统中活跃用户状态监控。
|
11. 在线用户:当前系统中活跃用户状态监控。
|
||||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
||||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
||||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||||
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||||
|
|
8
pom.xml
8
pom.xml
|
@ -29,7 +29,6 @@
|
||||||
<oshi.version>3.9.1</oshi.version>
|
<oshi.version>3.9.1</oshi.version>
|
||||||
<commons.io.version>2.5</commons.io.version>
|
<commons.io.version>2.5</commons.io.version>
|
||||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||||
<jsoup.version>1.11.3</jsoup.version>
|
|
||||||
<poi.version>3.17</poi.version>
|
<poi.version>3.17</poi.version>
|
||||||
<velocity.version>1.7</velocity.version>
|
<velocity.version>1.7</velocity.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -148,13 +147,6 @@
|
||||||
<version>${commons.fileupload.version}</version>
|
<version>${commons.fileupload.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- HTML解析器 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jsoup</groupId>
|
|
||||||
<artifactId>jsoup</artifactId>
|
|
||||||
<version>${jsoup.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
|
|
|
@ -121,6 +121,7 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(@Validated SysRole role)
|
public AjaxResult editSave(@Validated SysRole role)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleAllowed(role);
|
||||||
if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
||||||
{
|
{
|
||||||
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||||
|
@ -153,6 +154,7 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult authDataScopeSave(SysRole role)
|
public AjaxResult authDataScopeSave(SysRole role)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleAllowed(role);
|
||||||
role.setUpdateBy(ShiroUtils.getLoginName());
|
role.setUpdateBy(ShiroUtils.getLoginName());
|
||||||
if (roleService.authDataScope(role) > 0)
|
if (roleService.authDataScope(role) > 0)
|
||||||
{
|
{
|
||||||
|
@ -216,6 +218,7 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult changeStatus(SysRole role)
|
public AjaxResult changeStatus(SysRole role)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleAllowed(role);
|
||||||
return toAjax(roleService.changeStatus(role));
|
return toAjax(roleService.changeStatus(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
import com.ruoyi.framework.util.ShiroUtils;
|
||||||
|
@ -159,11 +158,8 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(@Validated SysUser user)
|
public AjaxResult editSave(@Validated SysUser user)
|
||||||
{
|
{
|
||||||
if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId()))
|
userService.checkUserAllowed(user);
|
||||||
{
|
if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||||
return error("不允许修改超级管理员用户");
|
|
||||||
}
|
|
||||||
else if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
||||||
}
|
}
|
||||||
|
@ -190,6 +186,7 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult resetPwdSave(SysUser user)
|
public AjaxResult resetPwdSave(SysUser user)
|
||||||
{
|
{
|
||||||
|
userService.checkUserAllowed(user);
|
||||||
user.setSalt(ShiroUtils.randomSalt());
|
user.setSalt(ShiroUtils.randomSalt());
|
||||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||||
if (userService.resetUserPwd(user) > 0)
|
if (userService.resetUserPwd(user) > 0)
|
||||||
|
@ -258,6 +255,7 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult changeStatus(SysUser user)
|
public AjaxResult changeStatus(SysUser user)
|
||||||
{
|
{
|
||||||
|
userService.checkUserAllowed(user);
|
||||||
return toAjax(userService.changeStatus(user));
|
return toAjax(userService.changeStatus(user));
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
|
@ -139,6 +139,16 @@
|
||||||
},
|
},
|
||||||
// 初始化事件
|
// 初始化事件
|
||||||
initEvent: function(data) {
|
initEvent: function(data) {
|
||||||
|
// 绑定选中事件、取消事件、全部选中、全部取消
|
||||||
|
$.btTable.on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rows) {
|
||||||
|
// 复选框分页保留保存选中数组
|
||||||
|
var rowIds = $.table.affectedRowIds(rows);
|
||||||
|
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
||||||
|
func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
|
||||||
|
selectionIds = _[func](selectionIds, rowIds);
|
||||||
|
selectionRows = _[func](selectionRows, rows);
|
||||||
|
}
|
||||||
|
});
|
||||||
// 触发行点击事件 加载成功事件
|
// 触发行点击事件 加载成功事件
|
||||||
$.btTable.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table load-success.bs.table", function () {
|
$.btTable.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table load-success.bs.table", function () {
|
||||||
// 工具栏按钮控制
|
// 工具栏按钮控制
|
||||||
|
@ -148,15 +158,6 @@
|
||||||
// 非单个禁用
|
// 非单个禁用
|
||||||
$('#' + $.table._option.toolbar + ' .single').toggleClass('disabled', rows.length!=1);
|
$('#' + $.table._option.toolbar + ' .single').toggleClass('disabled', rows.length!=1);
|
||||||
});
|
});
|
||||||
// 绑定选中事件、取消事件、全部选中、全部取消
|
|
||||||
$.btTable.on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rows) {
|
|
||||||
// 复选框分页保留保存选中数组
|
|
||||||
var rowIds = $.table.affectedRowIds(rows);
|
|
||||||
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
|
||||||
func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
|
|
||||||
selectionIds = _[func](selectionIds, rowIds);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 图片预览事件
|
// 图片预览事件
|
||||||
$.btTable.on('click', '.img-circle', function() {
|
$.btTable.on('click', '.img-circle', function() {
|
||||||
var src = $(this).attr('src');
|
var src = $(this).attr('src');
|
||||||
|
@ -365,7 +366,9 @@
|
||||||
return row[column];
|
return row[column];
|
||||||
});
|
});
|
||||||
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
||||||
rows = rows.concat(selectionIds);
|
rows = $.map(selectionRows, function (row) {
|
||||||
|
return row[column];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return $.common.uniqueFn(rows);
|
return $.common.uniqueFn(rows);
|
||||||
},
|
},
|
||||||
|
@ -388,7 +391,9 @@
|
||||||
return row[$.table._option.columns[1].field];
|
return row[$.table._option.columns[1].field];
|
||||||
});
|
});
|
||||||
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
if ($.common.isNotEmpty($.table._option.rememberSelected) && $.table._option.rememberSelected) {
|
||||||
rows = rows.concat(selectionIds);
|
rows = $.map(selectionRows, function (row) {
|
||||||
|
return row[$.table._option.columns[1].field];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return $.common.uniqueFn(rows);
|
return $.common.uniqueFn(rows);
|
||||||
},
|
},
|
||||||
|
@ -1348,7 +1353,11 @@
|
||||||
formToJSON: function(formId) {
|
formToJSON: function(formId) {
|
||||||
var json = {};
|
var json = {};
|
||||||
$.each($("#" + formId).serializeArray(), function(i, field) {
|
$.each($("#" + formId).serializeArray(), function(i, field) {
|
||||||
json[field.name] = field.value;
|
if(json[field.name]) {
|
||||||
|
json[field.name] += ("," + field.value);
|
||||||
|
} else {
|
||||||
|
json[field.name] = field.value;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-suggest" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-suggest</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-suggest" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-suggest</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-typeahead" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-typeahead</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-typeahead" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-typeahead</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-datetimepicker" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-datetimepicker</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-datetimepicker" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-datetimepicker</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=laydate" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=laydate</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#laydate" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#laydate</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
<option value="12">若依12</option>
|
<option value="12">若依12</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
|
<hr>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-duallistbox" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-duallistbox</a></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jasny-bootstrap</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=select2" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=select2</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#select2" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#select2</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-select" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=bootstrap-select</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-select" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-select</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="font-noraml">相关参数详细信息</label>
|
<label class="font-noraml">相关参数详细信息</label>
|
||||||
<div><a href="http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=jasny-bootstrap</a></div>
|
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-fileinput" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#bootstrap-fileinput</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<p class="m-t">更多示例请访问官方示例页面:<a href="http://jqueryvalidation.org/files/demo/" target="_blank">查看</a>
|
<p class="m-t">更多示例请访问官方示例页面:<a href="http://jqueryvalidation.org/files/demo/" target="_blank">查看</a>
|
||||||
</p>
|
</p>
|
||||||
<p>中文API可参考:<a href="http://doc.ruoyi.vip/#/standard/zjwd?id=jquery-validate" target="_blank">http://doc.ruoyi.vip/#/standard/zjwd?id=jquery-validate</a>
|
<p>中文API可参考:<a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-validate" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#jquery-validate</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
|
|
||||||
// 选中数据
|
// 选中数据
|
||||||
function checkItem(){
|
function checkItem(){
|
||||||
var arrays = $.table.selectColumns("userId");
|
// var arrays = $.table.selectColumns("userId");
|
||||||
|
var arrays = $.table.selectColumns("userCode");
|
||||||
alert(arrays);
|
alert(arrays);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -173,7 +173,7 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav navbar-top-links navbar-right welcome-message">
|
<ul class="nav navbar-top-links navbar-right welcome-message">
|
||||||
<li><a title="视频教程" href="http://doc.ruoyi.vip/#/standard/spjc" target="_blank"><i class="fa fa-video-camera"></i> 视频教程</a></li>
|
<li><a title="视频教程" href="http://doc.ruoyi.vip/ruoyi/document/spjc.html" target="_blank"><i class="fa fa-video-camera"></i> 视频教程</a></li>
|
||||||
<li><a title="开发文档" href="http://doc.ruoyi.vip" target="_blank"><i class="fa fa-question-circle"></i> 开发文档</a></li>
|
<li><a title="开发文档" href="http://doc.ruoyi.vip" target="_blank"><i class="fa fa-question-circle"></i> 开发文档</a></li>
|
||||||
<li><a title="全屏显示" href="javascript:void(0)" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏显示</a></li>
|
<li><a title="全屏显示" href="javascript:void(0)" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏显示</a></li>
|
||||||
<li class="dropdown user-menu">
|
<li class="dropdown user-menu">
|
||||||
|
|
|
@ -77,12 +77,6 @@
|
||||||
<artifactId>commons-fileupload</artifactId>
|
<artifactId>commons-fileupload</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- HTML解析器 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jsoup</groupId>
|
|
||||||
<artifactId>jsoup</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
package com.ruoyi.common.utils.html;
|
||||||
|
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转义和反转义工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class EscapeUtil
|
||||||
|
{
|
||||||
|
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
|
||||||
|
|
||||||
|
private static final char[][] TEXT = new char[64][];
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
TEXT[i] = new char[] { (char) i };
|
||||||
|
}
|
||||||
|
|
||||||
|
// special HTML characters
|
||||||
|
TEXT['\''] = "'".toCharArray(); // 单引号
|
||||||
|
TEXT['"'] = """.toCharArray(); // 单引号
|
||||||
|
TEXT['&'] = "&".toCharArray(); // &符
|
||||||
|
TEXT['<'] = "<".toCharArray(); // 小于号
|
||||||
|
TEXT['>'] = ">".toCharArray(); // 大于号
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转义文本中的HTML字符为安全的字符
|
||||||
|
*
|
||||||
|
* @param text 被转义的文本
|
||||||
|
* @return 转义后的文本
|
||||||
|
*/
|
||||||
|
public static String escape(String text)
|
||||||
|
{
|
||||||
|
return encode(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还原被转义的HTML特殊字符
|
||||||
|
*
|
||||||
|
* @param content 包含转义符的HTML内容
|
||||||
|
* @return 转换后的字符串
|
||||||
|
*/
|
||||||
|
public static String unescape(String content)
|
||||||
|
{
|
||||||
|
return decode(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有HTML标签,但是不删除标签内的内容
|
||||||
|
*
|
||||||
|
* @param content 文本
|
||||||
|
* @return 清除标签后的文本
|
||||||
|
*/
|
||||||
|
public static String clean(String content)
|
||||||
|
{
|
||||||
|
return content.replaceAll(RE_HTML_MARK, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape编码
|
||||||
|
*
|
||||||
|
* @param text 被编码的文本
|
||||||
|
* @return 编码后的字符
|
||||||
|
*/
|
||||||
|
private static String encode(String text)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
if ((text == null) || ((len = text.length()) == 0))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
StringBuilder buffer = new StringBuilder(len + (len >> 2));
|
||||||
|
char c;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
c = text.charAt(i);
|
||||||
|
if (c < 64)
|
||||||
|
{
|
||||||
|
buffer.append(TEXT[c]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape解码
|
||||||
|
*
|
||||||
|
* @param content 被转义的内容
|
||||||
|
* @return 解码后的字符串
|
||||||
|
*/
|
||||||
|
public static String decode(String content)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(content))
|
||||||
|
{
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder tmp = new StringBuilder(content.length());
|
||||||
|
int lastPos = 0, pos = 0;
|
||||||
|
char ch;
|
||||||
|
while (lastPos < content.length())
|
||||||
|
{
|
||||||
|
pos = content.indexOf("%", lastPos);
|
||||||
|
if (pos == lastPos)
|
||||||
|
{
|
||||||
|
if (content.charAt(pos + 1) == 'u')
|
||||||
|
{
|
||||||
|
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
|
||||||
|
tmp.append(ch);
|
||||||
|
lastPos = pos + 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
|
||||||
|
tmp.append(ch);
|
||||||
|
lastPos = pos + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pos == -1)
|
||||||
|
{
|
||||||
|
tmp.append(content.substring(lastPos));
|
||||||
|
lastPos = content.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp.append(content.substring(lastPos, pos));
|
||||||
|
lastPos = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
String html = "<script>alert(1);</script>";
|
||||||
|
System.out.println(EscapeUtil.clean(html));
|
||||||
|
System.out.println(EscapeUtil.escape(html));
|
||||||
|
System.out.println(EscapeUtil.unescape(html));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,7 @@ package com.ruoyi.common.xss;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
import org.jsoup.Jsoup;
|
import com.ruoyi.common.utils.html.EscapeUtil;
|
||||||
import org.jsoup.safety.Whitelist;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSS过滤处理
|
* XSS过滤处理
|
||||||
|
@ -31,7 +30,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
// 防xss攻击和过滤前后空格
|
// 防xss攻击和过滤前后空格
|
||||||
escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
|
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
|
||||||
}
|
}
|
||||||
return escapseValues;
|
return escapseValues;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,36 +38,43 @@ public class MyBatisConfig
|
||||||
{
|
{
|
||||||
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
|
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
|
||||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
|
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
|
||||||
typeAliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/" + DEFAULT_RESOURCE_PATTERN;
|
List<String> allResult = new ArrayList<String>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<String> result = new ArrayList<String>();
|
for (String aliasesPackage : typeAliasesPackage.split(","))
|
||||||
Resource[] resources = resolver.getResources(typeAliasesPackage);
|
|
||||||
if (resources != null && resources.length > 0)
|
|
||||||
{
|
{
|
||||||
MetadataReader metadataReader = null;
|
List<String> result = new ArrayList<String>();
|
||||||
for (Resource resource : resources)
|
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
|
||||||
|
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
|
||||||
|
Resource[] resources = resolver.getResources(aliasesPackage);
|
||||||
|
if (resources != null && resources.length > 0)
|
||||||
{
|
{
|
||||||
if (resource.isReadable())
|
MetadataReader metadataReader = null;
|
||||||
|
for (Resource resource : resources)
|
||||||
{
|
{
|
||||||
metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
if (resource.isReadable())
|
||||||
try
|
|
||||||
{
|
{
|
||||||
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
|
metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||||
}
|
try
|
||||||
catch (ClassNotFoundException e)
|
{
|
||||||
{
|
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
|
||||||
e.printStackTrace();
|
}
|
||||||
|
catch (ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.size() > 0)
|
||||||
|
{
|
||||||
|
HashSet<String> hashResult = new HashSet<String>(result);
|
||||||
|
allResult.addAll(hashResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result.size() > 0)
|
if (allResult.size() > 0)
|
||||||
{
|
{
|
||||||
HashSet<String> h = new HashSet<String>(result);
|
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
|
||||||
result.clear();
|
|
||||||
result.addAll(h);
|
|
||||||
typeAliasesPackage = String.join(",", (String[]) result.toArray(new String[0]));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,6 @@ import org.apache.shiro.subject.PrincipalCollection;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.RoleBlockedException;
|
import com.ruoyi.common.exception.user.RoleBlockedException;
|
||||||
import com.ruoyi.common.exception.user.UserBlockedException;
|
import com.ruoyi.common.exception.user.UserBlockedException;
|
||||||
|
|
|
@ -52,6 +52,16 @@ public class SysRole extends BaseEntity
|
||||||
/** 部门组(数据权限) */
|
/** 部门组(数据权限) */
|
||||||
private Long[] deptIds;
|
private Long[] deptIds;
|
||||||
|
|
||||||
|
public SysRole()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public SysRole(Long roleId)
|
||||||
|
{
|
||||||
|
this.roleId = roleId;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getRoleId()
|
public Long getRoleId()
|
||||||
{
|
{
|
||||||
return roleId;
|
return roleId;
|
||||||
|
@ -62,6 +72,16 @@ public class SysRole extends BaseEntity
|
||||||
this.roleId = roleId;
|
this.roleId = roleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAdmin()
|
||||||
|
{
|
||||||
|
return isAdmin(this.roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAdmin(Long roleId)
|
||||||
|
{
|
||||||
|
return roleId != null && 1L == roleId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDataScope()
|
public String getDataScope()
|
||||||
{
|
{
|
||||||
return dataScope;
|
return dataScope;
|
||||||
|
|
|
@ -93,6 +93,16 @@ public class SysUser extends BaseEntity
|
||||||
/** 岗位组 */
|
/** 岗位组 */
|
||||||
private Long[] postIds;
|
private Long[] postIds;
|
||||||
|
|
||||||
|
public SysUser()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public SysUser(Long userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getUserId()
|
public Long getUserId()
|
||||||
{
|
{
|
||||||
return userId;
|
return userId;
|
||||||
|
|
|
@ -108,6 +108,13 @@ public interface ISysRoleService
|
||||||
*/
|
*/
|
||||||
public String checkRoleKeyUnique(SysRole role);
|
public String checkRoleKeyUnique(SysRole role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验角色是否允许操作
|
||||||
|
*
|
||||||
|
* @param role 角色信息
|
||||||
|
*/
|
||||||
|
public void checkRoleAllowed(SysRole role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过角色ID查询角色使用数量
|
* 通过角色ID查询角色使用数量
|
||||||
*
|
*
|
||||||
|
@ -123,6 +130,7 @@ public interface ISysRoleService
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int changeStatus(SysRole role);
|
public int changeStatus(SysRole role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消授权用户角色
|
* 取消授权用户角色
|
||||||
*
|
*
|
||||||
|
|
|
@ -139,6 +139,13 @@ public interface ISysUserService
|
||||||
*/
|
*/
|
||||||
public String checkEmailUnique(SysUser user);
|
public String checkEmailUnique(SysUser user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验用户是否允许操作
|
||||||
|
*
|
||||||
|
* @param user 用户信息
|
||||||
|
*/
|
||||||
|
public void checkUserAllowed(SysUser user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户ID查询用户所属角色组
|
* 根据用户ID查询用户所属角色组
|
||||||
*
|
*
|
||||||
|
|
|
@ -150,6 +150,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||||
Long[] roleIds = Convert.toLongArray(ids);
|
Long[] roleIds = Convert.toLongArray(ids);
|
||||||
for (Long roleId : roleIds)
|
for (Long roleId : roleIds)
|
||||||
{
|
{
|
||||||
|
checkRoleAllowed(new SysRole(roleId));
|
||||||
SysRole role = selectRoleById(roleId);
|
SysRole role = selectRoleById(roleId);
|
||||||
if (countUserRoleByRoleId(roleId) > 0)
|
if (countUserRoleByRoleId(roleId) > 0)
|
||||||
{
|
{
|
||||||
|
@ -293,6 +294,19 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||||
return UserConstants.ROLE_KEY_UNIQUE;
|
return UserConstants.ROLE_KEY_UNIQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验角色是否允许操作
|
||||||
|
*
|
||||||
|
* @param role 角色信息
|
||||||
|
*/
|
||||||
|
public void checkRoleAllowed(SysRole role)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
|
||||||
|
{
|
||||||
|
throw new BusinessException("不允许操作超级管理员角色");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过角色ID查询角色使用数量
|
* 通过角色ID查询角色使用数量
|
||||||
*
|
*
|
||||||
|
|
|
@ -167,10 +167,7 @@ public class SysUserServiceImpl implements ISysUserService
|
||||||
Long[] userIds = Convert.toLongArray(ids);
|
Long[] userIds = Convert.toLongArray(ids);
|
||||||
for (Long userId : userIds)
|
for (Long userId : userIds)
|
||||||
{
|
{
|
||||||
if (SysUser.isAdmin(userId))
|
checkUserAllowed(new SysUser(userId));
|
||||||
{
|
|
||||||
throw new BusinessException("不允许删除超级管理员用户");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return userMapper.deleteUserByIds(userIds);
|
return userMapper.deleteUserByIds(userIds);
|
||||||
}
|
}
|
||||||
|
@ -345,6 +342,19 @@ public class SysUserServiceImpl implements ISysUserService
|
||||||
return UserConstants.USER_EMAIL_UNIQUE;
|
return UserConstants.USER_EMAIL_UNIQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验用户是否允许操作
|
||||||
|
*
|
||||||
|
* @param user 用户信息
|
||||||
|
*/
|
||||||
|
public void checkUserAllowed(SysUser user)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
|
||||||
|
{
|
||||||
|
throw new BusinessException("不允许操作超级管理员用户");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户所属角色组
|
* 查询用户所属角色组
|
||||||
*
|
*
|
||||||
|
@ -465,10 +475,6 @@ public class SysUserServiceImpl implements ISysUserService
|
||||||
@Override
|
@Override
|
||||||
public int changeStatus(SysUser user)
|
public int changeStatus(SysUser user)
|
||||||
{
|
{
|
||||||
if (SysUser.isAdmin(user.getUserId()))
|
|
||||||
{
|
|
||||||
throw new BusinessException("不允许修改超级管理员用户");
|
|
||||||
}
|
|
||||||
return userMapper.updateUser(user);
|
return userMapper.updateUser(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue