136 Commits

Author SHA1 Message Date
170cfb356c 若依 3.6.0 2021-07-12 08:42:11 +08:00
5879c2484a 菜单路由配置支持内链访问 2021-07-11 16:31:10 +08:00
c02dad2ca3 默认访问首页新增提示语 2021-07-11 15:28:11 +08:00
1bfa14e3c6 富文本默认上传返回url类型 2021-07-10 12:17:32 +08:00
5dec58e7f5 自定义弹窗拖拽指令 2021-07-09 17:12:29 +08:00
8321f92d2c 全局注册通用组件 2021-07-09 17:09:57 +08:00
da1095e298 授权用户添加访问权限 2021-07-09 17:08:30 +08:00
f56da498ab ImageUpload组件支持多图片上传 2021-07-08 19:17:09 +08:00
e259093e01 文件上传组件添加数量限制属性 2021-07-08 15:49:04 +08:00
e963a86b15 富文本编辑组件添加类型属性 2021-07-08 15:48:11 +08:00
e447fb806b FileUpload组件支持多文件上传 2021-07-08 12:36:02 +08:00
90c41d498c 角色管理新增分配用户功能 2021-07-05 14:54:09 +08:00
ce6bea4ba0 限制超级管理员不允许操作 2021-07-05 09:57:15 +08:00
9c7901f526 用户管理新增分配角色功能 2021-07-01 18:01:36 +08:00
04f5a93aa8 升级pagehelper到最新版1.3.1 2021-06-25 17:25:49 +08:00
751ca90690 !251 修复日志列表取消字段排序时的报错问题
Merge pull request !251 from 稚屿/N/A
2021-06-25 09:23:45 +00:00
1dfeae6a03 修复日志列表取消字段排序时的报错问题 2021-06-24 00:27:37 +00:00
1ed60c79c0 用户信息长度校验限制 2021-06-22 20:45:19 +08:00
aee1e53140 全局挂载字典标签组件 2021-06-22 20:44:40 +08:00
253e2b2de1 增加字典标签样式回显 2021-06-22 14:24:26 +08:00
b1413f021e 增加字典标签样式回显 2021-06-22 14:04:14 +08:00
60c22b6a43 update ry.sh. 2021-06-17 21:29:00 +08:00
3f05ed6ffa 封装iframe组件 2021-06-17 20:17:42 +08:00
090ad5323a 日志列表支持排序操作 2021-06-17 12:30:43 +08:00
3e90fd010d 升级commons.fileupload到最新版本v1.4 2021-06-16 09:53:00 +08:00
462862ba65 升级commons.io到最新版本v2.10.0 2021-06-16 09:52:38 +08:00
7601a72faf 升级element-ui到最新版本2.15.2 2021-06-15 10:26:19 +08:00
7ab14ff293 定时任务屏蔽rmi远程调用 2021-06-15 10:26:02 +08:00
200106df39 升级oshi到最新版本v5.7.4 2021-06-11 10:29:14 +08:00
ea66e20282 修复用户搜索分页变量错误 2021-06-10 22:36:22 +08:00
a209b39552 分页组件新增pagerCount属性 2021-06-10 22:29:13 +08:00
557672ba9f 系统布局配置支持动态标题开关 2021-06-10 18:05:27 +08:00
a3116cd27d 优化部门父级启用状态 2021-06-10 15:34:38 +08:00
2ace3257f9 升级swagger到最新版本v3.0.0 2021-06-09 20:07:36 +08:00
c16ee7fc2c 升级swagger到最新版本v3.0.0 2021-06-08 16:34:36 +08:00
fd33fe869d 修复导出角色数据范围翻译缺少仅本人 2021-06-08 16:27:24 +08:00
b7446f8d0f 富文本工具栏配置视频 2021-06-03 13:26:09 +08:00
19924cd184 修复关闭confirm提示框控制台报错问题 2021-06-03 13:24:29 +08:00
85470a1549 修复表单构建选择下拉选择控制台报错问题 2021-06-02 20:43:34 +08:00
2a604c0548 !237 同步菜单新增、修改界面“功能权限”maxlength为100(保持与数据库字段长度一致),避免因超过50后不能录入问题
Merge pull request !237 from 老李/origin
2021-06-02 20:40:09 +08:00
b7f3c68eca 优化图片工具类读取文件 2021-06-02 11:45:40 +08:00
edd2981076 调整用户测试接口swagger注解 2021-06-02 11:45:30 +08:00
c105a63c8b 添加bat脚本执行应用 2021-05-31 12:16:27 +08:00
01fef0b9e1 同步菜单新增、修改界面“功能权限”maxlength为100(保持与数据库字段长度一致),避免因超过50后不能录入问题 2021-05-31 10:31:50 +08:00
af9cfb40a4 优化参数&字典缓存操作 2021-05-27 17:38:44 +08:00
6fa3bfe051 修复两处存在SQL注入漏洞问题 2021-05-27 17:38:27 +08:00
5e64a93d11 若依 3.5.0 2021-05-25 09:37:55 +08:00
4aabf5d8be Redis设置HashKey序列化 2021-05-24 15:10:55 +08:00
cf6254a8d5 用户登录后记录最后登录IP&时间 2021-05-24 14:21:29 +08:00
883cff5de9 新增IE浏览器版本过低提示页面 2021-05-24 14:15:41 +08:00
7e79c4f249 生成vue模板导出按钮点击后添加遮罩 2021-05-24 11:34:03 +08:00
504638eb41 !234 【轻量级 PR】:删去两处冗余代码
Merge pull request !234 from xivLi/master
2021-05-24 11:30:21 +08:00
2adac4a899 升级fastjson到最新版1.2.76 2021-05-24 11:25:17 +08:00
56a943bf48 升级druid到最新版本v1.2.6 2021-05-24 11:24:54 +08:00
77ebca264a 修复请求形参未传值记录日志异常问题 2021-05-23 19:22:30 +08:00
7b94ae3a9a xss校验json条件优化 2021-05-23 19:20:36 +08:00
bd1edc6dcc !233 修正方法名单词拼写错误
Merge pull request !233 from lyqwer/N/A
2021-05-23 17:15:18 +08:00
09d166e97d !231 修正注释
Merge pull request !231 from 刘立伟/N/A
2021-05-23 17:14:52 +08:00
f3e5d908d6 quartz模块下 domain包中的 SysJob类不需要实现Serializable接口 2021-05-22 16:05:12 +08:00
9651a7d7fc 删去utils.uuid下 IdUtils类中 多余的import(同包下的UUID类) 2021-05-22 15:52:19 +08:00
b2914cbcb1 修正方法名单词拼写错误 2021-05-21 17:24:48 +08:00
d0a4d6b111 修正注释 2021-05-18 10:21:48 +08:00
b431703262 导出按钮点击之后添加遮罩 2021-05-17 15:37:58 +08:00
99726be9ac 修正导入表权限标识 2021-05-11 14:26:20 +08:00
32f333a00e 删除操作日志记录日志 2021-05-11 14:25:39 +08:00
be5c19b764 树级结构更新子节点使用replaceFirst 2021-05-11 14:25:25 +08:00
dd384e4a31 上传媒体类型添加视频格式 2021-05-11 14:25:08 +08:00
bdde195e2b !225 【bug修复】文件上传时出现java.nio.file.FileAlreadyExistsException
Merge pull request !225 from CANYON/master
2021-05-11 14:19:53 +08:00
14ea071306 修复文件上传时java.nio.file.FileAlreadyExistsException 2021-05-08 15:31:16 +08:00
50034301ac 添加新群号:201396349 2021-05-06 20:40:25 +08:00
85ed712c50 !222 update ruoyi-ui/src/assets/styles/element-ui.scss.
Merge pull request !222 from leizhuogogo/N/A
2021-05-06 20:39:36 +08:00
f67d682345 !221 update ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java.
Merge pull request !221 from phper08/N/A
2021-05-06 20:39:26 +08:00
3f1427eef9 update ruoyi-ui/src/assets/styles/element-ui.scss. 2021-05-06 17:50:28 +08:00
7d0f5e94ef update ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java. 2021-05-03 13:18:33 +08:00
62081aebb9 修复开启TopNav后,左侧打开外链问题 2021-04-21 16:34:44 +08:00
3f07632cd4 修复一级菜单包屑显示重复问题 2021-04-21 15:14:36 +08:00
2c94587263 优化ExcelUtil空值处理 2021-04-21 09:53:14 +08:00
2575c17f47 主题颜色保存配置 2021-04-19 16:59:56 +08:00
b6f13c546b 过滤BindingResult对象,防止异常 2021-04-18 21:54:53 +08:00
e60a69b670 兼容顶部栏一级菜单内部跳转 2021-04-18 18:33:13 +08:00
cb18eec802 修正模板字符编码 2021-04-18 15:45:49 +08:00
bef080c60a 升级mybatis到最新版3.5.6 阻止远程代码执行漏洞 2021-04-18 15:45:37 +08:00
de73cf300b 优化树表代码生成模板 2021-04-15 10:39:09 +08:00
cbcee86d2c 优化树表代码生成模板 2021-04-15 10:37:22 +08:00
cc50224d90 固定顶部导航栏&窗口大小改变实时更新栏数 2021-04-14 11:01:16 +08:00
ff09e1cf55 数据监控默认地址修改 2021-04-13 18:15:11 +08:00
fe2ccbdc1b 优化代码生成导出模板名称 2021-04-13 14:49:42 +08:00
c8df1f5e1f 布局设置支持保存&重置配置 2021-04-13 09:47:28 +08:00
e71c00e6fa 富文本编辑器支持自定义上传地址 2021-04-13 09:38:32 +08:00
dcb9839596 !209 导出 Excel 工作表的名称 由 ${businessName} 更改为 ${functionName}
Merge pull request !209 from lihy2021/N/A
2021-04-13 09:36:49 +08:00
f13b6d92d2 !205 富文本编辑器自定义上传地址
Merge pull request !205 from hechieh/N/A
2021-04-13 09:36:42 +08:00
6595c68df1 导出 Excel 工作表的名称 由 ${businessName} 更改为 ${functionName} 2021-04-12 14:52:14 +08:00
5a2a0c09b6 优化主子表代码生成 2021-04-12 13:26:54 +08:00
9aac65ff32 新增菜单导航显示风格TopNav(false为左侧导航菜单,true为顶部导航菜单) 2021-04-12 09:54:08 +08:00
5f2350569a 页签新增关闭右侧 2021-04-10 21:15:45 +08:00
ccf05b697d 富文本编辑器自定义上传地址 2021-04-10 17:08:49 +08:00
6810243ab7 修复树表数据显示不全&加载慢问题 2021-04-09 08:31:13 +08:00
b56b8846d9 修改主题后mini类型按钮无效问题 2021-04-08 13:54:48 +08:00
8e1e4cd8fe 通用下载完成后删除节点 2021-04-08 13:46:22 +08:00
9fa5c79713 !200 update ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java.
Merge pull request !200 from yvan7123/N/A
2021-04-08 13:42:30 +08:00
40a72c2b7e !199 规范命名、用户角色单个逻辑删除、去除多余代码
Merge pull request !199 from fuzui/some_problems
2021-04-08 13:40:28 +08:00
6fe9a358b7 update ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java. 2021-04-06 11:47:27 +08:00
9f6bc13e64 🔥 去除多余代码 2021-04-02 23:06:48 +08:00
ba5ab4b091 用户、角色单条删除时,使其逻辑删除 2021-04-02 22:49:19 +08:00
17407d0127 调整cache_repeat_key为驼峰格式 2021-04-02 22:40:15 +08:00
30f330f4a0 修复firefox下表单构建拖拽会新打卡一个选项卡 2021-03-30 17:45:35 +08:00
6ca7870393 修正注释 2021-03-30 15:30:18 +08:00
2a7342ec43 !195 读取excel增加非空判断
Merge pull request !195 from 叫我宏锅锅/yuhong
2021-03-30 15:23:04 +08:00
fc57e91b80 !196 RepeatedlyRequestWrapper.ServletInputStream 实现available方法
Merge pull request !196 from wangyang/master
2021-03-30 15:17:34 +08:00
347f36ceff fix:RepeatedlyRequestWrapper.ServletInputStream 实现available方法 2021-03-29 10:17:31 +08:00
9b9c1b999f 读取excel增加
if(row == null)
{
    continue;
}
判断。防止有时候Excel表中有空数据行,导致读取时出现空指针异常。
2021-03-29 09:00:44 +08:00
ec627704b2 取消 2021-03-29 08:58:46 +08:00
9e6b2a1265 读取excel增加
if(row == null)
{
    continue;
}
判断。防止有时候Excel表中有空数据行,导致读取时出现空指针异常。
2021-03-29 08:56:51 +08:00
266a5e844f !193 修复request.getInputStream() 重复读取错误问题
Merge pull request !193 from MccRay/master
2021-03-27 13:22:01 +08:00
0822680158 update ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java.
修复 getInputStream() has already been called for this request异常问题
2021-03-25 17:39:51 +08:00
090e258bf9 显隐列初始默认隐藏列 2021-03-24 15:46:37 +08:00
505fa06dc3 !192 update ruoyi-ui/src/views/system/user/profile/userAvatar.vue.
Merge pull request !192 from 谢凯/N/A
2021-03-24 15:32:24 +08:00
6cf53bfacb !191 update ruoyi-ui/src/views/system/user/profile/userAvatar.vue.
Merge pull request !191 from allworldg/N/A
2021-03-24 15:31:51 +08:00
881dc3fcf0 update ruoyi-ui/src/views/system/user/profile/userAvatar.vue. 2021-03-22 17:52:34 +08:00
b65c8d4512 update ruoyi-ui/src/views/system/user/profile/userAvatar.vue. 2021-03-21 21:20:23 +08:00
67371a9028 个人信息添加手机&邮箱重复验证 2021-03-21 08:53:11 +08:00
01b545e4ab 通用Controller添加响应返回消息 2021-03-16 14:43:55 +08:00
c2e9200626 数据监控默认账户密码防止越权访问 2021-03-14 16:37:34 +08:00
9502203bbe !187 【漏洞修复】升级commons-collections版本,解决3.2.1版本的反序列化漏洞问题
Merge pull request !187 from Delusive/master
2021-03-14 16:32:07 +08:00
c0f1569ad9 修复commons-collections引起的反序列化漏洞 2021-03-12 16:59:06 +08:00
61432480c8 删除多余的代码 2021-03-07 11:06:47 +08:00
78deee063d !180 富文本编辑组件支持只读
Merge pull request !180 from JOSWAY/master
2021-03-07 10:44:04 +08:00
4ad003649e !182 解决 Byte[] 类型 to string 死循环的问题
Merge pull request !182 from sproutcat/master
2021-03-07 10:39:41 +08:00
616f5a6aca !185 update ruoyi-ui/src/views/monitor/logininfor/index.vue.
Merge pull request !185 from asher/N/A
2021-03-07 10:39:30 +08:00
fea3ff7b2a !184 update ruoyi-ui/src/views/monitor/operlog/index.vue.
Merge pull request !184 from asher/N/A
2021-03-07 10:39:22 +08:00
f938a24df0 update ruoyi-ui/src/views/monitor/logininfor/index.vue. 2021-03-04 17:00:07 +08:00
45fa686a64 update ruoyi-ui/src/views/monitor/operlog/index.vue. 2021-03-04 16:58:18 +08:00
0d8c3b4940 升级oshi到最新版本v5.6.0 2021-03-03 13:53:03 +08:00
64e807f27b 添加新群号:186866453 2021-02-24 13:45:24 +08:00
tzg
9a384a2fc2 解决 Byte[] 类型 to string 死循环的问题 2021-02-23 16:30:14 +08:00
339b932a3d 富文本编辑组件支持只读 2021-02-22 17:49:17 +08:00
152 changed files with 4243 additions and 1877 deletions

View File

