100 Commits

Author SHA1 Message Date
db193a46e8 若依 3.7.0 2021-09-13 09:36:38 +08:00
04c340627d 修复多图组件验证失败被删除问题 2021-09-10 11:06:25 +08:00
15abd4d053 优化提示 2021-09-08 11:26:08 +08:00
a7376b36f8 修复代码生成页面数据编辑保存之后总是跳转第一页的问题
Merge pull request  from 稚屿/master
2021-09-08 03:19:59 +00:00
d2b61762b7 修复代码生成页面数据编辑保存之后总是跳转第一页的问题 2021-09-08 11:18:35 +08:00
a5e38f6f99 菜单管理支持配置路由参数 2021-09-08 09:28:23 +08:00
4988b585f8 修正单词拼写错误
Merge pull request  from 稚屿/master
2021-09-07 08:16:58 +00:00
b35f708c07 修正单词拼写错误 2021-09-05 21:36:33 +08:00
0e6150720c 页签新增关闭左侧 2021-09-05 13:27:58 +08:00
44adf03d2c 页签右键按钮添加图标 2021-09-05 13:26:45 +08:00
9ae5edaa74 菜单&部门新增展开/折叠功能 2021-09-04 12:10:33 +08:00
14c6c796e8 新增暗色菜单风格主题 2021-09-04 12:09:55 +08:00
5d72f9d224 修复保存配置主题颜色失效问题 2021-09-03 16:50:48 +08:00
e49f0cebf1 自定义弹层溢出滚动样式 2021-09-03 13:27:03 +08:00
6361e4efdc 定时任务支持在线生成cron表达式 2021-09-03 09:54:07 +08:00
cfa86bd4fe 代码生成: 导入表时查询 新创建表的优先排序在前面
Merge pull request  from xiaoshitou/N/A
2021-09-03 01:39:40 +00:00
a56bc47a81 代码生成: 导入表时查询 新创建表的优先排序在前面 2021-09-02 20:01:25 +00:00
a15bfdfb46 防止表格最后页最后项删除变成暂无数据 2021-09-02 10:55:10 +08:00
ee823b8326 防止表格最后页最后项删除变成暂无数据 2021-09-02 10:19:04 +08:00
57178e72a4 修改数据字典样式回显
Merge pull request  from 马小法/master
2021-09-01 01:20:59 +00:00
b8317a562c 修改非管理员登录时,获取菜单报错sql
Merge pull request  from Gold_Fish/master
2021-08-30 08:59:55 +00:00
8040ad8c03 修改数据字典回显 2021-08-30 16:53:16 +08:00
c628aa5be8 修改代码生成字典回显样式 2021-08-30 16:49:30 +08:00
b036e78d85 修改根据userId获取菜单sql 2021-08-30 02:42:49 +00:00
4e8c6fb7c0 修复字典组件值为整形不显示问题 2021-08-29 15:57:01 +08:00
134835c870 验证码默认20s超时 2021-08-29 15:56:46 +08:00
5ade90debf XssHttpServletRequestWrapper中增加available方法
Merge pull request  from Ming/master
2021-08-29 07:36:57 +00:00
bb0aeb39e3 修复带utc日期格式 yyyy-MM-dd'T'HH:mm:ss.SSS 在safari浏览器中无法正确格式化的问题
Merge pull request  from wjtc8/N/A
2021-08-29 07:35:06 +00:00
098c650655 update ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java.
增加available方法于XssHttpServletRequestWrapper
2021-08-24 08:42:56 +00:00
e52092c6d4 修改时检查用户数据权限范围 2021-08-24 16:00:39 +08:00
89911e7caf 修复带utc日期格式 yyyy-MM-dd'T'HH:mm:ss.SSS 在safari浏览器中无法正确格式化的问题 2021-08-24 05:51:00 +00:00
0fc266fe80 定时任务对检查异常进行事务回滚 2021-08-24 11:12:11 +08:00
d1ef19f08a 自定义可拖动弹窗高度指令 2021-08-20 17:57:44 +08:00
e6e10308ff 自定义可拖动弹窗宽度指令 2021-08-20 17:45:25 +08:00
cb5ee9c8a1 补充定时任务表字段注释 2021-08-20 11:04:15 +08:00
1e37f0430b 定时任务屏蔽ldap远程调用 2021-08-19 15:26:22 +08:00
295173258c update 优化 使用权限工具 获取用户信息
Merge pull request  from 疯狂的狮子Li/update
2021-08-19 06:55:13 +00:00
fec90d0487 update ruoyi-ui/src/layout/index.vue.
Merge pull request  from aasdd/N/A
2021-08-19 06:49:06 +00:00
aead560227 update 优化 使用权限工具 获取用户信息 2021-08-19 11:13:59 +08:00
8133c60ab3 update ruoyi-ui/src/layout/index.vue.
删掉此处代码,使右边栏动画生效。现在是没有动画的
2021-08-18 09:29:22 +00:00
5c155f5f11 支持自定义注解实现接口限流 2021-08-17 14:08:18 +08:00
03cf98d3c9 优化异常信息 2021-08-16 16:25:25 +08:00
6f51f729ba 添加日期范围支持重复添加多组日期范围,请求参数中对象的属性为null、undefined不进行拼接
Merge pull request  from wangzhaoqiang/master
2021-08-16 08:23:27 +00:00
57b159eb98 添加日期范围支持重复添加多组日期范围,请求参数中对象的属性为null、undefined不进行拼接 2021-08-16 14:48:34 +08:00
08da6834a5 修正方法名单词拼写错误
Merge pull request  from 稚屿/N/A
2021-08-16 02:36:36 +00:00
268468fb47 更新到【默认首页使用keep-alive缓存】后报错
Merge pull request  from wangzhaoqiang/master
2021-08-16 02:36:29 +00:00
333e19339c 修正方法名单词拼写错误 2021-08-15 10:26:05 +00:00
7b6ccd9b22 解决登录后浏览器后台Breadcrumb组件报错 2021-08-14 20:16:48 +08:00
5d6f134609 多图上传组件移除多余的api地址 2021-08-13 15:15:35 +08:00
f02743bde5 代码生成主子表多选行数据 2021-08-13 14:50:35 +08:00
3003bb0f50 Excel注解图片导入兼容xls 2021-08-13 10:56:35 +08:00
5139265d32 默认首页使用keep-alive缓存 2021-08-13 10:10:29 +08:00
8a67af6c26 修复角色分配用户页面接收参数与传递参数类型不一致导致的错误
Merge pull request  from 稚屿/N/A
2021-08-13 01:55:58 +00:00
8e4802505e 添加SysConfigservice,SysDictTypeService的实现方法遗漏的@Override注解
Merge pull request  from Old丶x/master
2021-08-13 01:55:52 +00:00
8ee641c1bc 修复角色分配用户页面接收参数与传递参数类型不一致导致的错误 2021-08-13 01:08:00 +00:00
779508989f 添加加载字典数据,清空字典数据,重置字典数据方法上遗漏的@Override注解 2021-08-12 17:30:31 +08:00
d9e805a6a5 添加获取验证码方法上遗漏的@Override注解 2021-08-12 17:19:56 +08:00
7be17ea89a Excel注解支持Image图片导入 2021-08-11 10:13:34 +08:00
1f07641d9b update bin 2021-08-11 10:11:13 +08:00
c0f4f805d0 补全注册用户方法上遗漏的@Override注解
Merge pull request  from 稚屿/N/A
2021-08-11 02:08:58 +00:00
b84224d7ba 补全注册用户方法上遗漏的@Override注解 2021-08-08 14:08:52 +00:00
98a143f1fe 添加新群号:101456076 2021-08-08 19:50:50 +08:00
3243428009 优化用户不能删除自己 2021-08-08 19:12:52 +08:00
7736097f6b 提取通用方法到基类控制器 2021-08-08 19:12:12 +08:00
fc60c003c3 升级element-ui到最新版本2.15.5 2021-08-06 14:31:39 +08:00
68ae4df2dc 升级commons.io到最新版本v2.11.0 2021-07-31 17:52:06 +08:00
de33e6ecc8 优化代码生成模板 2021-07-30 22:18:20 +08:00
a1cc346aca 优化代码生成模板 2021-07-30 21:50:47 +08:00
5397e345ca 新增是否开启用户注册功能 2021-07-30 21:23:35 +08:00
8ed7916b61 定时任务屏蔽http(s)远程调用 2021-07-30 11:28:46 +08:00
2de5cc52d1 启用父部门状态排除顶级节点 2021-07-30 11:28:04 +08:00
f6bc28000e 防止错误token导致的解析异常 2021-07-29 17:32:55 +08:00
6b5dd4d2be 优化XSS跨站脚本过滤 2021-07-28 16:04:59 +08:00
e6becb9337 BLOB下载时清除URL对象引用 2021-07-28 13:13:28 +08:00
8da55fb72a 添加新群号:101456076 2021-07-28 09:51:19 +08:00
6a5c86541a 跳转路由高亮相对应的菜单栏 2021-07-27 11:54:20 +08:00
3803ac78e2 升级oshi到最新版本v5.8.0 2021-07-27 11:53:59 +08:00
4095a1b6ee fix Issue #I42GRW 任意账户越权漏洞
Merge pull request  from lagXkjy/master
2021-07-27 02:08:04 +00:00
3347ca4d74 fix:Issue #I42GRW 修复任意账户越权漏洞 2021-07-27 09:33:12 +08:00
9b1883988b 升级element-ui到最新版本2.15.3 2021-07-26 09:50:58 +08:00
49c8a007cc 修复定时任务日志执行状态显示 2021-07-26 09:50:33 +08:00
64f6d28441 角色&菜单新增字段属性提示信息 2021-07-25 20:08:55 +08:00
c26d87c677 内链设置meta信息 2021-07-25 20:05:18 +08:00
97ae0eb7c7 密码框新增显示切换密码图标 2021-07-25 19:13:56 +08:00
6c1cccd031 导入用户样式调整 2021-07-25 19:08:00 +08:00
856d1ceba8 顶部菜单样式调整 2021-07-25 19:06:57 +08:00
60673b3b64 去除默认分页合理化参数 2021-07-25 10:35:37 +08:00
0a516e3001 更多操作按钮添加权限控制 2021-07-25 10:20:52 +08:00
bb87f35797 富文本新增上传文件大小限制 2021-07-25 08:57:01 +08:00
c43f9bc3c2 顶部菜单排除隐藏的默认路由 2021-07-24 18:20:55 +08:00
46b43b1bd9 code=401时request方法没有返回Promise.reject 修复
Merge pull request  from 严俊东/N/A
2021-07-24 02:48:01 +00:00
8dbda47174 修正方法名单词拼写错误
Merge pull request  from 稚屿/N/A
2021-07-23 11:34:30 +00:00
cdace51197 code=401时request方法没有返回Promise.reject 修复 2021-07-20 04:49:22 +00:00
c24fc4282c 修正方法名单词拼写错误 2021-07-20 00:54:50 +00:00
b616a2f2e7 定时任务新增更多操作 2021-07-15 17:35:33 +08:00
60abdf1dbc 升级oshi到最新版本v5.7.5 2021-07-14 09:53:26 +08:00
7b894da43c 参数管理支持配置验证码开关 2021-07-13 10:30:40 +08:00
c8b66f9b04 删除富文本video事件 2021-07-13 10:28:55 +08:00
25d9edd5c9 图片上传 - 多图时无法删除相应图片修复
Merge pull request  from 严俊东/N/A
2021-07-13 02:26:10 +00:00
77a21d098f 图片上传 - 多图时无法删除相应图片修复 2021-07-12 03:01:50 +00:00
151 changed files with 8797 additions and 5122 deletions
README.md
bin
pom.xml
ruoyi-admin
ruoyi-common
ruoyi-framework
ruoyi-generator
ruoyi-quartz
pom.xml
src
main
java
com
ruoyi
ruoyi-system
ruoyi-ui
sql