@ -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群 [![加入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) 点击按钮入群。

105
pom.xml
View File

@ -6,28 +6,30 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.4.0</version> <version>3.6.0</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依管理系统</description> <description>若依管理系统</description>
<properties> <properties>
<ruoyi.version>3.4.0</ruoyi.version> <ruoyi.version>3.6.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<druid.version>1.2.4</druid.version> <druid.version>1.2.6</druid.version>
<bitwalker.version>1.21</bitwalker.version> <bitwalker.version>1.21</bitwalker.version>
<swagger.version>2.9.2</swagger.version> <swagger.version>3.0.0</swagger.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<pagehelper.boot.version>1.3.0</pagehelper.boot.version> <mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version>
<fastjson.version>1.2.75</fastjson.version> <pagehelper.boot.version>1.3.1</pagehelper.boot.version>
<oshi.version>5.3.6</oshi.version> <fastjson.version>1.2.76</fastjson.version>
<jna.version>5.6.0</jna.version> <oshi.version>5.7.4</oshi.version>
<commons.io.version>2.5</commons.io.version> <jna.version>5.8.0</jna.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version> <commons.io.version>2.10.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> <poi.version>4.1.2</poi.version>
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<jwt.version>0.9.1</jwt.version> <jwt.version>0.9.1</jwt.version>
@ -36,7 +38,7 @@
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- SpringBoot的依赖配置--> <!-- SpringBoot的依赖配置-->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -45,28 +47,35 @@
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!--阿里数据库连接池 --> <!-- 阿里数据库连接池 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version> <version>${druid.version}</version>
</dependency> </dependency>
<!-- 解析客户端操作系统、浏览器等 --> <!-- 解析客户端操作系统、浏览器等 -->
<dependency> <dependency>
<groupId>eu.bitwalker</groupId> <groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId> <artifactId>UserAgentUtils</artifactId>
<version>${bitwalker.version}</version> <version>${bitwalker.version}</version>
</dependency> </dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- pagehelper 分页插件 --> <!-- pagehelper 分页插件 -->
<dependency> <dependency>
<groupId>com.github.pagehelper</groupId> <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version> <version>${pagehelper.boot.version}</version>
</dependency> </dependency>
<!-- 获取系统信息 --> <!-- 获取系统信息 -->
<dependency> <dependency>
<groupId>com.github.oshi</groupId> <groupId>com.github.oshi</groupId>
@ -85,108 +94,110 @@
<artifactId>jna-platform</artifactId> <artifactId>jna-platform</artifactId>
<version>${jna.version}</version> <version>${jna.version}</version>
</dependency> </dependency>
<!-- swagger2--> <!-- Swagger3依赖 -->
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version> <version>${swagger.version}</version>
<exclusions> <exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion> <exclusion>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId> <artifactId>swagger-models</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<!-- swagger2-UI--> <!-- io常用工具类 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!--io常用工具类 -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>${commons.io.version}</version> <version>${commons.io.version}</version>
</dependency> </dependency>
<!--文件上传工具类 --> <!-- 文件上传工具类 -->
<dependency> <dependency>
<groupId>commons-fileupload</groupId> <groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId> <artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version> <version>${commons.fileupload.version}</version>
</dependency> </dependency>
<!-- excel工具 --> <!-- excel工具 -->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version> <version>${poi.version}</version>
</dependency> </dependency>
<!--velocity代码生成使用模板 --> <!-- velocity代码生成使用模板 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId> <artifactId>velocity</artifactId>
<version>${velocity.version}</version> <version>${velocity.version}</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- collections工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons.collections.version}</version>
</dependency>
<!-- 阿里JSON解析器 --> <!-- 阿里JSON解析器 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>${fastjson.version}</version> <version>${fastjson.version}</version>
</dependency> </dependency>
<!--Token生成与解析--> <!-- Token生成与解析-->
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
<version>${jwt.version}</version> <version>${jwt.version}</version>
</dependency> </dependency>
<!--验证码 --> <!-- 验证码 -->
<dependency> <dependency>
<groupId>com.github.penggle</groupId> <groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId> <artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version> <version>${kaptcha.version}</version>
</dependency> </dependency>
<!-- 定时任务--> <!-- 定时任务-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId> <artifactId>ruoyi-quartz</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 代码生成--> <!-- 代码生成-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId> <artifactId>ruoyi-generator</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 核心模块--> <!-- 核心模块-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId> <artifactId>ruoyi-framework</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 系统模块--> <!-- 系统模块-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.4.0</version> <version>3.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -24,29 +24,17 @@
<optional>true</optional> <!-- 表示依赖不会传递 --> <optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency> </dependency>
<!-- swagger2--> <!-- swagger3-->
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-boot-starter</artifactId>
</dependency>
<!--防止进入swagger页面报类型转换错误排除2.9.2中的引用手动增加1.5.21版本-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency> </dependency>
<!-- 防止进入swagger页面报类型转换错误排除3.0.0中的引用手动增加1.6.2版本 -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId> <artifactId>swagger-models</artifactId>
<version>1.5.21</version> <version>1.6.2</version>
</dependency>
<!-- swagger2-UI-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency> </dependency>
<!-- Mysql驱动包 --> <!-- Mysql驱动包 -->

View File

@ -48,6 +48,7 @@ public class SysOperlogController extends BaseController
return util.exportExcel(list, "操作日志"); return util.exportExcel(list, "操作日志");
} }
@Log(title = "操作日志", businessType = BusinessType.DELETE)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/{operIds}") @DeleteMapping("/{operIds}")
public AjaxResult remove(@PathVariable Long[] operIds) public AjaxResult remove(@PathVariable Long[] operIds)

View File

@ -118,18 +118,19 @@ public class SysConfigController extends BaseController
@DeleteMapping("/{configIds}") @DeleteMapping("/{configIds}")
public AjaxResult remove(@PathVariable Long[] configIds) public AjaxResult remove(@PathVariable Long[] configIds)
{ {
return toAjax(configService.deleteConfigByIds(configIds)); configService.deleteConfigByIds(configIds);
return success();
} }
/** /**
* 清空缓存 * 刷新参数缓存
*/ */
@PreAuthorize("@ss.hasPermi('system:config:remove')") @PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.CLEAN) @Log(title = "参数管理", businessType = BusinessType.CLEAN)
@DeleteMapping("/clearCache") @DeleteMapping("/refreshCache")
public AjaxResult clearCache() public AjaxResult refreshCache()
{ {
configService.clearCache(); configService.resetConfigCache();
return AjaxResult.success(); return AjaxResult.success();
} }
} }

View File

@ -115,6 +115,7 @@ public class SysDictDataController extends BaseController
@DeleteMapping("/{dictCodes}") @DeleteMapping("/{dictCodes}")
public AjaxResult remove(@PathVariable Long[] dictCodes) public AjaxResult remove(@PathVariable Long[] dictCodes)
{ {
return toAjax(dictDataService.deleteDictDataByIds(dictCodes)); dictDataService.deleteDictDataByIds(dictCodes);
return success();
} }
} }

View File

@ -104,18 +104,19 @@ public class SysDictTypeController extends BaseController
@DeleteMapping("/{dictIds}") @DeleteMapping("/{dictIds}")
public AjaxResult remove(@PathVariable Long[] dictIds) public AjaxResult remove(@PathVariable Long[] dictIds)
{ {
return toAjax(dictTypeService.deleteDictTypeByIds(dictIds)); dictTypeService.deleteDictTypeByIds(dictIds);
return success();
} }
/** /**
* 清空缓存 * 刷新字典缓存
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:remove')") @PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.CLEAN) @Log(title = "字典类型", businessType = BusinessType.CLEAN)
@DeleteMapping("/clearCache") @DeleteMapping("/refreshCache")
public AjaxResult clearCache() public AjaxResult refreshCache()
{ {
dictTypeService.clearCache(); dictTypeService.resetDictCache();
return AjaxResult.success(); return AjaxResult.success();
} }

View File

@ -0,0 +1,29 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
/**
* 首页
*
* @author ruoyi
*/
@RestController
public class SysIndexController
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
/**
* 访问首页,提示语
*/
@RequestMapping("/")
public String index()
{
return StringUtils.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
}
}

View File

@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
@ -102,8 +101,7 @@ public class SysMenuController extends BaseController
{ {
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
} }
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
{ {
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} }
@ -123,8 +121,7 @@ public class SysMenuController extends BaseController
{ {
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
} }
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
{ {
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} }

View File

@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
@ -19,6 +20,7 @@ import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -59,6 +61,16 @@ public class SysProfileController extends BaseController
@PutMapping @PutMapping
public AjaxResult updateProfile(@RequestBody SysUser user) public AjaxResult updateProfile(@RequestBody SysUser user)
{ {
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
if (userService.updateUserProfile(user) > 0) if (userService.updateUserProfile(user) > 0)
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());

View File

@ -17,6 +17,7 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole; 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.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
@ -26,6 +27,7 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -179,4 +181,61 @@ public class SysRoleController extends BaseController
{ {
return AjaxResult.success(roleService.selectRoleAll()); return AjaxResult.success(roleService.selectRoleAll());
} }
/**
* 查询已分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list);
}
/**
* 查询未分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list);
}
/**
* 取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{
return toAjax(roleService.deleteAuthUser(userRole));
}
/**
* 批量取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{
return toAjax(roleService.deleteAuthUsers(roleId, userIds));
}
/**
* 批量选择用户授权
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll")
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
{
return toAjax(roleService.insertAuthUsers(roleId, userIds));
}
} }

View File

@ -202,4 +202,31 @@ public class SysUserController extends BaseController
user.setUpdateBy(SecurityUtils.getUsername()); user.setUpdateBy(SecurityUtils.getUsername());
return toAjax(userService.updateUserStatus(user)); return toAjax(userService.updateUserStatus(user));
} }
/**
* 根据用户编号获取授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
AjaxResult ajax = AjaxResult.success();
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user);
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax;
}
/**
* 用户授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
userService.insertUserAuth(userId, roleIds);
return success();
}
} }

View File

@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
@ -16,6 +17,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -55,34 +57,38 @@ public class TestController extends BaseController
} }
else else
{ {
return AjaxResult.error("用户不存在"); return error("用户不存在");
} }
} }
@ApiOperation("新增用户") @ApiOperation("新增用户")
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity") @ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
})
@PostMapping("/save") @PostMapping("/save")
public AjaxResult save(UserEntity user) public AjaxResult save(UserEntity user)
{ {
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{ {
return AjaxResult.error("用户ID不能为空"); return error("用户ID不能为空");
} }
return AjaxResult.success(users.put(user.getUserId(), user)); return AjaxResult.success(users.put(user.getUserId(), user));
} }
@ApiOperation("更新用户") @ApiOperation("更新用户")
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
@PutMapping("/update") @PutMapping("/update")
public AjaxResult update(UserEntity user) public AjaxResult update(@RequestBody UserEntity user)
{ {
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{ {
return AjaxResult.error("用户ID不能为空"); return error("用户ID不能为空");
} }
if (users.isEmpty() || !users.containsKey(user.getUserId())) if (users.isEmpty() || !users.containsKey(user.getUserId()))
{ {
return AjaxResult.error("用户不存在"); return error("用户不存在");
} }
users.remove(user.getUserId()); users.remove(user.getUserId());
return AjaxResult.success(users.put(user.getUserId(), user)); return AjaxResult.success(users.put(user.getUserId(), user));
@ -96,16 +102,16 @@ public class TestController extends BaseController
if (!users.isEmpty() && users.containsKey(userId)) if (!users.isEmpty() && users.containsKey(userId))
{ {
users.remove(userId); users.remove(userId);
return AjaxResult.success(); return success();
} }
else else
{ {
return AjaxResult.error("用户不存在"); return error("用户不存在");
} }
} }
} }
@ApiModel("用户实体") @ApiModel(value = "UserEntity", description = "用户实体")
class UserEntity class UserEntity
{ {
@ApiModelProperty("用户ID") @ApiModelProperty("用户ID")

View File

@ -8,6 +8,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.RequestHandlerSelectors;
@ -16,10 +17,10 @@ import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact; import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference; import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/** /**
* Swagger2的接口配置 * Swagger2的接口配置
@ -27,7 +28,6 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
* @author ruoyi * @author ruoyi
*/ */
@Configuration @Configuration
@EnableSwagger2
public class SwaggerConfig public class SwaggerConfig
{ {
/** 系统基础配置 */ /** 系统基础配置 */
@ -48,7 +48,7 @@ public class SwaggerConfig
@Bean @Bean
public Docket createRestApi() public Docket createRestApi()
{ {
return new Docket(DocumentationType.SWAGGER_2) return new Docket(DocumentationType.OAS_30)
// 是否启用Swagger // 是否启用Swagger
.enable(enabled) .enable(enabled)
// 用来创建该API的基本信息展示在文档的页面中自定义展示的信息 // 用来创建该API的基本信息展示在文档的页面中自定义展示的信息
@ -71,10 +71,10 @@ public class SwaggerConfig
/** /**
* 安全模式这里指定token通过Authorization头请求头传递 * 安全模式这里指定token通过Authorization头请求头传递
*/ */
private List<ApiKey> securitySchemes() private List<SecurityScheme> securitySchemes()
{ {
List<ApiKey> apiKeyList = new ArrayList<ApiKey>(); List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
return apiKeyList; return apiKeyList;
} }
@ -87,7 +87,7 @@ public class SwaggerConfig
securityContexts.add( securityContexts.add(
SecurityContext.builder() SecurityContext.builder()
.securityReferences(defaultAuth()) .securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$")) .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
.build()); .build());
return securityContexts; return securityContexts;
} }

View File

@ -43,8 +43,8 @@ spring:
allow: allow:
url-pattern: /druid/* url-pattern: /druid/*
# 控制台管理用户名和密码 # 控制台管理用户名和密码
login-username: login-username: ruoyi
login-password: login-password: 123456
filter: filter:
stat: stat:
enabled: true enabled: true

View File

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

View File

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

View File

@ -126,4 +126,9 @@ public class Constants
* 资源映射路径 前缀 * 资源映射路径 前缀
*/ */
public static final String RESOURCE_PREFIX = "/profile"; public static final String RESOURCE_PREFIX = "/profile";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
} }

View File

@ -57,6 +57,9 @@ public class UserConstants
/** ParentView组件标识 */ /** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView"; public final static String PARENT_VIEW = "ParentView";
/** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink";
/** 校验返回结果码 */ /** 校验返回结果码 */
public final static String UNIQUE = "0"; public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1"; public final static String NOT_UNIQUE = "1";

View File

@ -25,7 +25,7 @@ import com.ruoyi.common.utils.sql.SqlUtil;
*/ */
public class BaseController public class BaseController
{ {
protected final Logger logger = LoggerFactory.getLogger(BaseController.class); protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/** /**
* 将前台传递过来的日期格式的字符串自动转化为Date类型 * 将前台传递过来的日期格式的字符串自动转化为Date类型
@ -59,6 +59,19 @@ public class BaseController
} }
} }
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/** /**
* 响应请求分页数据 * 响应请求分页数据
*/ */
@ -84,6 +97,49 @@ public class BaseController
return rows > 0 ? AjaxResult.success() : AjaxResult.error(); return rows > 0 ? AjaxResult.success() : AjaxResult.error();
} }
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 返回成功
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
* 返回失败消息
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/** /**
* 页面跳转 * 页面跳转
*/ */

View File

@ -33,8 +33,8 @@ public class SysRole extends BaseEntity
@Excel(name = "角色排序") @Excel(name = "角色排序")
private String roleSort; private String roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限 */ /** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope; private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */ /** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */

View File

@ -92,6 +92,9 @@ public class SysUser extends BaseEntity
/** 岗位组 */ /** 岗位组 */
private Long[] postIds; private Long[] postIds;
/** 角色ID */
private Long roleId;
public SysUser() public SysUser()
{ {
@ -300,6 +303,16 @@ public class SysUser extends BaseEntity
this.postIds = postIds; this.postIds = postIds;
} }
public Long getRoleId()
{
return roleId;
}
public void setRoleId(Long roleId)
{
this.roleId = roleId;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -1,72 +1,84 @@
package com.ruoyi.common.core.page; package com.ruoyi.common.core.page;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
/** /**
* 分页数据 * 分页数据
* *
* @author ruoyi * @author ruoyi
*/ */
public class PageDomain public class PageDomain
{ {
/** 当前记录起始索引 */ /** 当前记录起始索引 */
private Integer pageNum; private Integer pageNum;
/** 每页显示记录数 */ /** 每页显示记录数 */
private Integer pageSize; private Integer pageSize;
/** 排序列 */ /** 排序列 */
private String orderByColumn; private String orderByColumn;
/** 排序的方向desc或者asc */ /** 排序的方向desc或者asc */
private String isAsc = "asc"; private String isAsc = "asc";
public String getOrderBy() public String getOrderBy()
{ {
if (StringUtils.isEmpty(orderByColumn)) if (StringUtils.isEmpty(orderByColumn))
{ {
return ""; return "";
} }
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
} }
public Integer getPageNum() public Integer getPageNum()
{ {
return pageNum; return pageNum;
} }
public void setPageNum(Integer pageNum) public void setPageNum(Integer pageNum)
{ {
this.pageNum = pageNum; this.pageNum = pageNum;
} }
public Integer getPageSize() public Integer getPageSize()
{ {
return pageSize; return pageSize;
} }
public void setPageSize(Integer pageSize) public void setPageSize(Integer pageSize)
{ {
this.pageSize = pageSize; this.pageSize = pageSize;
} }
public String getOrderByColumn() public String getOrderByColumn()
{ {
return orderByColumn; return orderByColumn;
} }
public void setOrderByColumn(String orderByColumn) public void setOrderByColumn(String orderByColumn)
{ {
this.orderByColumn = orderByColumn; this.orderByColumn = orderByColumn;
} }
public String getIsAsc() public String getIsAsc()
{ {
return isAsc; return isAsc;
} }
public void setIsAsc(String isAsc) public void setIsAsc(String isAsc)
{ {
this.isAsc = isAsc; if (StringUtils.isNotEmpty(isAsc))
} {
} // 兼容前端排序类型
if ("ascending".equals(isAsc))
{
isAsc = "asc";
}
else if ("descending".equals(isAsc))
{
isAsc = "desc";
}
this.isAsc = isAsc;
}
}
}

View File

@ -7,10 +7,11 @@ import java.nio.charset.Charset;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Set; import java.util.Set;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
/** /**
* 类型转换器 * 类型转换器
* *
* @author ruoyi * @author ruoyi
*/ */
public class Convert public class Convert
@ -19,7 +20,7 @@ public class Convert
* 转换为字符串<br> * 转换为字符串<br>
* 如果给定的值为null或者转换失败返回默认值<br> * 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -41,7 +42,7 @@ public class Convert
* 转换为字符串<br> * 转换为字符串<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -54,7 +55,7 @@ public class Convert
* 转换为字符<br> * 转换为字符<br>
* 如果给定的值为null或者转换失败返回默认值<br> * 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -78,7 +79,7 @@ public class Convert
* 转换为字符<br> * 转换为字符<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -91,7 +92,7 @@ public class Convert
* 转换为byte<br> * 转换为byte<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -129,7 +130,7 @@ public class Convert
* 转换为byte<br> * 转换为byte<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -142,7 +143,7 @@ public class Convert
* 转换为Short<br> * 转换为Short<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -180,7 +181,7 @@ public class Convert
* 转换为Short<br> * 转换为Short<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -193,7 +194,7 @@ public class Convert
* 转换为Number<br> * 转换为Number<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -227,7 +228,7 @@ public class Convert
* 转换为Number<br> * 转换为Number<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -240,7 +241,7 @@ public class Convert
* 转换为int<br> * 转换为int<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -278,7 +279,7 @@ public class Convert
* 转换为int<br> * 转换为int<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -289,7 +290,7 @@ public class Convert
/** /**
* 转换为Integer数组<br> * 转换为Integer数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -300,7 +301,7 @@ public class Convert
/** /**
* 转换为Long数组<br> * 转换为Long数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -311,7 +312,7 @@ public class Convert
/** /**
* 转换为Integer数组<br> * 转换为Integer数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param split 被转换的值 * @param split 被转换的值
* @return 结果 * @return 结果
@ -334,7 +335,7 @@ public class Convert
/** /**
* 转换为Long数组<br> * 转换为Long数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
@ -357,7 +358,7 @@ public class Convert
/** /**
* 转换为String数组<br> * 转换为String数组<br>
* *
* @param str 被转换的值 * @param str 被转换的值
* @return 结果 * @return 结果
*/ */
@ -368,7 +369,7 @@ public class Convert
/** /**
* 转换为String数组<br> * 转换为String数组<br>
* *
* @param split 分隔符 * @param split 分隔符
* @param split 被转换的值 * @param split 被转换的值
* @return 结果 * @return 结果
@ -382,7 +383,7 @@ public class Convert
* 转换为long<br> * 转换为long<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -421,7 +422,7 @@ public class Convert
* 转换为long<br> * 转换为long<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -434,7 +435,7 @@ public class Convert
* 转换为double<br> * 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -473,7 +474,7 @@ public class Convert
* 转换为double<br> * 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -486,7 +487,7 @@ public class Convert
* 转换为Float<br> * 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -524,7 +525,7 @@ public class Convert
* 转换为Float<br> * 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -537,7 +538,7 @@ public class Convert
* 转换为boolean<br> * 转换为boolean<br>
* String支持的值为true、false、yes、ok、no1,0 如果给定的值为空,或者转换失败,返回默认值<br> * String支持的值为true、false、yes、ok、no1,0 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -583,7 +584,7 @@ public class Convert
* 转换为boolean<br> * 转换为boolean<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -595,7 +596,7 @@ public class Convert
/** /**
* 转换为Enum对象<br> * 转换为Enum对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* *
* @param clazz Enum的Class * @param clazz Enum的Class
* @param value 值 * @param value 值
* @param defaultValue 默认值 * @param defaultValue 默认值
@ -631,7 +632,7 @@ public class Convert
/** /**
* 转换为Enum对象<br> * 转换为Enum对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* *
* @param clazz Enum的Class * @param clazz Enum的Class
* @param value 值 * @param value 值
* @return Enum * @return Enum
@ -645,7 +646,7 @@ public class Convert
* 转换为BigInteger<br> * 转换为BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -683,7 +684,7 @@ public class Convert
* 转换为BigInteger<br> * 转换为BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br> * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -696,7 +697,7 @@ public class Convert
* 转换为BigDecimal<br> * 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@ -742,7 +743,7 @@ public class Convert
* 转换为BigDecimal<br> * 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br> * 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @return 结果 * @return 结果
*/ */
@ -754,7 +755,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @return 字符串 * @return 字符串
*/ */
@ -766,7 +767,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @param charsetName 字符集 * @param charsetName 字符集
* @return 字符串 * @return 字符串
@ -779,7 +780,7 @@ public class Convert
/** /**
* 将对象转为字符串<br> * 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
* *
* @param obj 对象 * @param obj 对象
* @param charset 字符集 * @param charset 字符集
* @return 字符串 * @return 字符串
@ -795,9 +796,14 @@ public class Convert
{ {
return (String) obj; return (String) obj;
} }
else if (obj instanceof byte[] || obj instanceof Byte[]) else if (obj instanceof byte[])
{ {
return str((Byte[]) obj, charset); return str((byte[]) obj, charset);
}
else if (obj instanceof Byte[])
{
byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
return str(bytes, charset);
} }
else if (obj instanceof ByteBuffer) else if (obj instanceof ByteBuffer)
{ {
@ -808,7 +814,7 @@ public class Convert
/** /**
* 将byte数组转为字符串 * 将byte数组转为字符串
* *
* @param bytes byte数组 * @param bytes byte数组
* @param charset 字符集 * @param charset 字符集
* @return 字符串 * @return 字符串
@ -820,7 +826,7 @@ public class Convert
/** /**
* 解码字节码 * 解码字节码
* *
* @param data 字符串 * @param data 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 解码后的字符串 * @return 解码后的字符串
@ -841,7 +847,7 @@ public class Convert
/** /**
* 将编码的byteBuffer数据转换为字符串 * 将编码的byteBuffer数据转换为字符串
* *
* @param data 数据 * @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集 * @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串 * @return 字符串
@ -858,7 +864,7 @@ public class Convert
/** /**
* 将编码的byteBuffer数据转换为字符串 * 将编码的byteBuffer数据转换为字符串
* *
* @param data 数据 * @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集 * @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串 * @return 字符串
@ -875,7 +881,7 @@ public class Convert
// ----------------------------------------------------------------------- 全角半角转换 // ----------------------------------------------------------------------- 全角半角转换
/** /**
* 半角转全角 * 半角转全角
* *
* @param input String. * @param input String.
* @return 全角字符串. * @return 全角字符串.
*/ */
@ -886,7 +892,7 @@ public class Convert
/** /**
* 半角转全角 * 半角转全角
* *
* @param input String * @param input String
* @param notConvertSet 不替换的字符集合 * @param notConvertSet 不替换的字符集合
* @return 全角字符串. * @return 全角字符串.
@ -917,7 +923,7 @@ public class Convert
/** /**
* 全角转半角 * 全角转半角
* *
* @param input String. * @param input String.
* @return 半角字符串 * @return 半角字符串
*/ */
@ -928,7 +934,7 @@ public class Convert
/** /**
* 替换全角为半角 * 替换全角为半角
* *
* @param text 文本 * @param text 文本
* @param notConvertSet 不替换的字符集合 * @param notConvertSet 不替换的字符集合
* @return 替换后的字符 * @return 替换后的字符
@ -960,7 +966,7 @@ public class Convert
/** /**
* 数字金额大写转换 先写个完整的然后将如零拾替换成零 * 数字金额大写转换 先写个完整的然后将如零拾替换成零
* *
* @param n 数字 * @param n 数字
* @return 中文大写数字 * @return 中文大写数字
*/ */

View File

@ -68,4 +68,14 @@ public class InvalidExtensionException extends FileUploadException
super(allowedExtension, extension, filename); super(allowedExtension, extension, filename);
} }
} }
public static class InvalidVideoExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
} }

View File

@ -30,7 +30,7 @@ public class RepeatableFilter implements Filter
{ {
ServletRequest requestWrapper = null; ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest if (request instanceof HttpServletRequest
&& StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{ {
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
} }

View File

@ -38,18 +38,21 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
@Override @Override
public ServletInputStream getInputStream() throws IOException public ServletInputStream getInputStream() throws IOException
{ {
final ByteArrayInputStream bais = new ByteArrayInputStream(body); final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() return new ServletInputStream()
{ {
@Override @Override
public int read() throws IOException public int read() throws IOException
{ {
return bais.read(); return bais.read();
} }
@Override
public int available() throws IOException
{
return body.length;
}
@Override @Override
public boolean isFinished() public boolean isFinished()
{ {

View File

@ -99,6 +99,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
public boolean isJsonRequest() public boolean isJsonRequest()
{ {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE); String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header); return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
} }
} }

View File

@ -1,114 +1,114 @@
package com.ruoyi.common.utils; package com.ruoyi.common.utils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
/** /**
* 精确的浮点数运算 * 精确的浮点数运算
* *
* @author ruoyi * @author ruoyi
*/ */
public class Arith public class Arith
{ {
/** 默认除法运算精度 */ /** 默认除法运算精度 */
private static final int DEF_DIV_SCALE = 10; private static final int DEF_DIV_SCALE = 10;
/** 这个类不能实例化 */ /** 这个类不能实例化 */
private Arith() private Arith()
{ {
} }
/** /**
* 提供精确的加法运算。 * 提供精确的加法运算。
* @param v1 被加数 * @param v1 被加数
* @param v2 加数 * @param v2 加数
* @return 两个参数的和 * @return 两个参数的和
*/ */
public static double add(double v1, double v2) public static double add(double v1, double v2)
{ {
BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2)); BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue(); return b1.add(b2).doubleValue();
} }
/** /**
* 提供精确的减法运算。 * 提供精确的减法运算。
* @param v1 被减数 * @param v1 被减数
* @param v2 减数 * @param v2 减数
* @return 两个参数的差 * @return 两个参数的差
*/ */
public static double sub(double v1, double v2) public static double sub(double v1, double v2)
{ {
BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2)); BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue(); return b1.subtract(b2).doubleValue();
} }
/** /**
* 提供精确的乘法运算。 * 提供精确的乘法运算。
* @param v1 被乘数 * @param v1 被乘数
* @param v2 乘数 * @param v2 乘数
* @return 两个参数的积 * @return 两个参数的积
*/ */
public static double mul(double v1, double v2) public static double mul(double v1, double v2)
{ {
BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2)); BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue(); return b1.multiply(b2).doubleValue();
} }
/** /**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位以后的数字四舍五入。 * 小数点以后10位以后的数字四舍五入。
* @param v1 被除数 * @param v1 被除数
* @param v2 除数 * @param v2 除数
* @return 两个参数的商 * @return 两个参数的商
*/ */
public static double div(double v1, double v2) public static double div(double v1, double v2)
{ {
return div(v1, v2, DEF_DIV_SCALE); return div(v1, v2, DEF_DIV_SCALE);
} }
/** /**
* 提供相对精确的除法运算。当发生除不尽的情况时由scale参数指 * 提供相对精确的除法运算。当发生除不尽的情况时由scale参数指
* 定精度,以后的数字四舍五入。 * 定精度,以后的数字四舍五入。
* @param v1 被除数 * @param v1 被除数
* @param v2 除数 * @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。 * @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商 * @return 两个参数的商
*/ */
public static double div(double v1, double v2, int scale) public static double div(double v1, double v2, int scale)
{ {
if (scale < 0) if (scale < 0)
{ {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The scale must be a positive integer or zero"); "The scale must be a positive integer or zero");
} }
BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2)); BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0) if (b1.compareTo(BigDecimal.ZERO) == 0)
{ {
return BigDecimal.ZERO.doubleValue(); return BigDecimal.ZERO.doubleValue();
} }
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
} }
/** /**
* 提供精确的小数位四舍五入处理。 * 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字 * @param v 需要四舍五入的数字
* @param scale 小数点后保留几位 * @param scale 小数点后保留几位
* @return 四舍五入后的结果 * @return 四舍五入后的结果
*/ */
public static double round(double v, int scale) public static double round(double v, int scale)
{ {
if (scale < 0) if (scale < 0)
{ {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The scale must be a positive integer or zero"); "The scale must be a positive integer or zero");
} }
BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1"); BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
} }
} }

View File

@ -151,6 +151,16 @@ public class DictUtils
return StringUtils.stripEnd(propertyString.toString(), separator); return StringUtils.stripEnd(propertyString.toString(), separator);
} }
/**
* 删除指定字典缓存
*
* @param key 字典键
*/
public static void removeDictCache(String key)
{
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
}
/** /**
* 清空字典缓存 * 清空字典缓存
*/ */

View File

@ -22,7 +22,7 @@ public class ExceptionUtil
return str; return str;
} }
public static String getRootErrorMseeage(Exception e) public static String getRootErrorMessage(Exception e)
{ {
Throwable root = ExceptionUtils.getRootCause(e); Throwable root = ExceptionUtils.getRootCause(e);
root = (root == null ? e : root); root = (root == null ? e : root);

View File

@ -6,6 +6,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter; import com.ruoyi.common.core.text.StrFormatter;
/** /**
@ -260,6 +261,17 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return StrFormatter.format(template, params); return StrFormatter.format(template, params);
} }
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/** /**
* 字符串转set * 字符串转set
* *
@ -312,7 +324,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
} }
/** /**
* 下划线转驼峰命名 * 驼峰转下划线命名
*/ */
public static String toUnderScoreCase(String str) public static String toUnderScoreCase(String str)
{ {

View File

@ -131,13 +131,12 @@ public class FileUploadUtils
{ {
File desc = new File(uploadDir + File.separator + fileName); File desc = new File(uploadDir + File.separator + fileName);
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
if (!desc.exists()) if (!desc.exists())
{ {
desc.createNewFile(); if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
} }
return desc; return desc;
} }
@ -186,6 +185,11 @@ public class FileUploadUtils
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName); fileName);
} }
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else else
{ {
throw new InvalidExtensionException(allowedExtension, extension, fileName); throw new InvalidExtensionException(allowedExtension, extension, fileName);

View File

@ -18,7 +18,7 @@ import com.ruoyi.common.utils.StringUtils;
* *
* @author ruoyi * @author ruoyi
*/ */
public class FileUtils extends org.apache.commons.io.FileUtils public class FileUtils
{ {
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";

View File

@ -94,6 +94,7 @@ public class ImageUtils
} }
finally finally
{ {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(baos); IOUtils.closeQuietly(baos);
} }
} }

View File

@ -24,6 +24,8 @@ public class MimeTypeUtils
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb" }; "asf", "rm", "rmvb" };
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
public static final String[] DEFAULT_ALLOWED_EXTENSION = { public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片 // 图片
"bmp", "gif", "jpg", "jpeg", "png", "bmp", "gif", "jpg", "jpeg", "png",
@ -31,6 +33,8 @@ public class MimeTypeUtils
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件 // 压缩文件
"rar", "zip", "gz", "bz2", "rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf // pdf
"pdf" }; "pdf" };

View File