@ -82,4 +82,4 @@
## 若依前后端分离交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) 点击按钮入群。
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) 点击按钮入群。

@ -1,6 +1,6 @@
@echo off
echo.
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>target<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
echo.
%~d0

@ -1,6 +1,6 @@
@echo off
echo.
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD>Web<65><62><EFBFBD>̡<EFBFBD>
echo [<5B><>Ϣ] ʹ<EFBFBD><EFBFBD>Jar<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Web<EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>
echo.
cd %~dp0

@ -6,14 +6,14 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.6.0</version>
<version>3.7.0</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>3.6.0</ruoyi.version>
<ruoyi.version>3.7.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
@ -25,9 +25,9 @@
<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.7.4</oshi.version>
<oshi.version>5.8.0</oshi.version>
<jna.version>5.8.0</jna.version>
<commons.io.version>2.10.0</commons.io.version>
<commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version>
<commons.collections.version>3.2.2</commons.collections.version>
<poi.version>4.1.2</poi.version>

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

@ -17,6 +17,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
/**
* 验证码操作处理
@ -38,13 +39,23 @@ public class CaptchaController
// 验证码类型
@Value("${ruoyi.captchaType}")
private String captchaType;
@Autowired
private ISysConfigService configService;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaOnOff = configService.selectCaptchaOnOff();
ajax.put("captchaOnOff", captchaOnOff);
if (!captchaOnOff)
{
return ajax;
}
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
@ -78,7 +89,6 @@ public class CaptchaController
return AjaxResult.error(e.getMessage());
}
AjaxResult ajax = AjaxResult.success();
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;

@ -19,7 +19,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
@ -90,7 +89,7 @@ public class SysConfigController extends BaseController
{
return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setCreateBy(SecurityUtils.getUsername());
config.setCreateBy(getUsername());
return toAjax(configService.insertConfig(config));
}
@ -106,7 +105,7 @@ public class SysConfigController extends BaseController
{
return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setUpdateBy(SecurityUtils.getUsername());
config.setUpdateBy(getUsername());
return toAjax(configService.updateConfig(config));
}

@ -20,7 +20,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
@ -75,6 +74,7 @@ public class SysDeptController extends BaseController
@GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId)
{
deptService.checkDeptDataScope(deptId);
return AjaxResult.success(deptService.selectDeptById(deptId));
}
@ -113,7 +113,7 @@ public class SysDeptController extends BaseController
{
return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
dept.setCreateBy(SecurityUtils.getUsername());
dept.setCreateBy(getUsername());
return toAjax(deptService.insertDept(dept));
}
@ -138,7 +138,7 @@ public class SysDeptController extends BaseController
{
return AjaxResult.error("该部门包含未停用的子部门!");
}
dept.setUpdateBy(SecurityUtils.getUsername());
dept.setUpdateBy(getUsername());
return toAjax(deptService.updateDept(dept));
}

@ -19,7 +19,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
@ -91,7 +90,7 @@ public class SysDictDataController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictData dict)
{
dict.setCreateBy(SecurityUtils.getUsername());
dict.setCreateBy(getUsername());
return toAjax(dictDataService.insertDictData(dict));
}
@ -103,7 +102,7 @@ public class SysDictDataController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictData dict)
{
dict.setUpdateBy(SecurityUtils.getUsername());
dict.setUpdateBy(getUsername());
return toAjax(dictDataService.updateDictData(dict));
}

@ -19,7 +19,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService;
@ -76,7 +75,7 @@ public class SysDictTypeController extends BaseController
{
return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setCreateBy(SecurityUtils.getUsername());
dict.setCreateBy(getUsername());
return toAjax(dictTypeService.insertDictType(dict));
}
@ -92,7 +91,7 @@ public class SysDictTypeController extends BaseController
{
return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setUpdateBy(SecurityUtils.getUsername());
dict.setUpdateBy(getUsername());
return toAjax(dictTypeService.updateDictType(dict));
}

@ -12,11 +12,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
/**
@ -36,9 +34,6 @@ public class SysLoginController
@Autowired
private SysPermissionService permissionService;
@Autowired
private TokenService tokenService;
/**
* 登录方法
*
@ -64,8 +59,7 @@ public class SysLoginController
@GetMapping("getInfo")
public AjaxResult getInfo()
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
SysUser user = SecurityUtils.getLoginUser().getUser();
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合
@ -85,10 +79,8 @@ public class SysLoginController
@GetMapping("getRouters")
public AjaxResult getRouters()
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
// 用户信息
SysUser user = loginUser.getUser();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
Long userId = SecurityUtils.getUserId();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
return AjaxResult.success(menuService.buildMenus(menus));
}
}

@ -17,12 +17,8 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
/**
@ -37,9 +33,6 @@ public class SysMenuController extends BaseController
@Autowired
private ISysMenuService menuService;
@Autowired
private TokenService tokenService;
/**
* 获取菜单列表
*/
@ -47,9 +40,7 @@ public class SysMenuController extends BaseController
@GetMapping("/list")
public AjaxResult list(SysMenu menu)
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
Long userId = loginUser.getUser().getUserId();
List<SysMenu> menus = menuService.selectMenuList(menu, userId);
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menus);
}
@ -69,9 +60,7 @@ public class SysMenuController extends BaseController
@GetMapping("/treeselect")
public AjaxResult treeselect(SysMenu menu)
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
Long userId = loginUser.getUser().getUserId();
List<SysMenu> menus = menuService.selectMenuList(menu, userId);
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
}
@ -81,8 +70,7 @@ public class SysMenuController extends BaseController
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
List<SysMenu> menus = menuService.selectMenuList(loginUser.getUser().getUserId());
List<SysMenu> menus = menuService.selectMenuList(getUserId());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));
@ -105,7 +93,7 @@ public class SysMenuController extends BaseController
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
menu.setCreateBy(SecurityUtils.getUsername());
menu.setCreateBy(getUsername());
return toAjax(menuService.insertMenu(menu));
}
@ -129,7 +117,7 @@ public class SysMenuController extends BaseController
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
menu.setUpdateBy(SecurityUtils.getUsername());
menu.setUpdateBy(getUsername());
return toAjax(menuService.updateMenu(menu));
}

@ -17,7 +17,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
@ -63,7 +62,7 @@ public class SysNoticeController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysNotice notice)
{
notice.setCreateBy(SecurityUtils.getUsername());
notice.setCreateBy(getUsername());
return toAjax(noticeService.insertNotice(notice));
}
@ -75,7 +74,7 @@ public class SysNoticeController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysNotice notice)
{
notice.setUpdateBy(SecurityUtils.getUsername());
notice.setUpdateBy(getUsername());
return toAjax(noticeService.updateNotice(notice));
}

@ -18,7 +18,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService;
@ -83,7 +82,7 @@ public class SysPostController extends BaseController
{
return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setCreateBy(SecurityUtils.getUsername());
post.setCreateBy(getUsername());
return toAjax(postService.insertPost(post));
}
@ -103,7 +102,7 @@ public class SysPostController extends BaseController
{
return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setUpdateBy(SecurityUtils.getUsername());
post.setUpdateBy(getUsername());
return toAjax(postService.updatePost(post));
}