@ -22,7 +22,7 @@ public class EscapeUtil
// special HTML characters // special HTML characters
TEXT['\''] = "&#039;".toCharArray(); // 单引号 TEXT['\''] = "&#039;".toCharArray(); // 单引号
TEXT['"'] = "&#34;".toCharArray(); // 引号 TEXT['"'] = "&#34;".toCharArray(); // 引号
TEXT['&'] = "&#38;".toCharArray(); // &符 TEXT['&'] = "&#38;".toCharArray(); // &符
TEXT['<'] = "&#60;".toCharArray(); // 小于号 TEXT['<'] = "&#60;".toCharArray(); // 小于号
TEXT['>'] = "&#62;".toCharArray(); // 大于号 TEXT['>'] = "&#62;".toCharArray(); // 大于号

View File

@ -229,6 +229,10 @@ public class ExcelUtil<T>
{ {
// 从第2行开始取数据,默认第一行是表头. // 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i); Row row = sheet.getRow(i);
if(row == null)
{
continue;
}
T entity = null; T entity = null;
for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet()) for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet())
{ {
@ -537,7 +541,10 @@ public class ExcelUtil<T>
} }
else if (ColumnType.NUMERIC == attr.cellType()) else if (ColumnType.NUMERIC == attr.cellType())
{ {
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); if (StringUtils.isNotNull(value))
{
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
}
} }
else if (ColumnType.IMAGE == attr.cellType()) else if (ColumnType.IMAGE == attr.cellType())
{ {

View File

@ -1,7 +1,5 @@
package com.ruoyi.common.utils.uuid; package com.ruoyi.common.utils.uuid;
import com.ruoyi.common.utils.uuid.UUID;
/** /**
* ID生成器工具类 * ID生成器工具类
* *

View File

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

View File

@ -66,6 +66,7 @@ public class DataScopeAspect
@Before("dataScopePointCut()") @Before("dataScopePointCut()")
public void doBefore(JoinPoint point) throws Throwable public void doBefore(JoinPoint point) throws Throwable
{ {
clearDataScope(point);
handleDataScope(point); handleDataScope(point);
} }
@ -166,4 +167,17 @@ public class DataScopeAspect
} }
return null; return null;
} }
/**
* 拼接权限sql前先清空params.dataScope参数防止注入
*/
private void clearDataScope(final JoinPoint joinPoint)
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, "");
}
}
} }

View File

@ -16,6 +16,7 @@ import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.HandlerMapping;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
@ -196,7 +197,7 @@ public class LogAspect
{ {
for (int i = 0; i < paramsArray.length; i++) for (int i = 0; i < paramsArray.length; i++)
{ {
if (!isFilterObject(paramsArray[i])) if (StringUtils.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i]))
{ {
Object jsonObj = JSON.toJSON(paramsArray[i]); Object jsonObj = JSON.toJSON(paramsArray[i]);
params += jsonObj.toString() + " "; params += jsonObj.toString() + " ";
@ -237,6 +238,7 @@ public class LogAspect
return entry.getValue() instanceof MultipartFile; return entry.getValue() instanceof MultipartFile;
} }
} }
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse; return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
} }
} }

View File

@ -36,9 +36,14 @@ public class RedisConfig extends CachingConfigurerSupport
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper); serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
// 使用StringRedisSerializer来序列化和反序列化redis的key值 // 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet(); template.afterPropertiesSet();
return template; return template;
} }

View File

@ -31,8 +31,7 @@ public class ResourcesConfig implements WebMvcConfigurer
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
/** swagger配置 */ /** swagger配置 */
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
} }
/** /**

View File

@ -100,12 +100,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.antMatchers("/login", "/captchaImage").anonymous() .antMatchers("/login", "/captchaImage").anonymous()
.antMatchers( .antMatchers(
HttpMethod.GET, HttpMethod.GET,
"/",
"/*.html", "/*.html",
"/**/*.html", "/**/*.html",
"/**/*.css", "/**/*.css",
"/**/*.js" "/**/*.js",
"/profile/**"
).permitAll() ).permitAll()
.antMatchers("/profile/**").anonymous()
.antMatchers("/common/download**").anonymous() .antMatchers("/common/download**").anonymous()
.antMatchers("/common/download/resource**").anonymous() .antMatchers("/common/download/resource**").anonymous()
.antMatchers("/swagger-ui.html").anonymous() .antMatchers("/swagger-ui.html").anonymous()

View File

@ -78,9 +78,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
} }
// 唯一标识指定key + 消息头) // 唯一标识指定key + 消息头)
String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey; String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cache_repeat_key); Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
if (sessionObj != null) if (sessionObj != null)
{ {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
@ -95,7 +95,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
} }
Map<String, Object> cacheMap = new HashMap<String, Object>(); Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap); cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS); redisCache.setCacheObject(cacheRepeatKey, cacheMap, intervalTime, TimeUnit.SECONDS);
return false; return false;
} }

View File

@ -8,15 +8,20 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.Constants; 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.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysUserService;
/** /**
* 登录校验方法 * 登录校验方法
@ -34,6 +39,9 @@ public class SysLoginService
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@Autowired
private ISysUserService userService;
/** /**
* 登录验证 * 登录验证
@ -82,7 +90,18 @@ public class SysLoginService
} }
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
LoginUser loginUser = (LoginUser) authentication.getPrincipal(); LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUser());
// 生成token // 生成token
return tokenService.createToken(loginUser); return tokenService.createToken(loginUser);
} }
/**
* 记录登录信息
*/
public void recordLoginInfo(SysUser user)
{
user.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
user.setLoginDate(DateUtils.getNowDate());
userService.updateUserProfile(user);
}
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.4.0</version> <version>3.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -23,6 +23,12 @@
<artifactId>velocity</artifactId> <artifactId>velocity</artifactId>
</dependency> </dependency>
<!-- collections工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>

View File

@ -101,7 +101,7 @@ public class GenController extends BaseController
/** /**
* 导入表结构(保存) * 导入表结构(保存)
*/ */
@PreAuthorize("@ss.hasPermi('tool:gen:list')") @PreAuthorize("@ss.hasPermi('tool:gen:import')")
@Log(title = "代码生成", businessType = BusinessType.IMPORT) @Log(title = "代码生成", businessType = BusinessType.IMPORT)
@PostMapping("/importTable") @PostMapping("/importTable")
public AjaxResult importTableSave(String tables) public AjaxResult importTableSave(String tables)

View File

@ -10,6 +10,7 @@ import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template; import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
@ -27,7 +28,6 @@ import com.ruoyi.common.core.text.CharsetKit;
import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn; import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.mapper.GenTableColumnMapper; import com.ruoyi.generator.mapper.GenTableColumnMapper;

View File

@ -22,7 +22,7 @@ public class VelocityInitializer
// 加载classpath目录下的vm文件 // 加载classpath目录下的vm文件
p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 定义字符集 // 定义字符集
p.setProperty(Velocity.ENCODING_DEFAULT, Constants.UTF8); p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
p.setProperty(Velocity.OUTPUT_ENCODING, Constants.UTF8); p.setProperty(Velocity.OUTPUT_ENCODING, Constants.UTF8);
// 初始化Velocity引擎指定配置Properties // 初始化Velocity引擎指定配置Properties
Velocity.init(p); Velocity.init(p);

View File

@ -1,114 +1,114 @@
package ${packageName}.controller; package ${packageName}.controller;
import java.util.List; import java.util.List;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import ${packageName}.domain.${ClassName}; import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service; import ${packageName}.service.I${ClassName}Service;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
#if($table.crud || $table.sub) #if($table.crud || $table.sub)
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
#elseif($table.tree) #elseif($table.tree)
#end #end
/** /**
* ${functionName}Controller * ${functionName}Controller
* *
* @author ${author} * @author ${author}
* @date ${datetime} * @date ${datetime}
*/ */
@RestController @RestController
@RequestMapping("/${moduleName}/${businessName}") @RequestMapping("/${moduleName}/${businessName}")
public class ${ClassName}Controller extends BaseController public class ${ClassName}Controller extends BaseController
{ {
@Autowired @Autowired
private I${ClassName}Service ${className}Service; private I${ClassName}Service ${className}Service;
/** /**
* 查询${functionName}列表 * 查询${functionName}列表
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
@GetMapping("/list") @GetMapping("/list")
#if($table.crud || $table.sub) #if($table.crud || $table.sub)
public TableDataInfo list(${ClassName} ${className}) public TableDataInfo list(${ClassName} ${className})
{ {
startPage(); startPage();
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
return getDataTable(list); return getDataTable(list);
} }
#elseif($table.tree) #elseif($table.tree)
public AjaxResult list(${ClassName} ${className}) public AjaxResult list(${ClassName} ${className})
{ {
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
return AjaxResult.success(list); return AjaxResult.success(list);
} }
#end #end
/** /**
* 导出${functionName}列表 * 导出${functionName}列表
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
@Log(title = "${functionName}", businessType = BusinessType.EXPORT) @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
@GetMapping("/export") @GetMapping("/export")
public AjaxResult export(${ClassName} ${className}) public AjaxResult export(${ClassName} ${className})
{ {
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
return util.exportExcel(list, "${businessName}"); return util.exportExcel(list, "${functionName}数据");
} }
/** /**
* 获取${functionName}详细信息 * 获取${functionName}详细信息
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
@GetMapping(value = "/{${pkColumn.javaField}}") @GetMapping(value = "/{${pkColumn.javaField}}")
public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${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}ById(${pkColumn.javaField}));
} }
/** /**
* 新增${functionName} * 新增${functionName}
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
@Log(title = "${functionName}", businessType = BusinessType.INSERT) @Log(title = "${functionName}", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@RequestBody ${ClassName} ${className}) public AjaxResult add(@RequestBody ${ClassName} ${className})
{ {
return toAjax(${className}Service.insert${ClassName}(${className})); return toAjax(${className}Service.insert${ClassName}(${className}));
} }
/** /**
* 修改${functionName} * 修改${functionName}
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
@Log(title = "${functionName}", businessType = BusinessType.UPDATE) @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody ${ClassName} ${className}) public AjaxResult edit(@RequestBody ${ClassName} ${className})
{ {
return toAjax(${className}Service.update${ClassName}(${className})); return toAjax(${className}Service.update${ClassName}(${className}));
} }
/** /**
* 删除${functionName} * 删除${functionName}
*/ */
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
@Log(title = "${functionName}", businessType = BusinessType.DELETE) @Log(title = "${functionName}", businessType = BusinessType.DELETE)
@DeleteMapping("/{${pkColumn.javaField}s}") @DeleteMapping("/{${pkColumn.javaField}s}")
public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${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}ByIds(${pkColumn.javaField}s));
} }
} }

View File

@ -1,91 +1,91 @@
package ${packageName}.mapper; package ${packageName}.mapper;
import java.util.List; import java.util.List;
import ${packageName}.domain.${ClassName}; import ${packageName}.domain.${ClassName};
#if($table.sub) #if($table.sub)
import ${packageName}.domain.${subClassName}; import ${packageName}.domain.${subClassName};
#end #end
/** /**
* ${functionName}Mapper接口 * ${functionName}Mapper接口
* *
* @author ${author} * @author ${author}
* @date ${datetime} * @date ${datetime}
*/ */
public interface ${ClassName}Mapper public interface ${ClassName}Mapper
{ {
/** /**
* 查询${functionName} * 查询${functionName}
* *
* @param ${pkColumn.javaField} ${functionName}ID * @param ${pkColumn.javaField} ${functionName}ID
* @return ${functionName} * @return ${functionName}
*/ */
public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField}); public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
/** /**
* 查询${functionName}列表 * 查询${functionName}列表
* *
* @param ${className} ${functionName} * @param ${className} ${functionName}
* @return ${functionName}集合 * @return ${functionName}集合
*/ */
public List<${ClassName}> select${ClassName}List(${ClassName} ${className}); public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
/** /**
* 新增${functionName} * 新增${functionName}
* *
* @param ${className} ${functionName} * @param ${className} ${functionName}
* @return 结果 * @return 结果
*/ */
public int insert${ClassName}(${ClassName} ${className}); public int insert${ClassName}(${ClassName} ${className});
/** /**
* 修改${functionName} * 修改${functionName}
* *
* @param ${className} ${functionName} * @param ${className} ${functionName}
* @return 结果 * @return 结果
*/ */
public int update${ClassName}(${ClassName} ${className}); public int update${ClassName}(${ClassName} ${className});
/** /**
* 删除${functionName} * 删除${functionName}
* *
* @param ${pkColumn.javaField} ${functionName}ID * @param ${pkColumn.javaField} ${functionName}ID
* @return 结果 * @return 结果
*/ */
public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField}); public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
/** /**
* 批量删除${functionName} * 批量删除${functionName}
* *
* @param ${pkColumn.javaField}s 需要删除的数据ID * @param ${pkColumn.javaField}s 需要删除的数据ID
* @return 结果 * @return 结果
*/ */
public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s); public int delete${ClassName}ByIds(${pkColumn.javaType}[] ${pkColumn.javaField}s);
#if($table.sub) #if($table.sub)
/** /**
* 批量删除${subTable.functionName} * 批量删除${subTable.functionName}
* *
* @param customerIds 需要删除的数据ID * @param customerIds 需要删除的数据ID
* @return 结果 * @return 结果
*/ */
public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
/** /**
* 批量新增${subTable.functionName} * 批量新增${subTable.functionName}
* *
* @param ${subclassName}List ${subTable.functionName}列表 * @param ${subclassName}List ${subTable.functionName}列表
* @return 结果 * @return 结果
*/ */
public int batch${subClassName}(List<${subClassName}> ${subclassName}List); public int batch${subClassName}(List<${subClassName}> ${subclassName}List);
/** /**
* 通过${functionName}ID删除${subTable.functionName}信息 * 通过${functionName}ID删除${subTable.functionName}信息
* *
* @param roleId 角色ID * @param ${pkColumn.javaField} ${functionName}ID
* @return 结果 * @return 结果
*/ */
public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField}); public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
#end #end
} }

View File

@ -108,8 +108,12 @@
#elseif($column.list && "" != $column.dictType) #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}" :formatter="${javaField}Format" />
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
#if(${foreach.index} == 1)
<el-table-column label="${comment}" prop="${javaField}" />
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" /> <el-table-column label="${comment}" align="center" prop="${javaField}" />
#end #end
#end
#end #end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
@ -120,6 +124,13 @@
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']" v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button> >修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -247,46 +258,10 @@
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "imageUpload")
import ImageUpload from '@/components/ImageUpload';
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "fileUpload")
import FileUpload from '@/components/FileUpload';
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor';
#break
#end
#end
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
components: { components: {
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "imageUpload")
ImageUpload,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "fileUpload")
FileUpload,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
Treeselect Treeselect
}, },
data() { data() {
@ -394,7 +369,7 @@ export default {
children: node.children children: node.children
}; };
}, },
/** 查询部门下拉树结构 */ /** 查询${functionName}下拉树结构 */
getTreeselect() { getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
this.${businessName}Options = []; this.${businessName}Options = [];
@ -456,16 +431,21 @@ export default {
this.handleQuery(); this.handleQuery();
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd(row) {
this.reset(); this.reset();
this.getTreeselect(); this.getTreeselect();
if (row != null && row.${treeCode}) {
this.form.${treeParentCode} = row.${treeCode};
} else {
this.form.${treeParentCode} = 0;
}
this.open = true; this.open = true;
this.title = "添加${functionName}"; this.title = "添加${functionName}";
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
this.getTreeselect(); this.getTreeselect();
if (row != null) { if (row != null) {
this.form.${treeParentCode} = row.${treeCode}; this.form.${treeParentCode} = row.${treeCode};
} }
@ -516,7 +496,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}) }).catch(() => {});
} }
} }
}; };

View File

@ -108,6 +108,7 @@
plain plain
icon="el-icon-download" icon="el-icon-download"
size="mini" size="mini"
:loading="exportLoading"
@click="handleExport" @click="handleExport"
v-hasPermi="['${moduleName}:${businessName}:export']" v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button> >导出</el-button>
@ -309,51 +310,15 @@
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "imageUpload")
import ImageUpload from '@/components/ImageUpload';
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "fileUpload")
import FileUpload from '@/components/FileUpload';
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor';
#break
#end
#end
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
components: {
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "imageUpload")
ImageUpload,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "fileUpload")
FileUpload,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
},
data() { data() {
return { return {
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 导出遮罩层
exportLoading: false,
// 选中数组 // 选中数组
ids: [], ids: [],
#if($table.sub) #if($table.sub)
@ -587,7 +552,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}) }).catch(() => {});
}, },
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
@ -630,11 +595,13 @@ export default {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(function() { }).then(() => {
this.exportLoading = true;
return export${BusinessName}(queryParams); return export${BusinessName}(queryParams);
}).then(response => { }).then(response => {
this.download(response.msg); this.download(response.msg);
}) this.exportLoading = false;
}).catch(() => {});
} }
} }
}; };