@ -19,7 +19,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.web.service.TokenService;
@ -46,7 +45,7 @@ public class SysProfileController extends BaseController
@GetMapping
public AjaxResult profile()
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser();
AjaxResult ajax = AjaxResult.success(user);
ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
@ -71,14 +70,17 @@ public class SysProfileController extends BaseController
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
LoginUser loginUser = getLoginUser();
SysUser sysUser = loginUser.getUser();
user.setUserId(sysUser.getUserId());
user.setPassword(null);
if (userService.updateUserProfile(user) > 0)
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
// 更新缓存用户信息
loginUser.getUser().setNickName(user.getNickName());
loginUser.getUser().setPhonenumber(user.getPhonenumber());
loginUser.getUser().setEmail(user.getEmail());
loginUser.getUser().setSex(user.getSex());
sysUser.setNickName(user.getNickName());
sysUser.setPhonenumber(user.getPhonenumber());
sysUser.setEmail(user.getEmail());
sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
}
@ -92,7 +94,7 @@ public class SysProfileController extends BaseController
@PutMapping("/updatePwd")
public AjaxResult updatePwd(String oldPassword, String newPassword)
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = getLoginUser();
String userName = loginUser.getUsername();
String password = loginUser.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password))
@ -122,7 +124,7 @@ public class SysProfileController extends BaseController
{
if (!file.isEmpty())
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file);
if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
{

@ -0,0 +1,38 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService;
/**
* 注册验证
*
* @author ruoyi
*/
@RestController
public class SysRegisterController extends BaseController
{
@Autowired
private SysRegisterService registerService;
@Autowired
private ISysConfigService configService;
@PostMapping("/register")
public AjaxResult register(@RequestBody RegisterBody user)
{
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
{
return error("当前系统没有开启注册功能!");
}
String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg);
}
}

@ -21,8 +21,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
@ -78,6 +76,7 @@ public class SysRoleController extends BaseController
@GetMapping(value = "/{roleId}")
public AjaxResult getInfo(@PathVariable Long roleId)
{
roleService.checkRoleDataScope(roleId);
return AjaxResult.success(roleService.selectRoleById(roleId));
}
@ -97,7 +96,7 @@ public class SysRoleController extends BaseController
{
return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setCreateBy(SecurityUtils.getUsername());
role.setCreateBy(getUsername());
return toAjax(roleService.insertRole(role));
}
@ -119,12 +118,12 @@ public class SysRoleController extends BaseController
{
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setUpdateBy(SecurityUtils.getUsername());
role.setUpdateBy(getUsername());
if (roleService.updateRole(role) > 0)
{
// 更新缓存用户权限
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
@ -157,7 +156,7 @@ public class SysRoleController extends BaseController
public AjaxResult changeStatus(@RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
role.setUpdateBy(SecurityUtils.getUsername());
role.setUpdateBy(getUsername());
return toAjax(roleService.updateRoleStatus(role));
}

@ -2,6 +2,7 @@ package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
@ -20,14 +21,11 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@ -50,9 +48,6 @@ public class SysUserController extends BaseController
@Autowired
private ISysPostService postService;
@Autowired
private TokenService tokenService;
/**
* 获取用户列表
*/
@ -82,8 +77,7 @@ public class SysUserController extends BaseController
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream());
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
String operName = loginUser.getUsername();
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return AjaxResult.success(message);
}
@ -102,6 +96,7 @@ public class SysUserController extends BaseController
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{
userService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success();
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
@ -137,7 +132,7 @@ public class SysUserController extends BaseController
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setCreateBy(SecurityUtils.getUsername());
user.setCreateBy(getUsername());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
return toAjax(userService.insertUser(user));
}
@ -161,7 +156,7 @@ public class SysUserController extends BaseController
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setUpdateBy(SecurityUtils.getUsername());
user.setUpdateBy(getUsername());
return toAjax(userService.updateUser(user));
}
@ -173,6 +168,10 @@ public class SysUserController extends BaseController
@DeleteMapping("/{userIds}")
public AjaxResult remove(@PathVariable Long[] userIds)
{
if (ArrayUtils.contains(userIds, getUserId()))
{
return error("当前用户不能删除");
}
return toAjax(userService.deleteUserByIds(userIds));
}
@ -186,7 +185,7 @@ public class SysUserController extends BaseController
{
userService.checkUserAllowed(user);
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
user.setUpdateBy(SecurityUtils.getUsername());
user.setUpdateBy(getUsername());
return toAjax(userService.resetPwd(user));
}
@ -199,7 +198,7 @@ public class SysUserController extends BaseController
public AjaxResult changeStatus(@RequestBody SysUser user)
{
userService.checkUserAllowed(user);
user.setUpdateBy(SecurityUtils.getUsername());
user.setUpdateBy(getUsername());
return toAjax(userService.updateUserStatus(user));
}

@ -3,7 +3,7 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.6.0
version: 3.7.0
# 版权年份
copyrightYear: 2021
# 实例演示开关
@ -100,7 +100,6 @@ mybatis:
# PageHelper分页插件
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
@ -116,6 +115,6 @@ xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice/*
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*

@ -19,6 +19,7 @@ user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录

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

@ -14,5 +14,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
Excel[] value();
public Excel[] value();
}

@ -0,0 +1,40 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.LimitType;
/**
* 限流注解
*
* @author ruoyi
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
/**
* 限流key
*/
public String key() default Constants.RATE_LIMIT_KEY;
/**
* 限流时间,单位秒
*/
public int time() default 60;
/**
* 限流次数
*/
public int count() default 100;
/**
* 限流类型
*/
public LimitType limitType() default LimitType.DEFAULT;
}

@ -90,6 +90,14 @@ public class RuoYiConfig
RuoYiConfig.addressEnabled = addressEnabled;
}
/**
* 获取导入上传路径
*/
public static String getImportPath()
{
return getProfile() + "/import";
}
/**
* 获取头像上传路径
*/

@ -1,5 +1,7 @@
package com.ruoyi.common.constant;
import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
@ -47,6 +49,11 @@ public class Constants
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
@ -61,12 +68,17 @@ public class Constants
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 验证码有效期(分钟)
*/
@ -95,7 +107,7 @@ public class Constants
/**
* 用户名称
*/
public static final String JWT_USERNAME = "sub";
public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
@ -131,4 +143,9 @@ public class Constants
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap://";
}

@ -53,7 +53,7 @@ public class UserConstants
/** Layout组件标识 */
public final static String LAYOUT = "Layout";
/** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView";
@ -63,4 +63,16 @@ public class UserConstants
/** 校验返回结果码 */
public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1";
/**
* 用户名长度限制
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20;
/**
* 密码长度限制
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
}

@ -11,10 +11,12 @@ import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
@ -55,7 +57,8 @@ public class BaseController
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.startPage(pageNum, pageSize, orderBy);
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
}
@ -86,28 +89,6 @@ public class BaseController
return rspData;
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 返回成功
*/
@ -140,6 +121,28 @@ public class BaseController
return AjaxResult.error(message);
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 页面跳转
*/
@ -147,4 +150,36 @@ public class BaseController
{
return StringUtils.format("redirect:{}", url);
}
/**
* 获取用户缓存信息
*/
public LoginUser getLoginUser()
{
return SecurityUtils.getLoginUser();
}
/**
* 获取登录用户id
*/
public Long getUserId()
{
return getLoginUser().getUserId();
}
/**
* 获取登录部门id
*/
public Long getDeptId()
{
return getLoginUser().getDeptId();
}
/**
* 获取登录用户名
*/
public String getUsername()
{
return getLoginUser().getUsername();
}
}

@ -38,6 +38,9 @@ public class SysMenu extends BaseEntity
/** 组件路径 */
private String component;
/** 路由参数 */
private String query;
/** 是否为外链0是 1否 */
private String isFrame;
@ -137,6 +140,16 @@ public class SysMenu extends BaseEntity
this.component = component;
}
public String getQuery()
{
return query;
}
public void setQuery(String query)
{
this.query = query;
}
public String getIsFrame()
{
return isFrame;

@ -201,7 +201,7 @@ public class SysUser extends BaseEntity
this.avatar = avatar;
}
@JsonIgnore
@JsonIgnore
@JsonProperty
public String getPassword()
{

@ -16,6 +16,16 @@ public class LoginUser implements UserDetails
{
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private Long deptId;
/**
* 用户唯一标识
*/
@ -61,6 +71,26 @@ public class LoginUser implements UserDetails
*/
private SysUser user;
public Long getUserId()
{
return userId;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public String getToken()
{
return token;
@ -81,6 +111,14 @@ public class LoginUser implements UserDetails
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
{
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.permissions = permissions;
}
@JsonIgnore
@Override
public String getPassword()

@ -0,0 +1,11 @@
package com.ruoyi.common.core.domain.model;
/**
* 用户注册对象
*
* @author ruoyi
*/
public class RegisterBody extends LoginBody
{
}

@ -21,6 +21,9 @@ public class PageDomain
/** 排序的方向desc或者asc */
private String isAsc = "asc";
/** 分页参数合理化 */
private Boolean reasonable = true;
public String getOrderBy()
{
if (StringUtils.isEmpty(orderByColumn))
@ -81,4 +84,18 @@ public class PageDomain
this.isAsc = isAsc;
}
}
public Boolean getReasonable()
{
if (StringUtils.isNull(reasonable))
{
return Boolean.TRUE;
}
return reasonable;
}
public void setReasonable(Boolean reasonable)
{
this.reasonable = reasonable;
}
}

@ -29,6 +29,11 @@ public class TableSupport
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
*/
@ -39,6 +44,7 @@ public class TableSupport
pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
return pageDomain;
}

@ -0,0 +1,20 @@
package com.ruoyi.common.enums;
/**
* 限流类型
*
* @author ruoyi
*/
public enum LimitType
{
/**
* 默认策略全局限流
*/
DEFAULT,
/**
* 根据请求者IP进行限流
*/
IP
}

@ -1,43 +0,0 @@
package com.ruoyi.common.exception;
/**
* 自定义异常
*
* @author ruoyi
*/
public class CustomException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
public CustomException(String message)
{
this.message = message;
}
public CustomException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public CustomException(String message, Throwable e)
{
super(message, e);
this.message = message;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
}

@ -0,0 +1,58 @@
package com.ruoyi.common.exception;
/**
* 全局异常
*
* @author ruoyi
*/
public class GlobalException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException()
{
}
public GlobalException(String message)
{
this.message = message;
}
public String getDetailMessage()
{
return detailMessage;
}
public GlobalException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
public String getMessage()
{
return message;
}
public GlobalException setMessage(String message)
{
this.message = message;
return this;
}
}