View File

@ -12,12 +12,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#if($table.sub) #if($table.sub)
<resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result"> <resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
<collection property="${subclassName}List" notNullColumn="${subTable.pkColumn.columnName}" javaType="java.util.List" resultMap="${subClassName}Result" /> <collection property="${subclassName}List" notNullColumn="sub_${subTable.pkColumn.columnName}" javaType="java.util.List" resultMap="${subClassName}Result" />
</resultMap> </resultMap>
<resultMap type="${subClassName}" id="${subClassName}Result"> <resultMap type="${subClassName}" id="${subClassName}Result">
#foreach ($column in $subTable.columns) #foreach ($column in $subTable.columns)
<result property="${column.javaField}" column="${column.columnName}" /> <result property="${column.javaField}" column="sub_${column.columnName}" />
#end #end
</resultMap> </resultMap>
#end #end
@ -64,7 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where ${pkColumn.columnName} = #{${pkColumn.javaField}} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
#elseif($table.sub) #elseif($table.sub)
select#foreach($column in $columns) a.$column.columnName#if($velocityCount != $columns.size()),#end#end, select#foreach($column in $columns) a.$column.columnName#if($velocityCount != $columns.size()),#end#end,
#foreach($column in $subTable.columns) b.$column.columnName#if($velocityCount != $subTable.columns.size()),#end#end #foreach($column in $subTable.columns) b.$column.columnName as sub_$column.columnName#if($velocityCount != $subTable.columns.size()),#end#end
from ${tableName} a from ${tableName} a
left join ${subTableName} b on b.${subTableFkName} = a.${pkColumn.columnName} left join ${subTableName} b on b.${subTableFkName} = a.${pkColumn.columnName}

View File

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

View File