@ -0,0 +1,73 @@
package com.ruoyi.common.exception;
/**
* 业务异常
*
* @author ruoyi
*/
public final class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException()
{
}
public ServiceException(String message)
{
this.message = message;
}
public ServiceException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public String getDetailMessage()
{
return detailMessage;
}
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
public ServiceException setMessage(String message)
{
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
}

@ -1,4 +1,4 @@
package com.ruoyi.common.exception;
package com.ruoyi.common.exception.base;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;

@ -1,6 +1,6 @@
package com.ruoyi.common.exception.file;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.base.BaseException;
/**
* 文件信息异常类

@ -1,6 +1,6 @@
package com.ruoyi.common.exception.user;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.base.BaseException;
/**
* 用户信息异常类

@ -3,8 +3,6 @@ package com.ruoyi.common.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -27,16 +25,10 @@ public class XssFilter implements Filter
*/
public List<String> excludes = new ArrayList<>();
/**
* xss过滤开关
*/
public boolean enabled = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String tempExcludes = filterConfig.getInitParameter("excludes");
String tempEnabled = filterConfig.getInitParameter("enabled");
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] url = tempExcludes.split(",");
@ -45,10 +37,6 @@ public class XssFilter implements Filter
excludes.add(url[i]);
}
}
if (StringUtils.isNotEmpty(tempEnabled))
{
enabled = Boolean.valueOf(tempEnabled);
}
}
@Override
@ -68,25 +56,14 @@ public class XssFilter implements Filter
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
if (!enabled)
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches("GET") || method.matches("DELETE"))
{
return true;
}
if (excludes == null || excludes.isEmpty())
{
return false;
}
String url = request.getServletPath();
for (String pattern : excludes)
{
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find())
{
return true;
}
}
return false;
return StringUtils.matches(url, excludes);
}
@Override

@ -63,7 +63,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
// xss过滤
json = EscapeUtil.clean(json).trim();
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
byte[] jsonBytes = json.getBytes("utf-8");
final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
return new ServletInputStream()
{
@Override
@ -78,6 +79,12 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
return true;
}
@Override
public int available() throws IOException
{
return jsonBytes.length;
}
@Override
public void setReadListener(ReadListener readListener)
{

@ -5,7 +5,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
/**
* 安全服务工具类
@ -14,6 +14,36 @@ import com.ruoyi.common.exception.CustomException;
*/
public class SecurityUtils
{
/**
* 用户ID
**/
public static Long getUserId()
{
try
{
return getLoginUser().getUserId();
}
catch (Exception e)
{
throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取部门ID
**/
public static Long getDeptId()
{
try
{
return getLoginUser().getDeptId();
}
catch (Exception e)
{
throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户账户
**/
@ -25,7 +55,7 @@ public class SecurityUtils
}
catch (Exception e)
{
throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
}
}
@ -40,7 +70,7 @@ public class SecurityUtils
}
catch (Exception e)
{
throw new CustomException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
}
}

@ -48,6 +48,22 @@ public class ServletUtils
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name)
{
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue)
{
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获取request
*/

@ -6,6 +6,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.util.AntPathMatcher;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter;
@ -323,6 +324,29 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return list;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
{
if (isEmpty(cs) || isEmpty(searchCharSequences))
{
return false;
}
for (CharSequence testStr : searchCharSequences)
{
if (containsIgnoreCase(cs, testStr))
{
return true;
}
}
return false;
}
/**
* 驼峰转下划线命名
*/
@ -463,6 +487,45 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{

@ -127,7 +127,7 @@ public class FileUploadUtils
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
@ -141,7 +141,7 @@ public class FileUploadUtils
return desc;
}
private static final String getPathFileName(String uploadDir, String fileName) throws IOException
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);

@ -3,6 +3,7 @@ package com.ruoyi.common.utils.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
@ -10,8 +11,12 @@ import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
/**
* 文件处理工具类
@ -53,31 +58,50 @@ public class FileUtils
}
finally
{
if (os != null)
{
try
{
os.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
if (fis != null)
{
try
{
fis.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
IOUtils.close(os);
IOUtils.close(fis);
}
}
/**
* 写数据到文件中
*
* @param data 数据
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeImportBytes(byte[] data) throws IOException
{
return writeBytes(data, RuoYiConfig.getImportPath());
}
/**
* 写数据到文件中
*
* @param data 数据
* @param uploadDir 目标文件
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeBytes(byte[] data, String uploadDir) throws IOException
{
FileOutputStream fos = null;
String pathName = "";
try
{
String extension = getFileExtendName(data);
pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
fos = new FileOutputStream(file);
fos.write(data);
}
finally
{
IOUtils.close(fos);
}
return FileUploadUtils.getPathFileName(uploadDir, pathName);
}
/**
* 删除文件
*
@ -200,4 +224,33 @@ public class FileUtils
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
/**
* 获取图像后缀
*
* @param photoByte 图像数据
* @return 后缀名
*/
public static String getFileExtendName(byte[] photoByte)
{
String strFileExtendName = "jpg";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
{
strFileExtendName = "gif";
}
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
{
strFileExtendName = "jpg";
}
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
{
strFileExtendName = "bmp";
}
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
{
strFileExtendName = "png";
}
return strFileExtendName;
}
}