@ -13,12 +13,14 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.job.TaskException; import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quartz.domain.SysJob; import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService; import com.ruoyi.quartz.service.ISysJobService;
@ -81,7 +83,11 @@ public class SysJobController extends BaseController
{ {
if (!CronUtils.isValid(sysJob.getCronExpression())) if (!CronUtils.isValid(sysJob.getCronExpression()))
{ {
return AjaxResult.error("cron表达式不正确"); return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("新增任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
sysJob.setCreateBy(SecurityUtils.getUsername()); sysJob.setCreateBy(SecurityUtils.getUsername());
return toAjax(jobService.insertJob(sysJob)); return toAjax(jobService.insertJob(sysJob));
@ -97,7 +103,11 @@ public class SysJobController extends BaseController
{ {
if (!CronUtils.isValid(sysJob.getCronExpression())) if (!CronUtils.isValid(sysJob.getCronExpression()))
{ {
return AjaxResult.error("cron表达式不正确"); return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败Cron表达式不正确");
}
else if (StringUtils.containsIgnoreCase(sysJob.getInvokeTarget(), Constants.LOOKUP_RMI))
{
return AjaxResult.error("修改任务'" + sysJob.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
sysJob.setUpdateBy(SecurityUtils.getUsername()); sysJob.setUpdateBy(SecurityUtils.getUsername());
return toAjax(jobService.updateJob(sysJob)); return toAjax(jobService.updateJob(sysJob));

View File

@ -1,6 +1,5 @@
package com.ruoyi.quartz.domain; package com.ruoyi.quartz.domain;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -19,7 +18,7 @@ import com.ruoyi.quartz.util.CronUtils;
* *
* @author ruoyi * @author ruoyi
*/ */
public class SysJob extends BaseEntity implements Serializable public class SysJob extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

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

View File

@ -1,5 +1,7 @@
package com.ruoyi.system.domain.vo; package com.ruoyi.system.domain.vo;
import com.ruoyi.common.utils.StringUtils;
/** /**
* 路由显示信息 * 路由显示信息
* *
@ -22,6 +24,11 @@ public class MetaVo
*/ */
private boolean noCache; private boolean noCache;
/**
* 内链地址http(s)://开头)
*/
private String link;
public MetaVo() public MetaVo()
{ {
} }
@ -39,6 +46,24 @@ public class MetaVo
this.noCache = noCache; this.noCache = noCache;
} }
public MetaVo(String title, String icon, String link)
{
this.title = title;
this.icon = icon;
this.link = link;
}
public MetaVo(String title, String icon, boolean noCache, String link)
{
this.title = title;
this.icon = icon;
this.noCache = noCache;
if (StringUtils.ishttp(link))
{
this.link = link;
}
}
public boolean isNoCache() public boolean isNoCache()
{ {
return noCache; return noCache;
@ -68,4 +93,14 @@ public class MetaVo
{ {
this.icon = icon; this.icon = icon;
} }
public String getLink()
{
return link;
}
public void setLink(String link)
{
this.link = link;
}
} }

View File

@ -94,11 +94,11 @@ public interface SysDeptMapper
public int updateDept(SysDept dept); public int updateDept(SysDept dept);
/** /**
* 修改所在部门的父级部门状态 * 修改所在部门正常状态
* *
* @param dept 部门 * @param deptIds 部门ID组
*/ */
public void updateDeptStatus(SysDept dept); public void updateDeptStatusNormal(Long[] deptIds);
/** /**
* 修改子元素关系 * 修改子元素关系

View File

@ -19,6 +19,22 @@ public interface SysUserMapper
*/ */
public List<SysUser> selectUserList(SysUser sysUser); public List<SysUser> selectUserList(SysUser sysUser);
/**
* 根据条件分页查询未已配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
public List<SysUser> selectAllocatedList(SysUser user);
/**
* 根据条件分页查询未分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
public List<SysUser> selectUnallocatedList(SysUser user);
/** /**
* 通过用户名查询用户 * 通过用户名查询用户
* *

View File

@ -56,12 +56,22 @@ public interface ISysConfigService
* @param configIds 需要删除的参数ID * @param configIds 需要删除的参数ID
* @return 结果 * @return 结果
*/ */
public int deleteConfigByIds(Long[] configIds); public void deleteConfigByIds(Long[] configIds);
/** /**
* 清空缓存数据 * 加载参数缓存数据
*/ */
public void clearCache(); public void loadingConfigCache();
/**
* 清空参数缓存数据
*/
public void clearConfigCache();
/**
* 重置参数缓存数据
*/
public void resetConfigCache();
/** /**
* 校验参数键名是否唯一 * 校验参数键名是否唯一

View File

@ -41,7 +41,7 @@ public interface ISysDictDataService
* @param dictCodes 需要删除的字典数据ID * @param dictCodes 需要删除的字典数据ID
* @return 结果 * @return 结果
*/ */
public int deleteDictDataByIds(Long[] dictCodes); public void deleteDictDataByIds(Long[] dictCodes);
/** /**
* 新增保存字典数据信息 * 新增保存字典数据信息

View File

@ -56,12 +56,22 @@ public interface ISysDictTypeService
* @param dictIds 需要删除的字典ID * @param dictIds 需要删除的字典ID
* @return 结果 * @return 结果
*/ */
public int deleteDictTypeByIds(Long[] dictIds); public void deleteDictTypeByIds(Long[] dictIds);
/** /**
* 清空缓存数据 * 加载字典缓存数据
*/ */
public void clearCache(); public void loadingDictCache();
/**
* 清空字典缓存数据
*/
public void clearDictCache();
/**
* 重置字典缓存数据
*/
public void resetDictCache();
/** /**
* 新增保存字典类型信息 * 新增保存字典类型信息

View File

@ -3,6 +3,7 @@ package com.ruoyi.system.service;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.system.domain.SysUserRole;
/** /**
* 角色业务层 * 角色业务层
@ -20,7 +21,15 @@ public interface ISysRoleService
public List<SysRole> selectRoleList(SysRole role); public List<SysRole> selectRoleList(SysRole role);
/** /**
* 根据用户ID查询角色 * 根据用户ID查询角色列表
*
* @param userId 用户ID
* @return 角色列表
*/
public List<SysRole> selectRolesByUserId(Long userId);
/**
* 根据用户ID查询角色权限
* *
* @param userId 用户ID * @param userId 用户ID
* @return 权限列表 * @return 权限列表
@ -128,4 +137,30 @@ public interface ISysRoleService
* @return 结果 * @return 结果
*/ */
public int deleteRoleByIds(Long[] roleIds); public int deleteRoleByIds(Long[] roleIds);
/**
* 取消授权用户角色
*
* @param userRole 用户和角色关联信息
* @return 结果
*/
public int deleteAuthUser(SysUserRole userRole);
/**
* 批量取消授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要取消授权的用户数据ID
* @return 结果
*/
public int deleteAuthUsers(Long roleId, Long[] userIds);
/**
* 批量选择授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要删除的用户数据ID
* @return 结果
*/
public int insertAuthUsers(Long roleId, Long[] userIds);
} }

View File

@ -18,6 +18,22 @@ public interface ISysUserService
*/ */
public List<SysUser> selectUserList(SysUser user); public List<SysUser> selectUserList(SysUser user);
/**
* 根据条件分页查询已分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
public List<SysUser> selectAllocatedList(SysUser user);
/**
* 根据条件分页查询未分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
public List<SysUser> selectUnallocatedList(SysUser user);
/** /**
* 通过用户名查询用户 * 通过用户名查询用户
* *
@ -96,6 +112,14 @@ public interface ISysUserService
* @return 结果 * @return 结果
*/ */
public int updateUser(SysUser user); public int updateUser(SysUser user);
/**
* 用户授权角色
*
* @param userId 用户ID
* @param roleIds 角色组
*/
public void insertUserAuth(Long userId, Long[] roleIds);
/** /**
* 修改用户状态 * 修改用户状态

View File

@ -37,11 +37,7 @@ public class SysConfigServiceImpl implements ISysConfigService
@PostConstruct @PostConstruct
public void init() public void init()
{ {
List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig()); loadingConfigCache();
for (SysConfig config : configsList)
{
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
}
} }
/** /**
@ -137,7 +133,7 @@ public class SysConfigServiceImpl implements ISysConfigService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteConfigByIds(Long[] configIds) public void deleteConfigByIds(Long[] configIds)
{ {
for (Long configId : configIds) for (Long configId : configIds)
{ {
@ -146,26 +142,44 @@ public class SysConfigServiceImpl implements ISysConfigService
{ {
throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
} }
configMapper.deleteConfigById(configId);
redisCache.deleteObject(getCacheKey(config.getConfigKey()));
} }
int count = configMapper.deleteConfigByIds(configIds);
if (count > 0)
{
Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
redisCache.deleteObject(keys);
}
return count;
} }
/** /**
* 清空缓存数据 * 加载参数缓存数据
*/ */
@Override @Override
public void clearCache() public void loadingConfigCache()
{
List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
for (SysConfig config : configsList)
{
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
}
}
/**
* 清空参数缓存数据
*/
@Override
public void clearConfigCache()
{ {
Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*"); Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
redisCache.deleteObject(keys); redisCache.deleteObject(keys);
} }
/**
* 重置参数缓存数据
*/
@Override
public void resetConfigCache()
{
clearConfigCache();
loadingConfigCache();
}
/** /**
* 校验参数键名是否唯一 * 校验参数键名是否唯一
* *

View File

@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect; import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysDeptMapper;
@ -211,7 +212,7 @@ public class SysDeptServiceImpl implements ISysDeptService
if (UserConstants.DEPT_NORMAL.equals(dept.getStatus())) if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
{ {
// 如果该部门是启用状态,则启用该部门的所有上级部门 // 如果该部门是启用状态,则启用该部门的所有上级部门
updateParentDeptStatus(dept); updateParentDeptStatusNormal(dept);
} }
return result; return result;
} }
@ -221,12 +222,11 @@ public class SysDeptServiceImpl implements ISysDeptService
* *
* @param dept 当前部门 * @param dept 当前部门
*/ */
private void updateParentDeptStatus(SysDept dept) private void updateParentDeptStatusNormal(SysDept dept)
{ {
String updateBy = dept.getUpdateBy(); String ancestors = dept.getAncestors();
dept = deptMapper.selectDeptById(dept.getDeptId()); Long[] deptIds = Convert.toLongArray(ancestors);
dept.setUpdateBy(updateBy); deptMapper.updateDeptStatusNormal(deptIds);
deptMapper.updateDeptStatus(dept);
} }
/** /**
@ -241,7 +241,7 @@ public class SysDeptServiceImpl implements ISysDeptService
List<SysDept> children = deptMapper.selectChildrenDeptById(deptId); List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
for (SysDept child : children) for (SysDept child : children)
{ {
child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors)); child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
} }
if (children.size() > 0) if (children.size() > 0)
{ {

View File

@ -63,29 +63,31 @@ public class SysDictDataServiceImpl implements ISysDictDataService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteDictDataByIds(Long[] dictCodes) public void deleteDictDataByIds(Long[] dictCodes)
{ {
int row = dictDataMapper.deleteDictDataByIds(dictCodes); for (Long dictCode : dictCodes)
if (row > 0)
{ {
DictUtils.clearDictCache(); SysDictData data = selectDictDataById(dictCode);
dictDataMapper.deleteDictDataById(dictCode);
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
} }
return row;
} }
/** /**
* 新增保存字典数据信息 * 新增保存字典数据信息
* *
* @param dictData 字典数据信息 * @param data 字典数据信息
* @return 结果 * @return 结果
*/ */
@Override @Override
public int insertDictData(SysDictData dictData) public int insertDictData(SysDictData data)
{ {
int row = dictDataMapper.insertDictData(dictData); int row = dictDataMapper.insertDictData(data);
if (row > 0) if (row > 0)
{ {
DictUtils.clearDictCache(); List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
} }
return row; return row;
} }
@ -93,16 +95,17 @@ public class SysDictDataServiceImpl implements ISysDictDataService
/** /**
* 修改保存字典数据信息 * 修改保存字典数据信息
* *
* @param dictData 字典数据信息 * @param data 字典数据信息
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateDictData(SysDictData dictData) public int updateDictData(SysDictData data)
{ {
int row = dictDataMapper.updateDictData(dictData); int row = dictDataMapper.updateDictData(data);
if (row > 0) if (row > 0)
{ {
DictUtils.clearDictCache(); List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
} }
return row; return row;
} }

View File

@ -35,12 +35,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
@PostConstruct @PostConstruct
public void init() public void init()
{ {
List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll(); loadingDictCache();
for (SysDictType dictType : dictTypeList)
{
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
DictUtils.setDictCache(dictType.getDictType(), dictDatas);
}
} }
/** /**
@ -120,7 +115,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteDictTypeByIds(Long[] dictIds) public void deleteDictTypeByIds(Long[] dictIds)
{ {
for (Long dictId : dictIds) for (Long dictId : dictIds)
{ {
@ -129,37 +124,54 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
{ {
throw new CustomException(String.format("%1$s已分配,不能删除", dictType.getDictName())); throw new CustomException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
} }
dictTypeMapper.deleteDictTypeById(dictId);
DictUtils.removeDictCache(dictType.getDictType());
} }
int count = dictTypeMapper.deleteDictTypeByIds(dictIds);
if (count > 0)
{
DictUtils.clearDictCache();
}
return count;
} }
/** /**
* 清空缓存数据 * 加载字典缓存数据
*/ */
@Override public void loadingDictCache()
public void clearCache() {
List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll();
for (SysDictType dictType : dictTypeList)
{
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
DictUtils.setDictCache(dictType.getDictType(), dictDatas);
}
}
/**
* 清空字典缓存数据
*/
public void clearDictCache()
{ {
DictUtils.clearDictCache(); DictUtils.clearDictCache();
} }
/**
* 重置字典缓存数据
*/
public void resetDictCache()
{
clearDictCache();
loadingDictCache();
}
/** /**
* 新增保存字典类型信息 * 新增保存字典类型信息
* *
* @param dictType 字典类型信息 * @param dict 字典类型信息
* @return 结果 * @return 结果
*/ */
@Override @Override
public int insertDictType(SysDictType dictType) public int insertDictType(SysDictType dict)
{ {
int row = dictTypeMapper.insertDictType(dictType); int row = dictTypeMapper.insertDictType(dict);
if (row > 0) if (row > 0)
{ {
DictUtils.clearDictCache(); DictUtils.setDictCache(dict.getDictType(), null);
} }
return row; return row;
} }
@ -167,19 +179,20 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
/** /**
* 修改保存字典类型信息 * 修改保存字典类型信息
* *
* @param dictType 字典类型信息 * @param dict 字典类型信息
* @return 结果 * @return 结果
*/ */
@Override @Override
@Transactional @Transactional
public int updateDictType(SysDictType dictType) public int updateDictType(SysDictType dict)
{ {
SysDictType oldDict = dictTypeMapper.selectDictTypeById(dictType.getDictId()); SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId());
dictDataMapper.updateDictDataType(oldDict.getDictType(), dictType.getDictType()); dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType());
int row = dictTypeMapper.updateDictType(dictType); int row = dictTypeMapper.updateDictType(dict);
if (row > 0) if (row > 0)
{ {
DictUtils.clearDictCache(); List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType());
DictUtils.setDictCache(dict.getDictType(), dictDatas);
} }
return row; return row;
} }

View File

@ -1,465 +1,501 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.TreeSelect; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.vo.MetaVo; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.mapper.SysMenuMapper; import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper; import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.mapper.SysRoleMenuMapper;
import com.ruoyi.system.service.ISysMenuService;
/**
* 菜单 业务层处理 /**
* * 菜单 业务层处理
* @author ruoyi *
*/ * @author ruoyi
@Service */
public class SysMenuServiceImpl implements ISysMenuService @Service
{ public class SysMenuServiceImpl implements ISysMenuService
public static final String PREMISSION_STRING = "perms[\"{0}\"]"; {
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
@Autowired
private SysMenuMapper menuMapper; @Autowired
private SysMenuMapper menuMapper;
@Autowired
private SysRoleMapper roleMapper; @Autowired
private SysRoleMapper roleMapper;
@Autowired
private SysRoleMenuMapper roleMenuMapper; @Autowired
private SysRoleMenuMapper roleMenuMapper;
/**
* 根据用户查询系统菜单列表 /**
* * 根据用户查询系统菜单列表
* @param userId 用户ID *
* @return 菜单列表 * @param userId 用户ID
*/ * @return 菜单列表
@Override */
public List<SysMenu> selectMenuList(Long userId) @Override
{ public List<SysMenu> selectMenuList(Long userId)
return selectMenuList(new SysMenu(), userId); {
} return selectMenuList(new SysMenu(), userId);
}
/**
* 查询系统菜单列表 /**
* * 查询系统菜单列表
* @param menu 菜单信息 *
* @return 菜单列表 * @param menu 菜单信息
*/ * @return 菜单列表
@Override */
public List<SysMenu> selectMenuList(SysMenu menu, Long userId) @Override
{ public List<SysMenu> selectMenuList(SysMenu menu, Long userId)
List<SysMenu> menuList = null; {
// 管理员显示所有菜单信息 List<SysMenu> menuList = null;
if (SysUser.isAdmin(userId)) // 管理员显示所有菜单信息
{ if (SysUser.isAdmin(userId))
menuList = menuMapper.selectMenuList(menu); {
} menuList = menuMapper.selectMenuList(menu);
else }
{ else
menu.getParams().put("userId", userId); {
menuList = menuMapper.selectMenuListByUserId(menu); menu.getParams().put("userId", userId);
} menuList = menuMapper.selectMenuListByUserId(menu);
return menuList; }
} return menuList;
}
/**
* 根据用户ID查询权限 /**
* * 根据用户ID查询权限
* @param userId 用户ID *
* @return 权限列表 * @param userId 用户ID
*/ * @return 权限列表
@Override */
public Set<String> selectMenuPermsByUserId(Long userId) @Override
{ public Set<String> selectMenuPermsByUserId(Long userId)
List<String> perms = menuMapper.selectMenuPermsByUserId(userId); {
Set<String> permsSet = new HashSet<>(); List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
for (String perm : perms) Set<String> permsSet = new HashSet<>();
{ for (String perm : perms)
if (StringUtils.isNotEmpty(perm)) {
{ if (StringUtils.isNotEmpty(perm))
permsSet.addAll(Arrays.asList(perm.trim().split(","))); {
} permsSet.addAll(Arrays.asList(perm.trim().split(",")));
} }
return permsSet; }
} return permsSet;
}
/**
* 根据用户ID查询菜单 /**
* * 根据用户ID查询菜单
* @param userId 用户名称 *
* @return 菜单列表 * @param userId 用户名称
*/ * @return 菜单列表
@Override */
public List<SysMenu> selectMenuTreeByUserId(Long userId) @Override
{ public List<SysMenu> selectMenuTreeByUserId(Long userId)
List<SysMenu> menus = null; {
if (SecurityUtils.isAdmin(userId)) List<SysMenu> menus = null;
{ if (SecurityUtils.isAdmin(userId))
menus = menuMapper.selectMenuTreeAll(); {
} menus = menuMapper.selectMenuTreeAll();
else }
{ else
menus = menuMapper.selectMenuTreeByUserId(userId); {
} menus = menuMapper.selectMenuTreeByUserId(userId);
return getChildPerms(menus, 0); }
} return getChildPerms(menus, 0);
}
/**
* 根据角色ID查询菜单树信息 /**
* * 根据角色ID查询菜单树信息
* @param roleId 角色ID *
* @return 选中菜单列表 * @param roleId 角色ID
*/ * @return 选中菜单列表
@Override */
public List<Integer> selectMenuListByRoleId(Long roleId) @Override
{ public List<Integer> selectMenuListByRoleId(Long roleId)
SysRole role = roleMapper.selectRoleById(roleId); {
return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); SysRole role = roleMapper.selectRoleById(roleId);
} return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
}
/**
* 构建前端路由所需要的菜单 /**
* * 构建前端路由所需要的菜单
* @param menus 菜单列表 *
* @return 路由列表 * @param menus 菜单列表
*/ * @return 路由列表
@Override */
public List<RouterVo> buildMenus(List<SysMenu> menus) @Override
{ public List<RouterVo> buildMenus(List<SysMenu> menus)
List<RouterVo> routers = new LinkedList<RouterVo>(); {
for (SysMenu menu : menus) List<RouterVo> routers = new LinkedList<RouterVo>();
{ for (SysMenu menu : menus)
RouterVo router = new RouterVo(); {
router.setHidden("1".equals(menu.getVisible())); RouterVo router = new RouterVo();
router.setName(getRouteName(menu)); router.setHidden("1".equals(menu.getVisible()));
router.setPath(getRouterPath(menu)); router.setName(getRouteName(menu));
router.setComponent(getComponent(menu)); router.setPath(getRouterPath(menu));
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); router.setComponent(getComponent(menu));
List<SysMenu> cMenus = menu.getChildren(); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) List<SysMenu> cMenus = menu.getChildren();
{ if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
router.setAlwaysShow(true); {
router.setRedirect("noRedirect"); router.setAlwaysShow(true);
router.setChildren(buildMenus(cMenus)); router.setRedirect("noRedirect");
} router.setChildren(buildMenus(cMenus));
else if (isMeunFrame(menu)) }
{ else if (isMenuFrame(menu))
List<RouterVo> childrenList = new ArrayList<RouterVo>(); {
RouterVo children = new RouterVo(); router.setMeta(null);
children.setPath(menu.getPath()); List<RouterVo> childrenList = new ArrayList<RouterVo>();
children.setComponent(menu.getComponent()); RouterVo children = new RouterVo();
children.setName(StringUtils.capitalize(menu.getPath())); children.setPath(menu.getPath());
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); children.setComponent(menu.getComponent());
childrenList.add(children); children.setName(StringUtils.capitalize(menu.getPath()));
router.setChildren(childrenList); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
} childrenList.add(children);
routers.add(router); router.setChildren(childrenList);
} }
return routers; else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
} {
router.setMeta(null);
/** router.setPath("/inner");
* 构建前端所需要树结构 List<RouterVo> childrenList = new ArrayList<RouterVo>();
* RouterVo children = new RouterVo();
* @param menus 菜单列表 String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
* @return 树结构列表 children.setPath(routerPath);
*/ children.setComponent(UserConstants.INNER_LINK);
@Override children.setName(StringUtils.capitalize(routerPath));
public List<SysMenu> buildMenuTree(List<SysMenu> menus) children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
{ childrenList.add(children);
List<SysMenu> returnList = new ArrayList<SysMenu>(); router.setChildren(childrenList);
List<Long> tempList = new ArrayList<Long>(); }
for (SysMenu dept : menus) routers.add(router);
{ }
tempList.add(dept.getMenuId()); return routers;
} }
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
{ /**
SysMenu menu = (SysMenu) iterator.next(); * 构建前端所需要树结构
// 如果是顶级节点, 遍历该父节点的所有子节点 *
if (!tempList.contains(menu.getParentId())) * @param menus 菜单列表
{ * @return 树结构列表
recursionFn(menus, menu); */
returnList.add(menu); @Override
} public List<SysMenu> buildMenuTree(List<SysMenu> menus)
} {
if (returnList.isEmpty()) List<SysMenu> returnList = new ArrayList<SysMenu>();
{ List<Long> tempList = new ArrayList<Long>();
returnList = menus; for (SysMenu dept : menus)
} {
return returnList; tempList.add(dept.getMenuId());
} }
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
/** {
* 构建前端所需要下拉树结构 SysMenu menu = (SysMenu) iterator.next();
* // 如果是顶级节点, 遍历该父节点的所有子节点
* @param menus 菜单列表 if (!tempList.contains(menu.getParentId()))
* @return 下拉树结构列表 {
*/ recursionFn(menus, menu);
@Override returnList.add(menu);
public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) }
{ }
List<SysMenu> menuTrees = buildMenuTree(menus); if (returnList.isEmpty())
return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); {
} returnList = menus;
}
/** return returnList;
* 根据菜单ID查询信息 }
*
* @param menuId 菜单ID /**
* @return 菜单信息 * 构建前端所需要下拉树结构
*/ *
@Override * @param menus 菜单列表
public SysMenu selectMenuById(Long menuId) * @return 下拉树结构列表
{ */
return menuMapper.selectMenuById(menuId); @Override
} public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
{
/** List<SysMenu> menuTrees = buildMenuTree(menus);
* 是否存在菜单子节点 return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
* }
* @param menuId 菜单ID
* @return 结果 /**
*/ * 根据菜单ID查询信息
@Override *
public boolean hasChildByMenuId(Long menuId) * @param menuId 菜单ID
{ * @return 菜单信息
int result = menuMapper.hasChildByMenuId(menuId); */
return result > 0 ? true : false; @Override
} public SysMenu selectMenuById(Long menuId)
{
/** return menuMapper.selectMenuById(menuId);
* 查询菜单使用数量 }
*
* @param menuId 菜单ID /**
* @return 结果 * 是否存在菜单子节点
*/ *
@Override * @param menuId 菜单ID
public boolean checkMenuExistRole(Long menuId) * @return 结果
{ */
int result = roleMenuMapper.checkMenuExistRole(menuId); @Override
return result > 0 ? true : false; public boolean hasChildByMenuId(Long menuId)
} {
int result = menuMapper.hasChildByMenuId(menuId);
/** return result > 0 ? true : false;
* 新增保存菜单信息 }
*
* @param menu 菜单信息 /**
* @return 结果 * 查询菜单使用数量
*/ *
@Override * @param menuId 菜单ID
public int insertMenu(SysMenu menu) * @return 结果
{ */
return menuMapper.insertMenu(menu); @Override
} public boolean checkMenuExistRole(Long menuId)
{
/** int result = roleMenuMapper.checkMenuExistRole(menuId);
* 修改保存菜单信息 return result > 0 ? true : false;
* }
* @param menu 菜单信息
* @return 结果 /**
*/ * 新增保存菜单信息
@Override *
public int updateMenu(SysMenu menu) * @param menu 菜单信息
{ * @return 结果
return menuMapper.updateMenu(menu); */
} @Override
public int insertMenu(SysMenu menu)
/** {
* 删除菜单管理信息 return menuMapper.insertMenu(menu);
* }
* @param menuId 菜单ID
* @return 结果 /**
*/ * 修改保存菜单信息
@Override *
public int deleteMenuById(Long menuId) * @param menu 菜单信息
{ * @return 结果
return menuMapper.deleteMenuById(menuId); */
} @Override
public int updateMenu(SysMenu menu)
/** {
* 校验菜单名称是否唯一 return menuMapper.updateMenu(menu);
* }
* @param menu 菜单信息
* @return 结果 /**
*/ * 删除菜单管理信息
@Override *
public String checkMenuNameUnique(SysMenu menu) * @param menuId 菜单ID
{ * @return 结果
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); */
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); @Override
if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) public int deleteMenuById(Long menuId)
{ {
return UserConstants.NOT_UNIQUE; return menuMapper.deleteMenuById(menuId);
} }
return UserConstants.UNIQUE;
} /**
* 校验菜单名称是否唯一
/** *
* 获取路由名称 * @param menu 菜单信息
* * @return 结果
* @param menu 菜单信息 */
* @return 路由名称 @Override
*/ public String checkMenuNameUnique(SysMenu menu)
public String getRouteName(SysMenu menu) {
{ Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
String routerName = StringUtils.capitalize(menu.getPath()); SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
// 非外链并且是一级目录(类型为目录) if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue())
if (isMeunFrame(menu)) {
{ return UserConstants.NOT_UNIQUE;
routerName = StringUtils.EMPTY; }
} return UserConstants.UNIQUE;
return routerName; }
}
/**
/** * 获取路由名称
* 获取路由地址 *
* * @param menu 菜单信息
* @param menu 菜单信息 * @return 路由名称
* @return 路由地址 */
*/ public String getRouteName(SysMenu menu)
public String getRouterPath(SysMenu menu) {
{ String routerName = StringUtils.capitalize(menu.getPath());
String routerPath = menu.getPath(); // 非外链并且是一级目录(类型为目录)
// 非外链并且是一级目录(类型为目录) if (isMenuFrame(menu))
if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) {
&& UserConstants.NO_FRAME.equals(menu.getIsFrame())) routerName = StringUtils.EMPTY;
{ }
routerPath = "/" + menu.getPath(); return routerName;
} }
// 非外链并且是一级目录(类型为菜单)
else if (isMeunFrame(menu)) /**
{ * 获取路由地址
routerPath = "/"; *
} * @param menu 菜单信息
return routerPath; * @return 路由地址
} */
public String getRouterPath(SysMenu menu)
/** {
* 获取组件信息 String routerPath = menu.getPath();
* // 内链打开外网方式
* @param menu 菜单信息 if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
* @return 组件信息 {
*/ routerPath = StringUtils.replaceEach(routerPath, new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
public String getComponent(SysMenu menu) }
{ // 非外链并且是一级目录(类型为目录)
String component = UserConstants.LAYOUT; if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
if (StringUtils.isNotEmpty(menu.getComponent()) && !isMeunFrame(menu)) && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
{ {
component = menu.getComponent(); routerPath = "/" + menu.getPath();
} }
else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) // 非外链并且是一级目录(类型为菜单)
{ else if (isMenuFrame(menu))
component = UserConstants.PARENT_VIEW; {
} routerPath = "/";
return component; }
} return routerPath;
}
/**
* 是否为菜单内部跳转 /**
* * 获取组件信息
* @param menu 菜单信息 *
* @return 结果 * @param menu 菜单信息
*/ * @return 组件信息
public boolean isMeunFrame(SysMenu menu) */
{ public String getComponent(SysMenu menu)
return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) {
&& menu.getIsFrame().equals(UserConstants.NO_FRAME); String component = UserConstants.LAYOUT;
} if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
{
/** component = menu.getComponent();
* 是否为parent_view组件 }
* else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
* @param menu 菜单信息 {
* @return 结果 component = UserConstants.INNER_LINK;
*/ }
public boolean isParentView(SysMenu menu) else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
{ {
return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); component = UserConstants.PARENT_VIEW;
} }
return component;
/** }
* 根据父节点的ID获取所有子节点
* /**
* @param list 分类表 * 是否为菜单内部跳转
* @param parentId 传入的父节点ID *
* @return String * @param menu 菜单信息
*/ * @return 结果
public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) */
{ public boolean isMenuFrame(SysMenu menu)
List<SysMenu> returnList = new ArrayList<SysMenu>(); {
for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();) return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
{ && menu.getIsFrame().equals(UserConstants.NO_FRAME);
SysMenu t = (SysMenu) iterator.next(); }
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (t.getParentId() == parentId) /**
{ * 是否为内链组件
recursionFn(list, t); *
returnList.add(t); * @param menu 菜单信息
} * @return 结果
} */
return returnList; public boolean isInnerLink(SysMenu menu)
} {
return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
/** }
* 递归列表
* /**
* @param list * 是否为parent_view组件
* @param t *
*/ * @param menu 菜单信息
private void recursionFn(List<SysMenu> list, SysMenu t) * @return 结果
{ */
// 得到子节点列表 public boolean isParentView(SysMenu menu)
List<SysMenu> childList = getChildList(list, t); {
t.setChildren(childList); return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
for (SysMenu tChild : childList) }
{
if (hasChild(list, tChild)) /**
{ * 根据父节点的ID获取所有子节点
recursionFn(list, tChild); *
} * @param list 分类表
} * @param parentId 传入的父节点ID
} * @return String
*/
/** public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
* 得到子节点列表 {
*/ List<SysMenu> returnList = new ArrayList<SysMenu>();
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
{ {
List<SysMenu> tlist = new ArrayList<SysMenu>(); SysMenu t = (SysMenu) iterator.next();
Iterator<SysMenu> it = list.iterator(); // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
while (it.hasNext()) if (t.getParentId() == parentId)
{ {
SysMenu n = (SysMenu) it.next(); recursionFn(list, t);
if (n.getParentId().longValue() == t.getMenuId().longValue()) returnList.add(t);
{ }
tlist.add(n); }
} return returnList;
} }
return tlist;
} /**
* 递归列表
/** *
* 判断是否有子节点 * @param list
*/ * @param t
private boolean hasChild(List<SysMenu> list, SysMenu t) */
{ private void recursionFn(List<SysMenu> list, SysMenu t)
return getChildList(list, t).size() > 0 ? true : false; {
} // 得到子节点列表
} List<SysMenu> childList = getChildList(list, t);
t.setChildren(childList);
for (SysMenu tChild : childList)
{
if (hasChild(list, tChild))
{
recursionFn(list, tChild);
}
}
}
/**
* 得到子节点列表
*/
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
{
List<SysMenu> tlist = new ArrayList<SysMenu>();
Iterator<SysMenu> it = list.iterator();
while (it.hasNext())
{
SysMenu n = (SysMenu) it.next();
if (n.getParentId().longValue() == t.getMenuId().longValue())
{
tlist.add(n);
}
}
return tlist;
}
/**
* 判断是否有子节点
*/
private boolean hasChild(List<SysMenu> list, SysMenu t)
{
return getChildList(list, t).size() > 0 ? true : false;
}
}