@ -18,6 +18,14 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
@ -32,15 +40,23 @@ import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
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.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.annotation.Excel;
@ -50,11 +66,12 @@ import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileTypeUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
@ -116,12 +133,12 @@ public class ExcelUtil<T>
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 实体对象
*/
@ -168,24 +185,24 @@ public class ExcelUtil<T>
this.type = Type.IMPORT;
this.wb = WorkbookFactory.create(is);
List<T> list = new ArrayList<T>();
Sheet sheet = null;
if (StringUtils.isNotEmpty(sheetName))
{
// 如果指定sheet名,则取指定sheet中的内容.
sheet = wb.getSheet(sheetName);
}
else
{
// 如果传入的sheet名不存在则默认指向第1个sheet.
sheet = wb.getSheetAt(0);
}
// 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet
Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
if (sheet == null)
{
throw new IOException("文件sheet不存在");
}
int rows = sheet.getPhysicalNumberOfRows();
boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
Map<String, PictureData> pictures;
if (isXSSFWorkbook)
{
pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
}
else
{
pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
}
// 获取最后一个非空行的行下标比如总行数为n则返回的为n-1
int rows = sheet.getLastRowNum();
if (rows > 0)
{
@ -225,11 +242,12 @@ public class ExcelUtil<T>
}
}
}
for (int i = 1; i < rows; i++)
for (int i = 1; i <= rows; i++)
{
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
if(row == null)
// 判断当前行是否是空行
if (isRowEmpty(row))
{
continue;
}
@ -315,6 +333,16 @@ public class ExcelUtil<T>
{
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
}
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
if (image == null)
{
val = "";
}
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
}
@ -337,6 +365,23 @@ public class ExcelUtil<T>
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
* @throws IOException
*/
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName) throws IOException
{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
this.init(list, sheetName, Type.EXPORT);
exportExcel(response.getOutputStream());
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
@ -349,6 +394,43 @@ public class ExcelUtil<T>
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @return 结果
*/
public void importTemplateExcel(HttpServletResponse response, String sheetName) throws IOException
{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
this.init(null, sheetName, Type.IMPORT);
exportExcel(response.getOutputStream());
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @return 结果
*/
public void exportExcel(OutputStream out)
{
try
{
writeSheet();
wb.write(out);
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
}
finally
{
IOUtils.closeQuietly(wb);
IOUtils.closeQuietly(out);
}
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
@ -359,27 +441,7 @@ public class ExcelUtil<T>
OutputStream out = null;
try
{
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++)
{
createSheet(sheetNo, index);
// 产生一行
Row row = sheet.createRow(0);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (Type.EXPORT.equals(type))
{
fillExcelData(index, row);
addStatisticsRow();
}
}
writeSheet();
String filename = encodingFilename(sheetName);
out = new FileOutputStream(getAbsoluteFile(filename));
wb.write(out);
@ -388,31 +450,39 @@ public class ExcelUtil<T>
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
throw new CustomException("导出Excel失败请联系网站管理员");
throw new UtilException("导出Excel失败请联系网站管理员");
}
finally
{
if (wb != null)
IOUtils.closeQuietly(wb);
IOUtils.closeQuietly(out);
}
}
/**
* 创建写入数据到Sheet
*/
public void writeSheet()
{
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++)
{
createSheet(sheetNo, index);
// 产生一行
Row row = sheet.createRow(0);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
{
try
{
wb.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (out != null)
if (Type.EXPORT.equals(type))
{
try
{
out.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
fillExcelData(index, row);
addStatisticsRow();
}
}
}
@ -484,7 +554,7 @@ public class ExcelUtil<T>
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
@ -548,8 +618,7 @@ public class ExcelUtil<T>
}
else if (ColumnType.IMAGE == attr.cellType())
{
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
cell.getRow().getRowNum() + 1);
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
String imagePath = Convert.toStr(value);
if (StringUtils.isNotEmpty(imagePath))
{
@ -559,7 +628,7 @@ public class ExcelUtil<T>
}
}
}
/**
* 获取画布
*/
@ -802,7 +871,7 @@ public class ExcelUtil<T>
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 解析字典值
*
@ -828,7 +897,7 @@ public class ExcelUtil<T>
{
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/**
* 合计统计信息
*/
@ -859,13 +928,12 @@ public class ExcelUtil<T>
{
if (statistics.size() > 0)
{
Cell cell = null;
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
Set<Integer> keys = statistics.keySet();
cell = row.createCell(0);
Cell cell = row.createCell(0);
cell.setCellStyle(styles.get("total"));
cell.setCellValue("合计");
for (Integer key : keys)
{
cell = row.createCell(key);
@ -983,7 +1051,7 @@ public class ExcelUtil<T>
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
this.maxHeight = getRowHeight();
}
/**
* 根据注解获取最大行高
*/
@ -1097,4 +1165,92 @@ public class ExcelUtil<T>
}
return val;
}
}
/**
* 判断是否是空行
*
* @param row 判断的行
* @return
*/
private boolean isRowEmpty(Row row)
{
if (row == null)
{
return true;
}
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
{
Cell cell = row.getCell(i);
if (cell != null && cell.getCellType() != CellType.BLANK)
{
return false;
}
}
return true;
}
/**
* 获取Excel2003图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
List<HSSFPictureData> pictures = workbook.getAllPictures();
if (!pictures.isEmpty())
{
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
{
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (shape instanceof HSSFPicture)
{
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex() - 1;
HSSFPictureData picData = pictures.get(pictureIndex);
String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1());
sheetIndexPicMap.put(picIndex, picData);
}
}
return sheetIndexPicMap;
}
else
{
return sheetIndexPicMap;
}
}
/**
* 获取Excel2007图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
for (POIXMLDocumentPart dr : sheet.getRelations())
{
if (dr instanceof XSSFDrawing)
{
XSSFDrawing drawing = (XSSFDrawing) dr;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes)
{
if (shape instanceof XSSFPicture)
{
XSSFPicture pic = (XSSFPicture) shape;
XSSFClientAnchor anchor = pic.getPreferredSize();
CTMarker ctMarker = anchor.getFrom();
String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
sheetIndexPicMap.put(picIndex, pic.getPictureData());
}
}
}
}
return sheetIndexPicMap;
}
}

@ -1,6 +1,6 @@
package com.ruoyi.common.utils.sql;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.StringUtils;
/**
@ -22,7 +22,7 @@ public class SqlUtil
{
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new BaseException("参数不符合规范,不能进行查询");
throw new UtilException("参数不符合规范,不能进行查询");
}
return value;
}

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

@ -13,10 +13,8 @@ import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.common.utils.SecurityUtils;
/**
* 数据过滤处理
@ -79,7 +77,7 @@ public class DataScopeAspect
return;
}
// 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNotNull(loginUser))
{
SysUser currentUser = loginUser.getUser();

@ -27,10 +27,9 @@ import com.ruoyi.common.enums.HttpMethod;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysOperLog;
/**
@ -85,7 +84,7 @@ public class LogAspect
}
// 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();

@ -0,0 +1,116 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
/**
* 限流处理
*
* @author ruoyi
*/
@Aspect
@Component
public class RateLimiterAspect
{
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
private RedisTemplate<Object, Object> redisTemplate;
private RedisScript<Long> limitScript;
@Autowired
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
{
this.redisTemplate = redisTemplate;
}
@Autowired
public void setLimitScript(RedisScript<Long> limitScript)
{
this.limitScript = limitScript;
}
// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.annotation.RateLimiter)")
public void rateLimiterPointCut()
{
}
@Before("rateLimiterPointCut()")
public void doBefore(JoinPoint point) throws Throwable
{
RateLimiter rateLimiter = getAnnotationRateLimiter(point);
String key = rateLimiter.key();
int time = rateLimiter.time();
int count = rateLimiter.count();
String combineKey = getCombineKey(rateLimiter, point);
List<Object> keys = Collections.singletonList(combineKey);
try
{
Long number = redisTemplate.execute(limitScript, keys, count, time);
if (StringUtils.isNull(number) || number.intValue() > count)
{
throw new ServiceException("访问过于频繁,请稍后再试");
}
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key);
}
catch (ServiceException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException("服务器限流异常,请稍后再试");
}
}
/**
* 是否存在注解,如果存在就获取
*/
private RateLimiter getAnnotationRateLimiter(JoinPoint joinPoint)
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(RateLimiter.class);
}
return null;
}
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
{
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP)
{
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest()));
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
stringBuffer.append("-").append(targetClass.getName()).append("- ").append(method.getName());
return stringBuffer.toString();
}
}

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -17,11 +18,9 @@ import com.ruoyi.common.utils.StringUtils;
* @author ruoyi
*/
@Configuration
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public class FilterConfig
{
@Value("${xss.enabled}")
private String enabled;
@Value("${xss.excludes}")
private String excludes;
@ -40,7 +39,6 @@ public class FilterConfig
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes);
initParameters.put("enabled", enabled);
registration.setInitParameters(initParameters);
return registration;
}

@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@ -47,4 +48,32 @@ public class RedisConfig extends CachingConfigurerSupport
template.afterPropertiesSet();
return template;
}
@Bean
public DefaultRedisScript<Long> limitScript()
{
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(limitScriptText());
redisScript.setResultType(Long.class);
return redisScript;
}
/**
* 限流脚本
*/
private String limitScriptText()
{
return "local key = KEYS[1]\n" +
"local count = tonumber(ARGV[1])\n" +
"local time = tonumber(ARGV[2])\n" +
"local current = redis.call('get', key);\n" +
"if current and tonumber(current) > count then\n" +
" return current;\n" +
"end\n" +
"current = redis.call('incr', key)\n" +
"if tonumber(current) == 1 then\n" +
" redis.call('expire', key, time)\n" +
"end\n" +
"return current;";
}
}

@ -49,7 +49,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@ -96,8 +96,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage").anonymous()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").anonymous()
.antMatchers(
HttpMethod.GET,
"/",
@ -126,7 +126,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
/**
* 强散列哈希加密实现
*/

@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.LogUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
@ -65,7 +66,7 @@ public class AsyncFactory
logininfor.setOs(os);
logininfor.setMsg(message);
// 日志状态
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.SUCCESS);
}

@ -1,20 +1,18 @@
package com.ruoyi.framework.web.exception;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
/**
@ -28,59 +26,58 @@ public class GlobalExceptionHandler
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 基础异常
* 权限校验异常
*/
@ExceptionHandler(BaseException.class)
public AjaxResult baseException(BaseException e)
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
}
/**
* 请求方式不支持
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return AjaxResult.error(e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(CustomException.class)
public AjaxResult businessException(CustomException e)
{
if (StringUtils.isNull(e.getCode()))
{
return AjaxResult.error(e.getMessage());
}
return AjaxResult.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public AjaxResult handlerNoFoundException(Exception e)
@ExceptionHandler(ServiceException.class)
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
return AjaxResult.error(HttpStatus.NOT_FOUND, "路径不存在,请检查路径是否正确");
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
}
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAuthorizationException(AccessDeniedException e)
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
{
log.error(e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
}
@ExceptionHandler(AccountExpiredException.class)
public AjaxResult handleAccountExpiredException(AccountExpiredException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error(e.getMessage());
}
@ExceptionHandler(UsernameNotFoundException.class)
public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e)
{
log.error(e.getMessage(), e);
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e)
public AjaxResult handleException(Exception e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
@ -88,7 +85,7 @@ public class GlobalExceptionHandler
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public AjaxResult validatedBindException(BindException e)
public AjaxResult handleBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
@ -99,7 +96,7 @@ public class GlobalExceptionHandler
* 自定义验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object validExceptionHandler(MethodArgumentNotValidException e)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
{
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
@ -110,7 +107,7 @@ public class GlobalExceptionHandler
* 演示模式异常
*/
@ExceptionHandler(DemoModeException.class)
public AjaxResult demoModeException(DemoModeException e)
public AjaxResult handleDemoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
}

@ -1,12 +1,11 @@
package com.ruoyi.framework.web.service;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
/**
@ -27,9 +26,6 @@ public class PermissionService
private static final String PERMISSION_DELIMETER = ",";
@Autowired
private TokenService tokenService;
/**
* 验证用户是否具备某权限
*
@ -42,7 +38,7 @@ public class PermissionService
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
@ -73,7 +69,7 @@ public class PermissionService
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
@ -101,7 +97,7 @@ public class PermissionService
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
@ -140,7 +136,7 @@ public class PermissionService
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;

@ -11,7 +11,7 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
@ -21,6 +21,7 @@ import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
/**
@ -43,6 +44,9 @@ public class SysLoginService
@Autowired
private ISysUserService userService;
@Autowired
private ISysConfigService configService;
/**
* 登录验证
*
@ -54,18 +58,11 @@ public class SysLoginService
*/
public String login(String username, String password, String code, String uuid)
{
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
validateCaptcha(username, code, uuid);
}
// 用户验证
Authentication authentication = null;
@ -85,7 +82,7 @@ public class SysLoginService
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
throw new CustomException(e.getMessage());
throw new ServiceException(e.getMessage());
}
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
@ -95,6 +92,31 @@ public class SysLoginService
return tokenService.createToken(loginUser);
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
}
/**
* 记录登录信息
*/