View File

@ -16,6 +16,7 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysRoleDept; import com.ruoyi.system.domain.SysRoleDept;
import com.ruoyi.system.domain.SysRoleMenu; import com.ruoyi.system.domain.SysRoleMenu;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysRoleDeptMapper; import com.ruoyi.system.mapper.SysRoleDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper; import com.ruoyi.system.mapper.SysRoleMenuMapper;
@ -55,6 +56,31 @@ public class SysRoleServiceImpl implements ISysRoleService
return roleMapper.selectRoleList(role); return roleMapper.selectRoleList(role);
} }
/**
* 根据用户ID查询角色
*
* @param userId 用户ID
* @return 角色列表
*/
@Override
public List<SysRole> selectRolesByUserId(Long userId)
{
List<SysRole> userRoles = roleMapper.selectRolePermissionByUserId(userId);
List<SysRole> roles = selectRoleAll();
for (SysRole role : roles)
{
for (SysRole userRole : userRoles)
{
if (role.getRoleId().longValue() == userRole.getRoleId().longValue())
{
role.setFlag(true);
break;
}
}
}
return roles;
}
/** /**
* 根据用户ID查询权限 * 根据用户ID查询权限
* *
@ -325,4 +351,51 @@ public class SysRoleServiceImpl implements ISysRoleService
roleDeptMapper.deleteRoleDept(roleIds); roleDeptMapper.deleteRoleDept(roleIds);
return roleMapper.deleteRoleByIds(roleIds); return roleMapper.deleteRoleByIds(roleIds);
} }
/**
* 取消授权用户角色
*
* @param userRole 用户和角色关联信息
* @return 结果
*/
@Override
public int deleteAuthUser(SysUserRole userRole)
{
return userRoleMapper.deleteUserRoleInfo(userRole);
}
/**
* 批量取消授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要取消授权的用户数据ID
* @return 结果
*/
@Override
public int deleteAuthUsers(Long roleId, Long[] userIds)
{
return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
}
/**
* 批量选择授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要删除的用户数据ID
* @return 结果
*/
@Override
public int insertAuthUsers(Long roleId, Long[] userIds)
{
// 新增用户与角色管理
List<SysUserRole> list = new ArrayList<SysUserRole>();
for (Long userId : userIds)
{
SysUserRole ur = new SysUserRole();
ur.setUserId(userId);
ur.setRoleId(roleId);
list.add(ur);
}
return userRoleMapper.batchUserRole(list);
}
} }

View File