@ -0,0 +1,115 @@
package com.ruoyi.framework.web.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.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
/**
* 注册校验方法
*
* @author ruoyi
*/
@Component
public class SysRegisterService
{
@Autowired
private ISysUserService userService;
@Autowired
private ISysConfigService configService;
@Autowired
private RedisCache redisCache;
/**
* 注册
*/
public String register(RegisterBody registerBody)
{
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
{
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
}
if (StringUtils.isEmpty(username))
{
msg = "用户名不能为空";
}
else if (StringUtils.isEmpty(password))
{
msg = "用户密码不能为空";
}
else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
msg = "账户长度必须在2到20个字符之间";
}
else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
msg = "密码长度必须在5到20个字符之间";
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
{
msg = "保存用户'" + username + "'失败,注册账号已存在";
}
else
{
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
boolean regFlag = userService.registerUser(sysUser);
if (!regFlag)
{
msg = "注册失败,请联系系统管理人员";
}
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER,
MessageUtils.message("user.register.success")));
}
}
return msg;
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
{
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
throw new CaptchaException();
}
}
}

@ -60,12 +60,18 @@ public class TokenService
String token = getToken(request);
if (StringUtils.isNotEmpty(token))
{
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
try
{
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
}
catch (Exception e)
{
}
}
return null;
}

@ -10,7 +10,7 @@ import org.springframework.stereotype.Service;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
@ -37,17 +37,17 @@ public class UserDetailsServiceImpl implements UserDetailsService
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
return createLoginUser(user);
@ -55,6 +55,6 @@ public class UserDetailsServiceImpl implements UserDetailsService
public UserDetails createLoginUser(SysUser user)
{
return new LoginUser(user, permissionService.getMenuPermission(user));
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
}
}

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

@ -25,7 +25,7 @@ import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.text.CharsetKit;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.GenTable;
@ -180,7 +180,7 @@ public class GenTableServiceImpl implements IGenTableService
}
catch (Exception e)
{
throw new CustomException("导入失败:" + e.getMessage());
throw new ServiceException("导入失败:" + e.getMessage());
}
}
@ -269,7 +269,7 @@ public class GenTableServiceImpl implements IGenTableService
}
catch (IOException e)
{
throw new CustomException("渲染模板失败,表名:" + table.getTableName());
throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
}
}
}
@ -291,7 +291,7 @@ public class GenTableServiceImpl implements IGenTableService
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
if (StringUtils.isEmpty(dbTableColumns))
{
throw new CustomException("同步数据失败,原表结构不存在");
throw new ServiceException("同步数据失败,原表结构不存在");
}
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
@ -383,25 +383,25 @@ public class GenTableServiceImpl implements IGenTableService
JSONObject paramsObj = JSONObject.parseObject(options);
if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
{
throw new CustomException("树编码字段不能为空");
throw new ServiceException("树编码字段不能为空");
}
else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
{
throw new CustomException("树父编码字段不能为空");
throw new ServiceException("树父编码字段不能为空");
}
else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
{
throw new CustomException("树名称字段不能为空");
throw new ServiceException("树名称字段不能为空");
}
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
{
if (StringUtils.isEmpty(genTable.getSubTableName()))
{
throw new CustomException("关联子表的表名不能为空");
throw new ServiceException("关联子表的表名不能为空");
}
else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
{
throw new CustomException("子表关联的外键名不能为空");
throw new ServiceException("子表关联的外键名不能为空");
}
}
}

@ -280,7 +280,8 @@ public class VelocityUtils
*/
public static String getParentMenuId(JSONObject paramsObj)
{
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
&& StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID)))
{
return paramsObj.getString(GenConstants.PARENT_MENU_ID);
}

@ -92,6 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
order by create_time desc
</select>
<select id="selectDbTableListByNames" resultMap="GenTableResult">

@ -76,7 +76,7 @@ public class ${ClassName}Controller extends BaseController
@GetMapping(value = "/{${pkColumn.javaField}}")
public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
{
return AjaxResult.success(${className}Service.select${ClassName}ById(${pkColumn.javaField}));
return AjaxResult.success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
}
/**
@ -109,6 +109,6 @@ public class ${ClassName}Controller extends BaseController
@DeleteMapping("/{${pkColumn.javaField}s}")
public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
{
return toAjax(${className}Service.delete${ClassName}ByIds(${pkColumn.javaField}s));
return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s));
}
}

@ -17,10 +17,10 @@ public interface ${ClassName}Mapper
/**
* 查询${functionName}
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return ${functionName}
*/
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
/**
* 查询${functionName}列表
@ -49,27 +49,27 @@ public interface ${ClassName}Mapper
/**
* 删除${functionName}
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return 结果
*/
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
/**
* 批量删除${functionName}
*
* @param ${pkColumn.javaField}s 需要删除的数据ID
* @param ${pkColumn.javaField}s 需要删除的数据主键集合
* @return 结果
*/
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s);
public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
#if($table.sub)
/**
* 批量删除${subTable.functionName}
*
* @param customerIds 需要删除的数据ID
* @param ${pkColumn.javaField}s 需要删除的数据主键集合
* @return 结果
*/
public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
public int delete${subClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
/**
* 批量新增${subTable.functionName}
@ -81,7 +81,7 @@ public interface ${ClassName}Mapper
/**
* 通过${functionName}ID删除${subTable.functionName}信息
* 通过${functionName}主键删除${subTable.functionName}信息
*
* @param ${pkColumn.javaField} ${functionName}ID
* @return 结果

@ -14,10 +14,10 @@ public interface I${ClassName}Service
/**
* 查询${functionName}
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return ${functionName}
*/
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
/**
* 查询${functionName}列表
@ -46,16 +46,16 @@ public interface I${ClassName}Service
/**
* 批量删除${functionName}
*
* @param ${pkColumn.javaField}s 需要删除的${functionName}ID
* @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合
* @return 结果
*/
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s);
public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
/**
* 删除${functionName}信息
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return 结果
*/
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
}

@ -34,13 +34,13 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
/**
* 查询${functionName}
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return ${functionName}
*/
@Override
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField})
public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
{
return ${className}Mapper.select${ClassName}ById(${pkColumn.javaField});
return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
}
/**
@ -108,34 +108,34 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
/**
* 批量删除${functionName}
*
* @param ${pkColumn.javaField}s 需要删除的${functionName}ID
* @param ${pkColumn.javaField}s 需要删除的${functionName}主键
* @return 结果
*/
#if($table.sub)
@Transactional
#end
@Override
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s)
public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s)
{
#if($table.sub)
${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
#end
return ${className}Mapper.delete${ClassName}ByIds(${pkColumn.javaField}s);
return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s);
}
/**
* 删除${functionName}信息
*
* @param ${pkColumn.javaField} ${functionName}ID
* @param ${pkColumn.javaField} ${functionName}主键
* @return 结果
*/
@Override
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField})
public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
{
#if($table.sub)
${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
#end
return ${className}Mapper.delete${ClassName}ById(${pkColumn.javaField});
return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
}
#if($table.sub)
@ -147,7 +147,7 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
public void insert${subClassName}(${ClassName} ${className})
{
List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
Long ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
if (StringUtils.isNotNull(${subclassName}List))
{
List<${subClassName}> list = new ArrayList<${subClassName}>();

@ -106,7 +106,11 @@
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" />
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope">
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
</template>
</el-table-column>
#elseif($column.list && "" != $javaField)
#if(${foreach.index} == 1)
<el-table-column label="${comment}" prop="${javaField}" />
@ -378,20 +382,6 @@ export default {
this.${businessName}Options.push(data);
});
},
#foreach ($column in $columns)
#if(${column.dictType} != '')
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
// 取消按钮
cancel() {
this.open = false;

@ -108,7 +108,7 @@
plain
icon="el-icon-download"
size="mini"
:loading="exportLoading"
:loading="exportLoading"
@click="handleExport"
v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button>
@ -135,7 +135,11 @@
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" />
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope">
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
</template>
</el-table-column>
#elseif($column.list && "" != $javaField)
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
@ -426,20 +430,6 @@ export default {
this.loading = false;
});
},
#foreach ($column in $columns)
#if(${column.dictType} != '')
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
// 取消按钮
cancel() {
this.open = false;
@ -573,19 +563,18 @@ export default {
/** ${subTable.functionName}删除按钮操作 */
handleDelete${subClassName}() {
if (this.checked${subClassName}.length == 0) {
this.$alert("请先选择要删除的${subTable.functionName}数据", "提示", { confirmButtonText: "确定", });
this.msgError("请先选择要删除的${subTable.functionName}数据");
} else {
this.${subclassName}List.splice(this.checked${subClassName}[0].index - 1, 1);
const ${subclassName}List = this.${subclassName}List;
const checked${subClassName} = this.checked${subClassName};
this.${subclassName}List = ${subclassName}List.filter(function(item) {
return checked${subClassName}.indexOf(item.index) == -1
});
}
},
/** 选框选中数据 */
/** 选框选中数据 */
handle${subClassName}SelectionChange(selection) {
if (selection.length > 1) {
this.$refs.${subclassName}.clearSelection();
this.$refs.${subclassName}.toggleRowSelection(selection.pop());
} else {
this.checked${subClassName} = selection;
}
this.checked${subClassName} = selection.map(item => item.index)
},
#end
/** 导出按钮操作 */

@ -58,7 +58,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</select>
<select id="select${ClassName}ById" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
<select id="select${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
#if($table.crud || $table.tree)
<include refid="select${ClassName}Vo"/>
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
@ -102,11 +102,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where ${pkColumn.columnName} = #{${pkColumn.javaField}}
</update>
<delete id="delete${ClassName}ById" parameterType="${pkColumn.javaType}">
<delete id="delete${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}">
delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
</delete>
<delete id="delete${ClassName}ByIds" parameterType="String">
<delete id="delete${ClassName}By${pkColumn.capJavaField}s" parameterType="String">
delete from ${tableName} where ${pkColumn.columnName} in
<foreach item="${pkColumn.javaField}" collection="array" open="(" separator="," close=")">
#{${pkColumn.javaField}}
@ -121,7 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
<delete id="delete${subClassName}By${subTableFkClassName}" parameterType="Long">
<delete id="delete${subClassName}By${subTableFkClassName}" parameterType="${pkColumn.javaType}">
delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}}
</delete>

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

@ -19,7 +19,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quartz.domain.SysJob;
@ -79,18 +78,26 @@ public class SysJobController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:add')")
@Log(title = "定时任务", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
{
if (!CronUtils.isValid(sysJob.getCronExpression()))
if (!CronUtils.isValid(job.getCronExpression()))
{
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
return error("新增任务'" + job.getJobName() + "'失败Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
}
sysJob.setCreateBy(SecurityUtils.getUsername());
return toAjax(jobService.insertJob(sysJob));
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
}
job.setCreateBy(getUsername());
return toAjax(jobService.insertJob(job));
}
/**
@ -99,18 +106,26 @@ public class SysJobController extends BaseController
@PreAuthorize("@ss.hasPermi('monitor:job:edit')")
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
{
if (!CronUtils.isValid(sysJob.getCronExpression()))
if (!CronUtils.isValid(job.getCronExpression()))
{
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
return error("修改任务'" + job.getJobName() + "'失败Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
}
sysJob.setUpdateBy(SecurityUtils.getUsername());
return toAjax(jobService.updateJob(sysJob));
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
}
job.setUpdateBy(getUsername());
return toAjax(jobService.updateJob(job));
}
/**

@ -75,7 +75,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int pauseJob(SysJob job) throws SchedulerException
{
Long jobId = job.getJobId();
@ -95,7 +95,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int resumeJob(SysJob job) throws SchedulerException
{
Long jobId = job.getJobId();
@ -115,7 +115,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int deleteJob(SysJob job) throws SchedulerException
{
Long jobId = job.getJobId();
@ -135,7 +135,7 @@ public class SysJobServiceImpl implements ISysJobService
* @return 结果
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public void deleteJobByIds(Long[] jobIds) throws SchedulerException
{
for (Long jobId : jobIds)
@ -151,7 +151,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int changeStatus(SysJob job) throws SchedulerException
{
int rows = 0;
@ -173,7 +173,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public void run(SysJob job) throws SchedulerException
{
Long jobId = job.getJobId();
@ -191,7 +191,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int insertJob(SysJob job) throws SchedulerException, TaskException
{
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
@ -209,7 +209,7 @@ public class SysJobServiceImpl implements ISysJobService
* @param job 调度信息
*/
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public int updateJob(SysJob job) throws SchedulerException, TaskException
{
SysJob properties = selectJobById(job.getJobId());

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

@ -36,6 +36,11 @@ public class RouterVo
*/
private String component;
/**
* 路由参数:如 {"id": 1, "name": "ry"}
*/
private String query;
/**
* 当你一个路由下面的 children 声明的路由大于1个时自动会变成嵌套的模式--如组件页面
*/
@ -101,6 +106,16 @@ public class RouterVo
this.component = component;
}
public String getQuery()
{
return query;
}
public void setQuery(String query)
{
this.query = query;
}
public Boolean getAlwaysShow()
{
return alwaysShow;

@ -26,6 +26,13 @@ public interface ISysConfigService
*/
public String selectConfigByKey(String configKey);
/**
* 获取验证码开关
*
* @return true开启false关闭
*/
public boolean selectCaptchaOnOff();
/**
* 查询参数配置列表
*

@ -83,6 +83,13 @@ public interface ISysDeptService
*/
public String checkDeptNameUnique(SysDept dept);
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
public void checkDeptDataScope(Long deptId);
/**
* 新增保存部门信息
*

@ -82,6 +82,13 @@ public interface ISysRoleService
*/
public void checkRoleAllowed(SysRole role);
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
public void checkRoleDataScope(Long roleId);
/**
* 通过角色ID查询角色使用数量
*

@ -97,6 +97,13 @@ public interface ISysUserService
*/
public void checkUserAllowed(SysUser user);
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
public void checkUserDataScope(Long userId);
/**
* 新增用户信息
*
@ -105,6 +112,14 @@ public interface ISysUserService
*/
public int insertUser(SysUser user);
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
public boolean registerUser(SysUser user);
/**
* 修改用户信息
*
@ -112,7 +127,7 @@ public interface ISysUserService
* @return 结果
*/
public int updateUser(SysUser user);
/**
* 用户授权角色
*

@ -1,21 +1,21 @@
package com.ruoyi.system.service.impl;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;
/**
* 参数配置 服务层实现
@ -80,6 +80,22 @@ public class SysConfigServiceImpl implements ISysConfigService
return StringUtils.EMPTY;
}
/**
* 获取验证码开关
*
* @return true开启false关闭
*/
@Override
public boolean selectCaptchaOnOff()
{
String captchaOnOff = selectConfigByKey("sys.account.captchaOnOff");
if (StringUtils.isEmpty(captchaOnOff))
{
return true;
}
return Convert.toBool(captchaOnOff);
}
/**
* 查询参数配置列表
*
@ -140,7 +156,7 @@ public class SysConfigServiceImpl implements ISysConfigService
SysConfig config = selectConfigById(configId);
if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
{
throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
}
configMapper.deleteConfigById(configId);
redisCache.deleteObject(getCacheKey(config.getConfigKey()));

@ -11,9 +11,12 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysDeptService;
@ -171,6 +174,26 @@ public class SysDeptServiceImpl implements ISysDeptService
return UserConstants.UNIQUE;
}
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
@Override
public void checkDeptDataScope(Long deptId)
{
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
{
SysDept dept = new SysDept();
dept.setDeptId(deptId);
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
if (StringUtils.isEmpty(depts))
{
throw new ServiceException("没有权限访问部门数据!");
}
}
}
/**
* 新增保存部门信息
*
@ -184,7 +207,7 @@ public class SysDeptServiceImpl implements ISysDeptService
// 如果父节点不为正常状态,则不允许新增子节点
if (!UserConstants.DEPT_NORMAL.equals(info.getStatus()))
{
throw new CustomException("部门停用,不允许新增");
throw new ServiceException("部门停用,不允许新增");
}
dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
return deptMapper.insertDept(dept);
@ -209,7 +232,8 @@ public class SysDeptServiceImpl implements ISysDeptService
updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
}
int result = deptMapper.updateDept(dept);
if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
&& !StringUtils.equals("0", dept.getAncestors()))
{
// 如果该部门是启用状态,则启用该部门的所有上级部门
updateParentDeptStatusNormal(dept);

@ -1,19 +1,19 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.mapper.SysDictTypeMapper;
import com.ruoyi.system.service.ISysDictTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.List;
/**
* 字典 业务层处理
@ -122,7 +122,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
SysDictType dictType = selectDictTypeById(dictId);
if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0)
{
throw new CustomException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
}
dictTypeMapper.deleteDictTypeById(dictId);
DictUtils.removeDictCache(dictType.getDictType());
@ -132,6 +132,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
/**
* 加载字典缓存数据
*/
@Override
public void loadingDictCache()
{
List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll();
@ -145,6 +146,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
/**
* 清空字典缓存数据
*/
@Override
public void clearDictCache()
{
DictUtils.clearDictCache();
@ -153,6 +155,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
/**
* 重置字典缓存数据
*/
@Override
public void resetDictCache()
{
clearDictCache();

@ -151,6 +151,7 @@ public class SysMenuServiceImpl implements ISysMenuService
router.setName(getRouteName(menu));
router.setPath(getRouterPath(menu));
router.setComponent(getComponent(menu));
router.setQuery(menu.getQuery());
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
List<SysMenu> cMenus = menu.getChildren();
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
@ -173,7 +174,7 @@ public class SysMenuServiceImpl implements ISysMenuService
}
else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
{
router.setMeta(null);
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
router.setPath("/inner");
List<RouterVo> childrenList = new ArrayList<RouterVo>();
RouterVo children = new RouterVo();

@ -4,7 +4,7 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.mapper.SysPostMapper;
@ -147,7 +147,7 @@ public class SysPostServiceImpl implements ISysPostService
SysPost post = selectPostById(postId);
if (countUserPostById(postId) > 0)
{
throw new CustomException(String.format("%1$s已分配,不能删除", post.getPostName()));
throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName()));
}
}
return postMapper.deletePostByIds(postIds);

@ -11,7 +11,9 @@ import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysRoleDept;
@ -183,7 +185,27 @@ public class SysRoleServiceImpl implements ISysRoleService
{
if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
{
throw new CustomException("不允许操作超级管理员角色");
throw new ServiceException("不允许操作超级管理员角色");
}
}
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
@Override
public void checkRoleDataScope(Long roleId)
{
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
{
SysRole role = new SysRole();
role.setRoleId(roleId);
List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
if (StringUtils.isEmpty(roles))
{
throw new ServiceException("没有权限访问角色数据!");
}
}
}
@ -342,7 +364,7 @@ public class SysRoleServiceImpl implements ISysRoleService
SysRole role = selectRoleById(roleId);
if (countUserRoleByRoleId(roleId) > 0)
{
throw new CustomException(String.format("%1$s已分配,不能删除", role.getRoleName()));
throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
}
}
// 删除角色与菜单关联

@ -11,9 +11,10 @@ import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.SysUserPost;
import com.ruoyi.system.domain.SysUserRole;
@ -223,7 +224,27 @@ public class SysUserServiceImpl implements ISysUserService
{
if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
{
throw new CustomException("不允许操作超级管理员用户");
throw new ServiceException("不允许操作超级管理员用户");
}
}
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
@Override
public void checkUserDataScope(Long userId)
{
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
{
SysUser user = new SysUser();
user.setUserId(userId);
List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
if (StringUtils.isEmpty(users))
{
throw new ServiceException("没有权限访问用户数据!");
}
}
}
@ -246,6 +267,18 @@ public class SysUserServiceImpl implements ISysUserService
return rows;
}
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
public boolean registerUser(SysUser user)
{
return userMapper.insertUser(user) > 0;
}
/**
* 修改保存用户信息
*
@ -473,7 +506,7 @@ public class SysUserServiceImpl implements ISysUserService
{
if (StringUtils.isNull(userList) || userList.size() == 0)
{
throw new CustomException("导入用户数据不能为空!");
throw new ServiceException("导入用户数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
@ -518,7 +551,7 @@ public class SysUserServiceImpl implements ISysUserService
if (failureNum > 0)
{
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new CustomException(failureMsg.toString());
throw new ServiceException(failureMsg.toString());
}
else
{

@ -30,6 +30,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectDeptList" parameterType="SysDept" resultMap="SysDeptResult">
<include refid="selectDeptVo"/>
where d.del_flag = '0'
<if test="deptId != null and deptId != 0">
AND dept_id = #{deptId}
</if>
<if test="parentId != null and parentId != 0">
AND parent_id = #{parentId}
</if>

@ -12,6 +12,7 @@
<result property="orderNum" column="order_num" />
<result property="path" column="path" />
<result property="component" column="component" />
<result property="query" column="query" />
<result property="isFrame" column="is_frame" />
<result property="isCache" column="is_cache" />
<result property="menuType" column="menu_type" />
@ -27,7 +28,7 @@
</resultMap>
<sql id="selectMenuVo">
select menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
select menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
from sys_menu
</sql>
@ -48,32 +49,32 @@
</select>
<select id="selectMenuTreeAll" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
left join sys_role ro on ur.role_id = ro.role_id
where ur.user_id = #{params.userId}
<if test="menuName != null and menuName != ''">
AND menu_name like concat('%', #{menuName}, '%')
AND m.menu_name like concat('%', #{menuName}, '%')
</if>
<if test="visible != null and visible != ''">
AND visible = #{visible}
AND m.visible = #{visible}
</if>
<if test="status != null and status != ''">
AND status = #{status}
AND m.status = #{status}
</if>
order by m.parent_id, m.order_num
</select>
<select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
@ -132,6 +133,7 @@
<if test="orderNum != null and orderNum != ''">order_num = #{orderNum},</if>
<if test="path != null and path != ''">path = #{path},</if>
<if test="component != null">component = #{component},</if>
<if test="query != null">query = #{query},</if>
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
@ -154,6 +156,7 @@
<if test="orderNum != null and orderNum != ''">order_num,</if>
<if test="path != null and path != ''">path,</if>
<if test="component != null and component != ''">component,</if>
<if test="query != null and query != ''">query,</if>
<if test="isFrame != null and isFrame != ''">is_frame,</if>
<if test="isCache != null and isCache != ''">is_cache,</if>
<if test="menuType != null and menuType != ''">menu_type,</if>
@ -171,6 +174,7 @@
<if test="orderNum != null and orderNum != ''">#{orderNum},</if>
<if test="path != null and path != ''">#{path},</if>
<if test="component != null and component != ''">#{component},</if>
<if test="query != null and query != ''">#{query},</if>
<if test="isFrame != null and isFrame != ''">#{isFrame},</if>
<if test="isCache != null and isCache != ''">#{isCache},</if>
<if test="menuType != null and menuType != ''">#{menuType},</if>

@ -33,6 +33,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
where r.del_flag = '0'
<if test="roleId != null and roleId != 0">
AND r.role_id = #{roleId}
</if>
<if test="roleName != null and roleName != ''">
AND r.role_name like concat('%', #{roleName}, '%')
</if>

@ -59,6 +59,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0'
<if test="userId != null and userId != 0">
AND u.user_id = #{userId}
</if>
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>

@ -1,6 +1,6 @@
@echo off
echo.
echo [<5B><>Ϣ] ʹ<><CAB9> Vue <20><><EFBFBD><EFBFBD> Web <20><><EFBFBD>̡<EFBFBD>
echo [<5B><>Ϣ] ʹ<><CAB9> Vue CLI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Web <20><><EFBFBD>̡<EFBFBD>
echo.
%~d0

@ -1,6 +1,6 @@
{
"name": "ruoyi",
"version": "3.6.0",
"version": "3.7.0",
"description": "若依管理系统",
"author": "若依",
"license": "MIT",
@ -41,7 +41,7 @@
"clipboard": "2.0.6",
"core-js": "3.8.1",
"echarts": "4.9.0",
"element-ui": "2.15.2",
"element-ui": "2.15.5",
"file-saver": "2.0.4",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",

@ -15,6 +15,18 @@ export function login(username, password, code, uuid) {
})
}
// 注册方法
export function register(data) {
return request({
url: '/register',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return request({
@ -35,6 +47,7 @@ export function logout() {
export function getCodeImg() {
return request({
url: '/captchaImage',
method: 'get'
method: 'get',
timeout: 20000
})
}

@ -60,10 +60,17 @@
color: inherit;
}
.el-dialog:not(.is-fullscreen){
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
}
.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
overflow: auto;
overflow-x: hidden;
max-height: 70vh;
padding: 10px 20px 0;
}
.el-table {
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
th {
@ -130,7 +137,7 @@
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #1890ff;
color: #409EFF;
margin-left: 5px;
}

@ -3,15 +3,15 @@
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: $sideBarWidth;
margin-left: $base-sidebar-width;
position: relative;
}
.sidebar-container {
-webkit-transition: width .28s;
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
width: $base-sidebar-width !important;
background-color: $base-menu-background;
height: 100%;
position: fixed;
font-size: 0px;
@ -81,12 +81,12 @@
}
& .theme-dark .is-active > .el-submenu__title {
color: $subMenuActiveText !important;
color: $base-menu-color-active !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
min-width: $base-sidebar-width !important;
&:hover {
background-color: rgba(0, 0, 0, 0.06) !important;
@ -95,10 +95,10 @@
& .theme-dark .nest-menu .el-submenu>.el-submenu__title,
& .theme-dark .el-submenu .el-menu-item {
background-color: $subMenuBg !important;
background-color: $base-sub-menu-background !important;
&:hover {
background-color: $subMenuHover !important;
background-color: $base-sub-menu-hover !important;
}
}
}
@ -154,7 +154,7 @@
}
.el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important;
min-width: $base-sidebar-width !important;
}
// mobile responsive
@ -165,14 +165,14 @@
.sidebar-container {
transition: transform .28s;
width: $sideBarWidth !important;
width: $base-sidebar-width !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
transform: translate3d(-$base-sidebar-width, 0, 0);
}
}
}

@ -8,37 +8,47 @@ $tiffany: #4AB7BD;
$yellow:#FEC171;
$panGreen: #30B08F;
// sidebar
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
// 默认菜单主题风格
$base-menu-color:#bfcbd9;
$base-menu-color-active:#f4f4f5;
$base-menu-background:#304156;
$base-logo-title-color: #ffffff;
$menuBg:#304156;
$menuHover:#263445;
$sidebarTitle: #ffffff;
$base-menu-light-color:rgba(0,0,0,.70);
$base-menu-light-background:#ffffff;
$base-logo-light-title-color: #001529;
$menuLightBg:#ffffff;
$menuLightHover:#f0f1f5;
$sidebarLightTitle: #001529;
$base-sub-menu-background:#1f2d3d;
$base-sub-menu-hover:#001528;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
// 自定义暗色菜单风格
/**
$base-menu-color:hsla(0,0%,100%,.65);
$base-menu-color-active:#fff;
$base-menu-background:#001529;
$base-logo-title-color: #ffffff;
$sideBarWidth: 200px;
$base-menu-light-color:rgba(0,0,0,.70);
$base-menu-light-background:#ffffff;
$base-logo-light-title-color: #001529;
$base-sub-menu-background:#000c17;
$base-sub-menu-hover:#001528;
*/
$base-sidebar-width: 200px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
menuLightBg: $menuLightBg;
menuLightHover: $menuLightHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
sidebarTitle: $sidebarTitle;
sidebarLightTitle: $sidebarLightTitle
menuColor: $base-menu-color;
menuLightColor: $base-menu-light-color;
menuColorActive: $base-menu-color-active;
menuBackground: $base-menu-background;
menuLightBackground: $base-menu-light-background;
subMenuBackground: $base-sub-menu-background;
subMenuHover: $base-sub-menu-hover;
sideBarWidth: $base-sidebar-width;
logoTitleColor: $base-logo-title-color;
logoLightTitleColor: $base-logo-light-title-color
}

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