@ -66,6 +66,32 @@ public class SysUserServiceImpl implements ISysUserService
return userMapper.selectUserList(user); return userMapper.selectUserList(user);
} }
/**
* 根据条件分页查询已分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectAllocatedList(SysUser user)
{
return userMapper.selectAllocatedList(user);
}
/**
* 根据条件分页查询未分配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUnallocatedList(SysUser user)
{
return userMapper.selectUnallocatedList(user);
}
/** /**
* 通过用户名查询用户 * 通过用户名查询用户
* *
@ -242,6 +268,20 @@ public class SysUserServiceImpl implements ISysUserService
return userMapper.updateUser(user); return userMapper.updateUser(user);
} }
/**
* 用户授权角色
*
* @param userId 用户ID
* @param roleIds 角色组
*/
@Override
@Transactional
public void insertUserAuth(Long userId, Long[] roleIds)
{
userRoleMapper.deleteUserRoleByUserId(userId);
insertUserRole(userId, roleIds);
}
/** /**
* 修改用户状态 * 修改用户状态
* *
@ -356,6 +396,32 @@ public class SysUserServiceImpl implements ISysUserService
} }
} }
/**
* 新增用户角色信息
*
* @param userId 用户ID
* @param roleIds 角色组
*/
public void insertUserRole(Long userId, Long[] roleIds)
{
if (StringUtils.isNotNull(roleIds))
{
// 新增用户与角色管理
List<SysUserRole> list = new ArrayList<SysUserRole>();
for (Long roleId : roleIds)
{
SysUserRole ur = new SysUserRole();
ur.setUserId(userId);
ur.setRoleId(roleId);
list.add(ur);
}
if (list.size() > 0)
{
userRoleMapper.batchUserRole(list);
}
}
}
/** /**
* 通过用户ID删除用户 * 通过用户ID删除用户
* *

View File

@ -140,14 +140,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</update> </update>
<update id="updateDeptStatus" parameterType="SysDept"> <update id="updateDeptStatusNormal" parameterType="Long">
update sys_dept update sys_dept set status = '0' where dept_id in
<set> <foreach collection="array" item="deptId" open="(" separator="," close=")">
<if test="status != null and status != ''">status = #{status},</if> #{deptId}
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> </foreach>
update_time = sysdate()
</set>
where dept_id in (${ancestors})
</update> </update>
<delete id="deleteDeptById" parameterType="Long"> <delete id="deleteDeptById" parameterType="Long">

View File

@ -135,12 +135,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where role_id = #{roleId} where role_id = #{roleId}
</update> </update>
<update id="updateRoleStatus" parameterType="SysRole">
update sys_user set status = #{status} where user_id = #{userId}
</update>
<delete id="deleteRoleById" parameterType="Long"> <delete id="deleteRoleById" parameterType="Long">
delete from sys_role where role_id = #{roleId} update sys_role set del_flag = '2' where role_id = #{roleId}
</delete> </delete>
<delete id="deleteRoleByIds" parameterType="Long"> <delete id="deleteRoleByIds" parameterType="Long">

View File

@ -81,6 +81,41 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
${params.dataScope} ${params.dataScope}
</select> </select>
<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id
where u.del_flag = '0' and r.role_id = #{roleId}
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id
where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId})
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult"> <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/> <include refid="selectUserVo"/>
where u.user_name = #{userName} where u.user_name = #{userName}
@ -169,7 +204,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update> </update>
<delete id="deleteUserById" parameterType="Long"> <delete id="deleteUserById" parameterType="Long">
delete from sys_user where user_id = #{userId} update sys_user set del_flag = '2' where user_id = #{userId}
</delete> </delete>
<delete id="deleteUserByIds" parameterType="Long"> <delete id="deleteUserByIds" parameterType="Long">

View File

@ -1,3 +1,6 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
# 开发环境配置 # 开发环境配置
ENV = 'development' ENV = 'development'

View File

@ -1,3 +1,6 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'

View File

@ -1,3 +1,6 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
NODE_ENV = production NODE_ENV = production
# 测试环境配置 # 测试环境配置

View File

@ -1,6 +1,6 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.4.0", "version": "3.6.0",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",
@ -41,7 +41,7 @@
"clipboard": "2.0.6", "clipboard": "2.0.6",
"core-js": "3.8.1", "core-js": "3.8.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"element-ui": "2.15.0", "element-ui": "2.15.2",
"file-saver": "2.0.4", "file-saver": "2.0.4",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
@ -55,6 +55,7 @@
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "^2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0" "vuex": "3.6.0"

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title> <title><%= webpackConfig.name %></title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style> <style>
html, html,
body, body,

View File

@ -6,6 +6,14 @@
<script> <script>
export default { export default {
name: 'App' name: 'App',
metaInfo() {
return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
titleTemplate: title => {
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
}
}
}
} }
</script> </script>

View File

@ -51,10 +51,10 @@ export function delConfig(configId) {
}) })
} }
// 清理参数缓存 // 刷新参数缓存
export function clearCache() { export function refreshCache() {
return request({ return request({
url: '/system/config/clearCache', url: '/system/config/refreshCache',
method: 'delete' method: 'delete'
}) })
} }

View File

@ -43,10 +43,10 @@ export function delType(dictId) {
}) })
} }
// 清理参数缓存 // 刷新字典缓存
export function clearCache() { export function refreshCache() {
return request({ return request({
url: '/system/dict/type/clearCache', url: '/system/dict/type/refreshCache',
method: 'delete' method: 'delete'
}) })
} }

View File

@ -72,4 +72,49 @@ export function exportRole(query) {
method: 'get', method: 'get',
params: query params: query
}) })
}
// 查询角色已授权用户列表
export function allocatedUserList(query) {
return request({
url: '/system/role/authUser/allocatedList',
method: 'get',
params: query
})
}
// 查询角色未授权用户列表
export function unallocatedUserList(query) {
return request({
url: '/system/role/authUser/unallocatedList',
method: 'get',
params: query
})
}
// 取消用户授权角色
export function authUserCancel(data) {
return request({
url: '/system/role/authUser/cancel',
method: 'put',
data: data
})
}
// 批量取消用户授权角色
export function authUserCancelAll(data) {
return request({
url: '/system/role/authUser/cancelAll',
method: 'put',
params: data
})
}
// 授权用户选择
export function authUserSelectAll(data) {
return request({
url: '/system/role/authUser/selectAll',
method: 'put',
params: data
})
} }

View File

@ -125,3 +125,20 @@ export function importTemplate() {
method: 'get' method: 'get'
}) })
} }
// 查询授权角色
export function getAuthRole(userId) {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
})
}
// 保存授权角色
export function updateAuthRole(data) {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
})
}

View File

@ -1,84 +1,92 @@
// cover some element-ui styles // cover some element-ui styles
.el-breadcrumb__inner, .el-breadcrumb__inner,
.el-breadcrumb__inner a { .el-breadcrumb__inner a {
font-weight: 400 !important; font-weight: 400 !important;
} }
.el-upload { .el-upload {
input[type="file"] { input[type="file"] {
display: none !important; display: none !important;
} }
} }
.el-upload__input { .el-upload__input {
display: none; display: none;
} }
.cell { .cell {
.el-tag { .el-tag {
margin-right: 0px; margin-right: 0px;
} }
} }
.small-padding { .small-padding {
.cell { .cell {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
} }
.fixed-width { .fixed-width {
.el-button--mini { .el-button--mini {
padding: 7px 10px; padding: 7px 10px;
width: 60px; width: 60px;
} }
} }
.status-col { .status-col {
.cell { .cell {
padding: 0 10px; padding: 0 10px;
text-align: center; text-align: center;
.el-tag { .el-tag {
margin-right: 0px; margin-right: 0px;
} }
} }
} }
// to fixed https://github.com/ElemeFE/element/issues/2461 // to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog { .el-dialog {
transform: none; transform: none;
left: 0; left: 0;
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
} }
// refine element ui upload // refine element ui upload
.upload-container { .upload-container {
.el-upload { .el-upload {
width: 100%; width: 100%;
.el-upload-dragger { .el-upload-dragger {
width: 100%; width: 100%;
height: 200px; height: 200px;
} }
} }
} }
// dropdown // dropdown
.el-dropdown-menu { .el-dropdown-menu {
a { a {
display: block display: block
} }
} }
// fix date-picker ui bug in filter-item // fix date-picker ui bug in filter-item
.el-range-editor.el-input__inner { .el-range-editor.el-input__inner {
display: inline-flex !important; display: inline-flex !important;
} }
// to fix el-date-picker css style // to fix el-date-picker css style
.el-range-separator { .el-range-separator {
box-sizing: content-box; box-sizing: content-box;
} }
.el-menu--collapse
> div
> .el-submenu
> .el-submenu__title
.el-submenu__icon-arrow {
display: none;
}

View File

@ -53,6 +53,13 @@
margin-left: 20px; margin-left: 20px;
} }
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
font-family: inherit;
font-weight: 500;
line-height: 1.1;
color: inherit;
}
.el-dialog:not(.is-fullscreen){ .el-dialog:not(.is-fullscreen){
margin-top: 6vh !important; margin-top: 6vh !important;
} }
@ -105,13 +112,32 @@
position: absolute; position: absolute;
} }
@media ( max-width : 768px) {
.pagination-container .el-pagination > .el-pagination__jump {
display: none !important;
}
.pagination-container .el-pagination > .el-pagination__sizes {
display: none !important;
}
}
.el-table .fixed-width .el-button--mini { .el-table .fixed-width .el-button--mini {
color: #409EFF;
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
width: inherit; width: inherit;
} }
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #1890ff;
margin-left: 5px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
.el-tree-node__content > .el-checkbox { .el-tree-node__content > .el-checkbox {
margin-right: 8px; margin-right: 8px;
} }

View File

@ -135,9 +135,6 @@
margin-left: 20px; margin-left: 20px;
} }
.el-submenu__icon-arrow {
display: none;
}
} }
} }

View File

@ -0,0 +1,51 @@
<template>
<div>
<template v-for="(item, index) in options">
<template v-if="values.includes(item.dictValue)">
<span
v-if="item.listClass == 'default' || item.listClass == ''"
:key="item.dictValue"
:index="index"
:class="item.cssClass"
>{{ item.dictLabel }}</span
>
<el-tag
v-else
:key="item.dictValue"
:index="index"
:type="item.listClass == 'primary' ? '' : item.listClass"
:class="item.cssClass"
>
{{ item.dictLabel }}
</el-tag>
</template>
</template>
</div>
</template>
<script>
export default {
name: "DictTag",
props: {
options: {
type: Array,
default: null,
},
value: [String, Array],
},
computed: {
values() {
if (this.value) {
return Array.isArray(this.value) ? this.value : [this.value];
} else {
return [];
}
},
},
};
</script>
<style scoped>
.el-tag + .el-tag {
margin-left: 10px;
}
</style>

View File

@ -1,195 +1,262 @@
<template> <template>
<div class="editor" ref="editor" :style="styles"></div> <div>
</template> <el-upload
:action="uploadUrl"
<script> :on-success="handleUploadSuccess"
import Quill from "quill"; :on-error="handleUploadError"
import "quill/dist/quill.core.css"; name="file"
import "quill/dist/quill.snow.css"; :show-file-list="false"
import "quill/dist/quill.bubble.css"; :headers="headers"
style="display: none"
export default { ref="upload"
name: "Editor", v-if="this.type == 'url'"
props: { >
/* 编辑器的内容 */ </el-upload>
value: { <div class="editor" ref="editor" :style="styles"></div>
type: String, </div>
default: "", </template>
},
/* 高度 */ <script>
height: { import Quill from "quill";
type: Number, import "quill/dist/quill.core.css";
default: null, import "quill/dist/quill.snow.css";
}, import "quill/dist/quill.bubble.css";
/* 最小高度 */ import { getToken } from "@/utils/auth";
minHeight: {
type: Number, export default {
default: null, name: "Editor",
}, props: {
}, /* 编辑器的内容 */
data() { value: {
return { type: String,
Quill: null, default: "",
currentValue: "", },
options: { /* 高度 */
theme: "snow", height: {
bounds: document.body, type: Number,
debug: "warn", default: null,
modules: { },
// 工具栏配置 /* 最小高度 */
toolbar: [ minHeight: {
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线 type: Number,
["blockquote", "code-block"], // 引用 代码块 default: null,
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表 },
[{ indent: "-1" }, { indent: "+1" }], // 缩进 /* 只读 */
[{ size: ["small", false, "large", "huge"] }], // 字体大小 readOnly: {
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题 type: Boolean,
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色 default: false,
[{ align: [] }], // 对齐方式 },
["clean"], // 清除文本格式 /* 类型base64格式、url格式 */
["link", "image", "video"] // 链接、图片、视频 type: {
], type: String,
}, default: "url",
placeholder: "请输入内容", }
readOnly: false, },
}, data() {
}; return {
}, uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
computed: { headers: {
styles() { Authorization: "Bearer " + getToken()
let style = {}; },
if (this.minHeight) { Quill: null,
style.minHeight = `${this.minHeight}px`; currentValue: "",
} options: {
if (this.height) { theme: "snow",
style.height = `${this.height}px`; bounds: document.body,
} debug: "warn",
return style; modules: {
}, // 工具栏配置
}, toolbar: [
watch: { ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
value: { ["blockquote", "code-block"], // 引用 代码块
handler(val) { [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
if (val !== this.currentValue) { [{ indent: "-1" }, { indent: "+1" }], // 缩进
this.currentValue = val === null ? "" : val; [{ size: ["small", false, "large", "huge"] }], // 字体大小
if (this.Quill) { [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
this.Quill.pasteHTML(this.currentValue); [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
} [{ align: [] }], // 对齐方式
} ["clean"], // 清除文本格式
}, ["link", "image", "video"] // 链接、图片、视频
immediate: true, ],
}, },
}, placeholder: "请输入内容",
mounted() { readOnly: this.readOnly,
this.init(); },
}, };
beforeDestroy() { },
this.Quill = null; computed: {
}, styles() {
methods: { let style = {};
init() { if (this.minHeight) {
const editor = this.$refs.editor; style.minHeight = `${this.minHeight}px`;
this.Quill = new Quill(editor, this.options); }
this.Quill.pasteHTML(this.currentValue); if (this.height) {
this.Quill.on("text-change", (delta, oldDelta, source) => { style.height = `${this.height}px`;
const html = this.$refs.editor.children[0].innerHTML; }
const text = this.Quill.getText(); return style;
const quill = this.Quill; },
this.currentValue = html; },
this.$emit("input", html); watch: {
this.$emit("on-change", { html, text, quill }); value: {
}); handler(val) {
this.Quill.on("text-change", (delta, oldDelta, source) => { if (val !== this.currentValue) {
this.$emit("on-text-change", delta, oldDelta, source); this.currentValue = val === null ? "" : val;
}); if (this.Quill) {
this.Quill.on("selection-change", (range, oldRange, source) => { this.Quill.pasteHTML(this.currentValue);
this.$emit("on-selection-change", range, oldRange, source); }
}); }
this.Quill.on("editor-change", (eventName, ...args) => { },
this.$emit("on-editor-change", eventName, ...args); immediate: true,
}); },
}, },
}, mounted() {
}; this.init();
</script> },
beforeDestroy() {
<style> this.Quill = null;
.editor, .ql-toolbar { },
white-space: pre-wrap!important; methods: {
line-height: normal !important; init() {
} const editor = this.$refs.editor;
.quill-img { this.Quill = new Quill(editor, this.options);
display: none; // 如果设置了上传地址则自定义图片上传事件
} if (this.type == 'url') {
.ql-snow .ql-tooltip[data-mode="link"]::before { let toolbar = this.Quill.getModule("toolbar");
content: "请输入链接地址:"; toolbar.addHandler("image", (value) => {
} this.uploadType = "image";
.ql-snow .ql-tooltip.ql-editing a.ql-action::after { if (value) {
border-right: 0px; this.$refs.upload.$children[0].$refs.input.click();
content: "保存"; } else {
padding-right: 0px; this.quill.format("image", false);
} }
});
.ql-snow .ql-tooltip[data-mode="video"]::before { toolbar.addHandler("video", (value) => {
content: "请输入视频地址:"; this.uploadType = "video";
} if (value) {
this.$refs.upload.$children[0].$refs.input.click();
.ql-snow .ql-picker.ql-size .ql-picker-label::before, } else {
.ql-snow .ql-picker.ql-size .ql-picker-item::before { this.quill.format("video", false);
content: "14px"; }
} });
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, }
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { this.Quill.pasteHTML(this.currentValue);
content: "10px"; this.Quill.on("text-change", (delta, oldDelta, source) => {
} const html = this.$refs.editor.children[0].innerHTML;
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, const text = this.Quill.getText();
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { const quill = this.Quill;
content: "18px"; this.currentValue = html;
} this.$emit("input", html);
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, this.$emit("on-change", { html, text, quill });
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { });
content: "32px"; this.Quill.on("text-change", (delta, oldDelta, source) => {
} this.$emit("on-text-change", delta, oldDelta, source);
});
.ql-snow .ql-picker.ql-header .ql-picker-label::before, this.Quill.on("selection-change", (range, oldRange, source) => {
.ql-snow .ql-picker.ql-header .ql-picker-item::before { this.$emit("on-selection-change", range, oldRange, source);
content: "文本"; });
} this.Quill.on("editor-change", (eventName, ...args) => {
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, this.$emit("on-editor-change", eventName, ...args);
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { });
content: "标题1"; },
} handleUploadSuccess(res, file) {
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, // 获取富文本组件实例
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { let quill = this.Quill;
content: "标题2"; // 如果上传成功
} if (res.code == 200) {
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, // 获取光标所在位置
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { let length = quill.getSelection().index;
content: "标题3"; // 插入图片 res.url为服务器返回的图片地址
} quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName);
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, // 调整光标到最后
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { quill.setSelection(length + 1);
content: "标题4"; } else {
} this.$message.error("图片插入失败");
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, }
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { },
content: "标题5"; handleUploadError() {
} this.$message.error("图片插入失败");
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, },
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { },
content: "标题6"; };
} </script>
.ql-snow .ql-picker.ql-font .ql-picker-label::before, <style>
.ql-snow .ql-picker.ql-font .ql-picker-item::before { .editor, .ql-toolbar {
content: "标准字体"; white-space: pre-wrap !important;
} line-height: normal !important;
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, }
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { .quill-img {
content: "衬线字体"; display: none;
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, .ql-snow .ql-tooltip[data-mode="link"]::before {
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { content: "请输入链接地址:";
content: "等宽字体"; }
} .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
</style> border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";
}
</style>

View File

@ -4,7 +4,7 @@
:action="uploadFileUrl" :action="uploadFileUrl"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:file-list="fileList" :file-list="fileList"
:limit="1" :limit="limit"
:on-error="handleUploadError" :on-error="handleUploadError"
:on-exceed="handleExceed" :on-exceed="handleExceed"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
@ -26,8 +26,8 @@
<!-- 文件列表 --> <!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in list"> <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="file.url" :underline="false" target="_blank"> <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span> <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link> </el-link>
<div class="ele-upload-list__item-content-action"> <div class="ele-upload-list__item-content-action">
@ -42,9 +42,15 @@
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
export default { export default {
name: "FileUpload",
props: { props: {
// 值 // 值
value: [String, Object, Array], value: [String, Object, Array],
// 数量限制
limit: {
type: Number,
default: 5,
},
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
@ -63,6 +69,7 @@ export default {
}, },
data() { data() {
return { return {
baseUrl: process.env.VUE_APP_BASE_API,
uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: "Bearer " + getToken(),
@ -70,30 +77,35 @@ export default {
fileList: [], fileList: [],
}; };
}, },
watch: {
value: {
handler(val) {
if (val) {
let temp = 1;
// 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(',');
// 然后将数组转为对象数组
this.fileList = list.map(item => {
if (typeof item === "string") {
item = { name: item, url: item };
}
item.uid = item.uid || new Date().getTime() + temp++;
return item;
});
} else {
this.fileList = [];
return [];
}
},
deep: true,
immediate: true
}
},
computed: { computed: {
// 是否显示提示 // 是否显示提示
showTip() { showTip() {
return this.isShowTip && (this.fileType || this.fileSize); return this.isShowTip && (this.fileType || this.fileSize);
}, },
// 列表
list() {
let temp = 1;
if (this.value) {
// 首先将值转为数组
const list = Array.isArray(this.value) ? this.value : [this.value];
// 然后将数组转为对象数组
return list.map((item) => {
if (typeof item === "string") {
item = { name: item, url: item };
}
item.uid = item.uid || new Date().getTime() + temp++;
return item;
});
} else {
this.fileList = [];
return [];
}
},
}, },
methods: { methods: {
// 上传前校检格式和大小 // 上传前校检格式和大小
@ -126,7 +138,7 @@ export default {
}, },
// 文件个数超出 // 文件个数超出
handleExceed() { handleExceed() {
this.$message.error(`只允许上传单个文件`); this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
}, },
// 上传失败 // 上传失败
handleUploadError(err) { handleUploadError(err) {
@ -135,12 +147,13 @@ export default {
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
this.$message.success("上传成功"); this.$message.success("上传成功");
this.$emit("input", res.url); this.fileList.push({ name: res.fileName, url: res.fileName });
this.$emit("input", this.listToString(this.fileList));
}, },
// 删除文件 // 删除文件
handleDelete(index) { handleDelete(index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1);
this.$emit("input", ''); this.$emit("input", this.listToString(this.fileList));
}, },
// 获取文件名称 // 获取文件名称
getFileName(name) { getFileName(name) {
@ -149,11 +162,17 @@ export default {
} else { } else {
return ""; return "";
} }
},
// 对象转成指定字符串分隔
listToString(list, separator) {
let strs = "";
separator = separator || ",";
for (let i in list) {
strs += list[i].url + separator;
}
return strs != '' ? strs.substr(0, strs.length - 1) : '';
} }
}, }
created() {
this.fileList = this.list;
},
}; };
</script> </script>

View File

@ -70,9 +70,11 @@ export default {
this.show = false this.show = false
}, },
change(val) { change(val) {
const path = val.path;
if(this.ishttp(val.path)) { if(this.ishttp(val.path)) {
// http(s):// 路径新窗口打开 // http(s):// 路径新窗口打开
window.open(val.path, "_blank"); const pindex = path.indexOf("http");
window.open(path.substr(pindex, path.length), "_blank");
} else { } else {
this.$router.push(val.path) this.$router.push(val.path)
} }

View File

@ -5,33 +5,38 @@
list-type="picture-card" list-type="picture-card"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:limit="limit"
:on-error="handleUploadError" :on-error="handleUploadError"
:on-exceed="handleExceed"
name="file" name="file"
:show-file-list="false" :on-remove="handleRemove"
:show-file-list="true"
:headers="headers" :headers="headers"
style="display: inline-block; vertical-align: top" :file-list="fileList"
:on-preview="handlePictureCardPreview"
:class="{hide: this.fileList.length >= this.limit}"
> >
<el-image v-if="!value" :src="value"> <i class="el-icon-plus"></i>
<div slot="error" class="image-slot">
<i class="el-icon-plus" />
</div>
</el-image>
<div v-else class="image">
<el-image :src="value" :style="`width:150px;height:150px;`" fit="fill"/>
<div class="mask">
<div class="actions">
<span title="预览" @click.stop="dialogVisible = true">
<i class="el-icon-zoom-in" />
</span>
<span title="移除" @click.stop="removeImage">
<i class="el-icon-delete" />
</span>
</div>
</div>
</div>
</el-upload> </el-upload>
<el-dialog :visible.sync="dialogVisible" title="预览" width="800" append-to-body>
<img :src="value" style="display: block; max-width: 100%; margin: 0 auto;"> <!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip">
请上传
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
的文件
</div>
<el-dialog
:visible.sync="dialogVisible"
title="预览"
width="800"
append-to-body
>
<img
:src="dialogImageUrl"
style="display: block; max-width: 100%; margin: 0 auto"
/>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
@ -40,36 +45,128 @@
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
export default { export default {
props: {
value: [String, Object, Array],
// 图片数量限制
limit: {
type: Number,
default: 5,
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["png", "jpg", "jpeg"],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
}
},
data() { data() {
return { return {
dialogImageUrl: "",
dialogVisible: false, dialogVisible: false,
hideUpload: false,
baseUrl: process.env.VUE_APP_BASE_API,
uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: "Bearer " + getToken(),
}, },
fileList: []
}; };
}, },
props: { watch: {
value: { value: {
type: String, handler(val) {
default: "", if (val) {
// 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(',');
// 然后将数组转为对象数组
this.fileList = list.map(item => {
if (typeof item === "string") {
if (item.indexOf(this.baseUrl) === -1) {
item = { name: this.baseUrl + item, url: this.baseUrl + item };
} else {
item = { name: item, url: item };
}
}
return item;
});
} else {
this.fileList = [];
return [];
}
},
deep: true,
immediate: true
}
},
computed: {
// 是否显示提示
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
}, },
}, },
methods: { methods: {
removeImage() { // 删除图片
this.$emit("input", ""); handleRemove(file, fileList) {
const findex = this.fileList.indexOf(file.name);
this.fileList.splice(findex, 1);
this.$emit("input", this.listToString(this.fileList));
}, },
// 上传成功回调
handleUploadSuccess(res) { handleUploadSuccess(res) {
this.$emit("input", res.url); this.fileList.push({ name: res.fileName, url: res.fileName });
this.$emit("input", this.listToString(this.fileList));
this.loading.close(); this.loading.close();
}, },
handleBeforeUpload() { // 上传前loading加载
handleBeforeUpload(file) {
let isImg = false;
if (this.fileType.length) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
isImg = this.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
} else {
isImg = file.type.indexOf("image") > -1;
}
if (!isImg) {
this.$message.error(
`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
);
return false;
}
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
this.loading = this.$loading({ this.loading = this.$loading({
lock: true, lock: true,
text: "上传中", text: "上传中",
background: "rgba(0, 0, 0, 0.7)", background: "rgba(0, 0, 0, 0.7)",
}); });
}, },
// 文件个数超出
handleExceed() {
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
},
// 上传失败
handleUploadError() { handleUploadError() {
this.$message({ this.$message({
type: "error", type: "error",
@ -77,24 +174,37 @@ export default {
}); });
this.loading.close(); this.loading.close();
}, },
}, // 预览
watch: {}, handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
// 对象转成指定字符串分隔
listToString(list, separator) {
let strs = "";
separator = separator || ",";
for (let i in list) {
strs += list[i].url + separator;
}
return strs != '' ? strs.substr(0, strs.length - 1) : '';
}
}
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.image { // .el-upload--picture-card 控制加号部分
position: relative; ::v-deep.hide .el-upload--picture-card {
.mask { display: none;
opacity: 0;
position: absolute;
top: 0;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
transition: all 0.3s;
}
&:hover .mask {
opacity: 1;
}
} }
</style> // 去掉动画效果
::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {
transition: all 0s;
}
::v-deep .el-list-enter, .el-list-leave-active {
opacity: 0;
transform: translateY(0);
}
</style>

View File

@ -6,6 +6,7 @@
:page-size.sync="pageSize" :page-size.sync="pageSize"
:layout="layout" :layout="layout"
:page-sizes="pageSizes" :page-sizes="pageSizes"
:pager-count="pagerCount"
:total="total" :total="total"
v-bind="$attrs" v-bind="$attrs"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@ -38,6 +39,11 @@ export default {
return [10, 20, 30, 50] return [10, 20, 30, 50]
} }
}, },
// 移动端页码按钮的数量端默认值5
pagerCount: {
type: Number,
default: document.body.clientWidth < 992 ? 5 : 7
},
layout: { layout: {
type: String, type: String,
default: 'total, sizes, prev, pager, next, jumper' default: 'total, sizes, prev, pager, next, jumper'

View File

@ -43,7 +43,14 @@ export default {
type: Array, type: Array,
}, },
}, },
created() {
// 显隐列初始默认隐藏列
for (let item in this.columns) {
if (this.columns[item].visible === false) {
this.value.push(parseInt(item));
}
}
},
methods: { methods: {
// 搜索 // 搜索
toggleSearch() { toggleSearch() {

View File

@ -35,7 +35,6 @@ export default {
if (typeof val !== 'string') return if (typeof val !== 'string') return
const themeCluster = this.getThemeCluster(val.replace('#', '')) const themeCluster = this.getThemeCluster(val.replace('#', ''))
const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
console.log(themeCluster, originalCluster)
const $message = this.$message({ const $message = this.$message({
message: ' Compiling the theme', message: ' Compiling the theme',

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