194 Commits
v3.0 ... v3.3.0

Author SHA1 Message Date
8988d0b4ab 若依 3.3.0 2020-12-14 09:02:10 +08:00
ceefa20aa2 调整代码生成页列宽 2020-12-13 16:05:49 +08:00
89e1f2a53f 修改Set可能导致嵌套的问题 2020-12-13 15:01:03 +08:00
6800a12014 !138 修改Set可能导致嵌套的问题
Merge pull request !138 from BecomeDream/N/A
2020-12-13 14:54:17 +08:00
e8f63b2994 修改Set可能导致嵌套的问题 2020-12-11 18:16:57 +08:00
ecfe7006e2 代码生成预览支持高亮显示 2020-12-11 17:04:54 +08:00
9e387dc447 去除用户手机邮箱部门必填验证 2020-12-11 13:26:14 +08:00
231bbf6928 !135 增加日志记录过滤对象类型(解决多文件场景报错)
Merge pull request !135 from geruishi/master
2020-12-11 13:24:03 +08:00
d6eac2dc8d 前端更新插件版本 2020-12-11 09:27:12 +08:00
b368ad764f 升级core-js到最新版本3.8.1 2020-12-10 12:08:18 +08:00
ffd5f0ce5d 升级vue-router到最新版本3.4.9 2020-12-10 11:14:44 +08:00
a50beae599 代码生成预览提供滚动机制 2020-12-10 11:13:39 +08:00
cf7f51a633 解决多文件上传Log报错 2020-12-09 16:05:09 +08:00
4d46f4c1b5 删除用户和角色解绑关联 2020-12-09 10:32:53 +08:00
a941c1b488 !134 修改 代码生成 预览无法左右滑动
Merge pull request !134 from 〝走走停停/master
2020-12-09 10:27:34 +08:00
d6b6151aea update ruoyi-ui/src/assets/styles/ruoyi.scss. 2020-12-08 17:49:51 +08:00
fbc071a573 关闭页签清理缓存数据 2020-12-08 16:43:26 +08:00
6cfff90b4a 缓存仪表图设置默认大小 2020-12-08 16:13:21 +08:00
474cca921e 回显数据字典防止空值报错 2020-12-08 16:12:00 +08:00
1657e06be6 !132 update ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java.
Merge pull request !132 from abbfun/N/A
2020-12-08 16:03:51 +08:00
c01eeb8521 update ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java. 2020-12-08 11:11:34 +08:00
f90899d72a 支持主题风格配置 2020-12-07 14:13:02 +08:00
7e78a9167f 修改用户头像预览宽高 2020-12-06 16:22:45 +08:00
563e11d9c1 get请求params添加null值判断 2020-12-06 11:05:02 +08:00
ef92ad4d8c 支持get请求映射params参数 2020-12-04 10:52:20 +08:00
d8b006c15f 升级bitwalker到最新版本1.21 2020-12-04 10:51:20 +08:00
0e2b97a886 升级poi到最新版本4.1.2 2020-12-03 13:28:04 +08:00
1c7a5faae8 Excel支持注解align对齐方式 2020-12-03 13:26:46 +08:00
23868c4fad 防止安全扫描YUI出现的风险提示 2020-12-03 10:26:22 +08:00
3b2669d148 修改缓存监控内存单位 2020-11-30 19:27:03 +08:00
1147ea5f8a 设置用户头像悬停高度 2020-11-30 11:10:27 +08:00
a1bf5aaf8e 升级element-ui版本到2.14.1 2020-11-30 10:37:48 +08:00
2797c1eb3a 修正转换字符串的目标字符集属性 2020-11-30 10:31:11 +08:00
1791d7cf40 !126 update pom.xml.
Merge pull request !126 from abbfun/N/A
2020-11-30 10:07:08 +08:00
01861f0aae update pom.xml. 2020-11-29 16:16:54 +08:00
a69cc94f35 三级菜单自动配置组件 2020-11-28 20:39:03 +08:00
c666faed66 修复三级菜单之间切换页面无法缓存的问题 2020-11-28 20:31:45 +08:00
6072239a40 修改缓存监控内存单位 2020-11-28 13:57:19 +08:00
a3b86d6f6d 代码生成删除多余的数字float类型 2020-11-28 12:09:24 +08:00
fd831d5a90 Excel支持导入Boolean型数据 2020-11-28 12:08:55 +08:00
e83412b9a5 升级oshi到最新版本v5.3.6 2020-11-24 16:17:33 +08:00
90ac416e02 新增缓存监控功能 2020-11-23 10:02:50 +08:00
5b63f0cab9 优化头像样式,鼠标移入悬停遮罩 2020-11-19 09:33:10 +08:00
8f145bba3a 若依 v3.2.1 2020-11-18 09:32:15 +08:00
6bb166b89f 阻止任意文件下载漏洞 2020-11-17 10:29:52 +08:00
823e95667e 代码生成支持上传控件 2020-11-16 16:20:17 +08:00
566053da0c 新增图片上传组件 2020-11-16 15:52:58 +08:00
0ef007240d 调整默认首页 2020-11-07 10:38:35 +08:00
0a75dcdd85 升级druid到最新版本v1.2.2 2020-11-05 13:58:36 +08:00
4c2626ffec 2020年双十一云服务器优惠,错过又要等一年 2020-11-04 16:58:28 +08:00
082b19e33a mapperLocations配置支持分隔符 2020-11-02 17:34:52 +08:00
b779cf053d !112 未选择时,点击“确认”,出现必填验证提示。使用blur的话,选择之后验证消息不会自动消失,使用change会自动消失。
Merge pull request !112 from FlyFive/N/A
2020-11-02 17:30:06 +08:00
212012dc62 未选择时,点击“确认”,出现必填验证提示。使用blur的话,选择之后验证消息不会自动消失,使用change会自动消失。 2020-11-02 11:49:25 +08:00
7de2cf77b4 !111 update ruoyi-ui/src/views/system/dept/index.vue.
Merge pull request !111 from FlyFive/N/A
2020-10-26 16:57:58 +08:00
2b9d46439f update ruoyi-ui/src/views/system/dept/index.vue.
验证的提示信息错了
2020-10-26 16:31:51 +08:00
79265d59b7 !109 误修改,回退
Merge pull request !109 from tucke/master
2020-10-26 10:00:46 +08:00
093ba5b389 误修改,回退 2020-10-26 09:53:58 +08:00
3807b11290 权限调整 2020-10-23 17:27:20 +08:00
c9f25cb34e 调整sql默认时间 2020-10-21 11:30:37 +08:00
203b54e5aa !106 update ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java.
Merge pull request !106 from abbfun/N/A
2020-10-14 17:12:57 +08:00
403f5c5dcf 解决代码生成没有bit类型的问题 2020-10-14 17:08:20 +08:00
c6d0b9a9ae update ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java.
权限字符串修正
2020-10-14 16:21:43 +08:00
08df2c93a9 删除不必要的代码 2020-10-13 14:41:26 +08:00
fbbdd94999 !105 update ruoyi-ui/src/views/system/role/index.vue.
Merge pull request !105 from FlyFive/N/A
2020-10-13 14:38:02 +08:00
0cae7d0058 update ruoyi-ui/src/views/system/role/index.vue.
getMenuAllCheckedKeys()方法中选中节点和半选节点获取的方法反了。
2020-10-12 13:50:25 +08:00
b0965653bf 删除不必要的代码 2020-10-10 17:54:30 +08:00
e472f62523 升级pagehelper到最新版1.3.0 2020-10-10 16:39:14 +08:00
69256940df 若依 3.2 2020-10-10 09:38:21 +08:00
b9f686be53 升级druid到最新版本v1.2.1 2020-10-09 11:45:33 +08:00
521ff51238 升级fastjson到最新版1.2.74 2020-10-09 11:45:06 +08:00
f67c97e095 !102 rouyi.js中添加日期范围方法dateRange获取bug修复
Merge pull request !102 from zora/master
2020-10-09 11:37:18 +08:00
dd721ff894 修正定时任务执行一次权限标识 2020-10-07 13:36:55 +08:00
ae4290bdda 修复页签关闭所有固定标签路由不刷新问题 2020-10-03 20:05:24 +08:00
c19fec2cf8 格式化代码 2020-10-03 20:05:06 +08:00
669c42795a 表单构建布局型组件新增按钮 2020-10-03 17:47:24 +08:00
0d79f10c2f jna指定版本 2020-10-03 11:43:23 +08:00
d3595cd930 修正菜单提示信息错误 2020-10-03 11:15:18 +08:00
5b0525d05c [修改]此工具类应使用参数dateRange而非bind在model上的dateRange 2020-09-27 13:22:23 +08:00
fb07677c32 左侧菜单文字过长显示省略号 2020-09-24 19:21:55 +08:00
a82a3d9465 升级oshi到最新版本v5.2.5 2020-09-22 18:25:58 +08:00
28bceda630 修正文字错误 2020-09-22 11:09:18 +08:00
69829827fe 菜单&数据权限新增(展开/折叠 全选/全不选 父子联动) 2020-09-21 14:10:01 +08:00
89607fb028 !100 解决添加用户角色时报错问题
Merge pull request !100 from wensanpi/master
2020-09-21 10:31:59 +08:00
1aa18c523d update ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml. 2020-09-20 17:38:21 +08:00
abeb8d7fd8 菜单新增是否缓存keep-alive 2020-09-20 10:34:03 +08:00
478fae0d28 菜单&数据权限新增(展开/折叠 全选/全不选 父子联动) 2020-09-19 13:42:37 +08:00
0ecf27f8d6 去除多余的空格 2020-09-18 17:09:27 +08:00
0a5bb34fbf 升级springboot到2.1.17 提升安全性 2020-09-18 16:51:27 +08:00
9e38c7de2e 代码生成支持同步数据库 2020-09-18 10:24:21 +08:00
9ca28d6dbf 表格操作列间距调整 2020-09-18 10:23:31 +08:00
497f98ba90 导入excel整形值校验优化 2020-09-17 18:22:50 +08:00
a948affb2d 代码生成支持富文本控件 2020-09-15 15:53:27 +08:00
57b49dd5fa 限制系统内置参数不允许删除 2020-09-15 15:51:12 +08:00
9c0ed9c424 修复通知公告longblob类型乱码问题 2020-09-10 18:23:12 +08:00
70ab18052c 富文本工具栏样式对齐 2020-09-10 16:56:33 +08:00
aeb02c79d8 修正注释图标路径 2020-09-10 16:53:58 +08:00
33793d8eff Excel导出类型NUMERIC支持精度浮点类型 2020-09-09 11:30:34 +08:00
9652906954 降级druid到版本v1.1.22,防止出现一些错误 2020-09-09 10:08:31 +08:00
9fccc7de40 修正调用目标字符串最大长度 2020-09-07 16:40:38 +08:00
599be64fa8 升级jjwt到0.9.1 2020-09-07 16:40:21 +08:00
50ac363682 升级druid到最新版本v1.1.23 2020-09-04 14:47:07 +08:00
f84b157419 !87 数据权限中的空值处理
Merge pull request !87 from sproutcat/master
2020-09-04 14:17:32 +08:00
f4536d5d2e !86 数据字典缓存处理的一点小问题
Merge pull request !86 from 说一/master
2020-09-04 14:07:47 +08:00
aed958b1be !82 修复Editor组件在传入内容为null时无法响应式更新其内容的bug
Merge pull request !82 from HaoRan/N/A
2020-09-04 14:04:08 +08:00
tzg
0a51f7d743 空值处理 2020-09-02 14:59:10 +08:00
3fd9147afb 解决“在只填加了字典类型,没有添加字典数据时,会出现缓存了空集合,即使后边添加了字典数据也没用,只能清空redis缓存。”的问题,小问题就是判断稍稍改了下,若依大大让我pr当个贡献者,很荣幸很欣慰。感谢! 2020-09-02 10:14:34 +08:00
4f86b6d9ca 修改公告内容字段类型 2020-09-01 18:07:59 +08:00
a65c287075 修复Editor组件无法对响应式更新null值问题 2020-08-31 02:10:01 +08:00
1af0d1665c 数据权限判断对象类型 2020-08-28 15:45:54 +08:00
4e32788b36 修正数据库字符串类型nvarchar 2020-08-28 14:11:32 +08:00
068c3e6f0d 优化递归子节点 2020-08-28 10:14:59 +08:00
dd6640086e 代码生成树模板去掉多余双引号 2020-08-27 17:34:06 +08:00
be54188ba6 导出Excel调整targetAttr获取值方法,防止get方法不规范 2020-08-26 15:39:46 +08:00
a4e2339f90 生成页面时不忽略remark属性 2020-08-26 14:24:37 +08:00
bf771ae5c8 Excel注解支持自动统计数据总和 2020-08-26 11:37:49 +08:00
fa5596bb20 Editor组件优化,支持自定义高度&图片冲突问题 2020-08-22 13:18:41 +08:00
eb30fc4b1a 修改公告内容字段类型 2020-08-22 13:11:40 +08:00
0446d211df 设置默认排序顺序 2020-08-19 17:02:23 +08:00
da146c2a70 Excel注解支持设置BigDecimal精度&舍入规则 2020-08-19 11:20:31 +08:00
7de5358dcd 升级fastjson到最新版1.2.73 2020-08-19 11:17:24 +08:00
549c7ee97a 代码生成添加select必填选项 2020-08-18 18:15:12 +08:00
5fcf342f5a 修改sass为node-sass,避免el-icon图标乱码 2020-08-18 17:36:20 +08:00
c89722a7dd !74 update ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java.
Merge pull request !74 from Lyy/N/A
2020-08-18 17:30:18 +08:00
61e10f2783 !73 代码生成:select的表单验证失效
Merge pull request !73 from sunshine/master
2020-08-18 17:30:03 +08:00
c6912ca1d5 !64 修改sass为node-sass,避免el-icon图标乱码
Merge pull request !64 from 心悦李国楠/dev-心悦
2020-08-18 17:27:19 +08:00
5c4f0c5503 !65 根节点为子部门时,树状结构显示问题
Merge pull request !65 from GSTong/master
2020-08-18 17:21:51 +08:00
Lyy
4f7702b22a update ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java.
修改注释,CRSF禁用
2020-08-17 17:05:33 +08:00
04e294b3e5 代码生成:select的表单验证失效 2020-08-17 12:08:34 +08:00
d596d5bb8e 还原 addDateRange js 函数 2020-08-13 12:08:24 +08:00
8f9f0c04cc 若依 3.1 2020-08-13 10:27:56 +08:00
1bad003fe3 修改公私钥 2020-08-12 11:55:26 +08:00
ad4df6245d 优化防重复提交拦截器,请求没有消息头则使用地址 2020-08-11 11:24:55 +08:00
gst
0070297fe1 根节点为子部门时,树状结构显示问题 2020-08-11 10:59:02 +08:00
71ec44a545 修正在线用户日志记录类型 2020-08-10 17:26:11 +08:00
1efae4a588 优化防重复提交拦截器,接口请求非json数据不获取Body消息体 2020-08-10 17:10:34 +08:00
650359c357 修改sass为node-sass,避免el-icon图标乱码 2020-08-10 16:28:50 +08:00
a78211ca00 优化上级菜单不能选择自己 2020-08-10 12:20:52 +08:00
74f52677be 表格右侧工具栏组件 2020-08-10 10:12:39 +08:00
60d5c03e65 !63 重写表格工具栏右侧添加刷新&显隐查询栏
Merge pull request !63 from 平凡/重写表格工具栏右侧添加刷新&显隐查询栏
2020-08-10 09:53:27 +08:00
5b04f388e9 重写表格工具栏右侧添加刷新&显隐查询栏 2020-08-09 11:07:10 +08:00
a7eb07c7a0 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue 2020-08-07 16:07:02 +08:00
d0b315f4a5 删除重复的placeholder 2020-08-07 16:03:45 +08:00
a6051d4638 !60 代码注释错误
Merge pull request !60 from waylon/master
2020-08-07 15:56:44 +08:00
c4ee9ea7c8 修复注释错误 2020-08-07 14:26:30 +08:00
7c39f92538 修复富文本空格和缩进保存后不生效问题 2020-08-07 12:26:15 +08:00
51fa66f61a 唯一限制条件只返回单条数据 2020-08-05 14:28:45 +08:00
3b61ed56b0 添加获取当前的环境配置方法 2020-08-05 12:56:32 +08:00
db904f679e !57 若干 ruoyi-ui 前端公共工具函数优化
Merge pull request !57 from FungLeo/master
2020-08-05 11:39:56 +08:00
98982515f7 !55 修复在线用户判断逻辑
Merge pull request !55 from 心悦李国楠/dev-心悦
2020-08-05 11:39:09 +08:00
1a7baa0639 !58 cell的cellType由Numeric修正为String
Merge pull request !58 from 4ook/master
2020-08-05 11:38:44 +08:00
a9695d1756 修复BUG: 导出Excel功能, 当attr的cellType为String时, cell的cellType由Numeric修正为String。 2020-08-05 11:28:57 +08:00
d78f642201 Merge remote-tracking branch 'upstream/master' 2020-08-05 10:26:05 +08:00
26dfee2ce8 彻底重写回显数据字典方法 2020-08-05 10:24:54 +08:00
b56898858d 超时登录后页面跳转到首页 2020-08-05 10:04:43 +08:00
503dd64e3f 优化 addDateRange js 函数 2020-08-04 14:32:29 +08:00
876ecf21c7 优化构建树形数据JS方法 2020-08-04 14:11:02 +08:00
107672419e Merge remote-tracking branch 'upstream/master' 2020-08-04 11:59:42 +08:00
21d07c1d71 修复角色的权限分配后,未实时生效问题 2020-08-04 11:51:25 +08:00
d8d636fdbd 优化 回显数据字典(字符串数组)JS 函数 2020-08-04 11:39:43 +08:00
743fce7829 优化防重提交唯一标识 2020-08-04 11:07:37 +08:00
de2ac66f0b 修复在线用户判断逻辑 2020-08-03 17:57:33 +08:00
8b5d254242 全局异常状态汉化拦截处理 2020-08-03 09:11:49 +08:00
a7eb0f98ac README 2020-08-03 09:02:28 +08:00
4dcf737db0 表格工具栏右侧添加刷新&显隐查询栏 2020-08-01 15:45:38 +08:00
b32d0724b7 升级vue-cli版本到4.4.4 2020-07-31 22:35:30 +08:00
8deacb702e !54 update ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml.
Merge pull request !54 from yongdaidai/N/A
2020-07-31 16:50:28 +08:00
5be8d46d05 !51 优化生成vue文件的vm模板文件
Merge pull request !51 from FungLeo/master
2020-07-31 16:49:51 +08:00
fb19dd3e4e update ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml.
解决如果导入多个同名部门dept_name,parent_id相同,但是删除状态(del_flag)不同,导致查询结果为多条,mybatis不能映射为一条数据的问题.
2020-07-31 14:59:23 +08:00
cbf4795fd5 表单类型为Integer/Long设置整形默认值 2020-07-30 21:47:50 +08:00
5d74ed32bd 表单类型为Integer/Long设置整形默认值 2020-07-30 16:03:44 +08:00
6afaced3cf !53 update ruoyi-ui/src/views/system/role/index.vue.
Merge pull request !53 from abbfun/N/A
2020-07-30 10:04:11 +08:00
f3976c0792 update ruoyi-ui/src/views/system/role/index.vue.
权限修正(角色导出权限)
2020-07-29 21:16:53 +08:00
22225a5119 HTML过滤器改为将html转义 2020-07-28 17:28:09 +08:00
fe030cc022 修改 node-sass 为 dart-sass 2020-07-27 16:55:51 +08:00
ca657b0482 优化 index-tree.vue.vm 文件,undefined 修改为 null 2020-07-26 17:33:42 +08:00
c1d1ace36d 优化index.vue.vm模板,!=1修改为严格不等;undefined修改为null 2020-07-26 17:29:40 +08:00
6e7d7aba93 代码生成支持自定义路径 2020-07-24 15:37:57 +08:00
388e36ed4d 优化参数 2020-07-23 21:45:22 +08:00
5d89d0b36a !49 代码生成器默认mapper路径与默认mapperScan路径不一致
Merge pull request !49 from HaoRan/master
2020-07-23 21:25:10 +08:00
55095a50b5 !48 ExcelUtil 功能优化
Merge pull request !48 from soulCoke/master
2020-07-23 21:25:02 +08:00
ee4b4de7b1 修复 代码生成器默认mapper路径与默认mapperScan路径不一致的bug 2020-07-23 21:01:18 +08:00
92c6301285 Excel支持分割字符串组内容 2020-07-23 18:58:45 +08:00
5c6adb25fc 代码生成支持复选框 2020-07-23 17:02:55 +08:00
8dd3ca5bb6 excel 导入数字不需要格式化 ,导入允许列和属性个数不一致。 2020-07-23 15:54:03 +08:00
be778ba370 修复参数注释 2020-07-23 14:54:11 +08:00
52d48fa63e 检查字符支持小数点&降级改成异常提醒 2020-07-23 11:29:40 +08:00
df3ef54b41 验证码类型支持(数组计算、字符验证) 2020-07-23 11:17:04 +08:00
1e40e60dbf 支持CORS跨域请求 2020-07-22 15:25:42 +08:00
133a10ecf2 !47 修复和优化前端 utils 工具函数
Merge pull request !47 from FungLeo/master
2020-07-22 13:00:51 +08:00
6a84ae42a5 代码生成支持选择上级菜单 2020-07-21 15:52:11 +08:00
b2d79b62d1 代码生成支持选择上级菜单 2020-07-21 11:21:20 +08:00
a09a342f58 优化 uitls/ruoyi.js 中 selectDictLabel 方法,数组迭代器换为 some
提高性能
2020-07-21 10:22:07 +08:00
3e1bd8e3bc 修复 utils/index.js 中不包含 parseTime 函数的 bug 2020-07-21 10:18:56 +08:00
8a076e175f Excel导出导入支持dictType字典类型 2020-07-20 15:25:05 +08:00
161 changed files with 4226 additions and 1358 deletions

3
.gitignore vendored
View File

@ -37,7 +37,8 @@ nbdist/
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
!*/build/*.xml

View File

@ -6,9 +6,10 @@
* 支持加载动态权限菜单,多方式轻松权限控制。
* 高效率开发,使用代码生成器可以一键生成前后端代码。
* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link)腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)  
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
## 内置功能
@ -46,27 +47,27 @@
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr>
<tr>

43
pom.xml
View File

@ -6,29 +6,31 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.0.0</version>
<version>3.3.0</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>3.0.0</ruoyi.version>
<ruoyi.version>3.3.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.boot.version>1.3.2</mybatis.boot.version>
<druid.version>1.1.14</druid.version>
<bitwalker.version>1.19</bitwalker.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<druid.version>1.2.2</druid.version>
<bitwalker.version>1.21</bitwalker.version>
<swagger.version>2.9.2</swagger.version>
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
<fastjson.version>1.2.70</fastjson.version>
<oshi.version>3.9.1</oshi.version>
<kaptcha.version>2.3.2</kaptcha.version>
<pagehelper.boot.version>1.3.0</pagehelper.boot.version>
<fastjson.version>1.2.74</fastjson.version>
<oshi.version>5.3.6</oshi.version>
<jna.version>5.6.0</jna.version>
<commons.io.version>2.5</commons.io.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version>
<poi.version>3.17</poi.version>
<poi.version>4.1.2</poi.version>
<velocity.version>1.7</velocity.version>
<jwt.version>0.9.0</jwt.version>
<jwt.version>0.9.1</jwt.version>
</properties>
<!-- 依赖声明 -->
@ -39,7 +41,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<version>2.1.18.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -71,6 +73,18 @@
<artifactId>oshi-core</artifactId>
<version>${oshi.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
<!-- swagger2-->
<dependency>
@ -137,6 +151,13 @@
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!--验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!-- 定时任务-->
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.0.0</version>
<version>3.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
@ -95,7 +95,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>

View File

@ -1,16 +1,20 @@
package com.ruoyi.web.controller.common;
import java.io.ByteArrayOutputStream;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.VerifyCodeUtils;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
@ -22,8 +26,18 @@ import com.ruoyi.common.utils.uuid.IdUtils;
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
// 验证码类型
@Value("${ruoyi.captchaType}")
private String captchaType;
/**
* 生成验证码
@ -31,32 +45,42 @@ public class CaptchaController
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
// 生成随机字串
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
// 唯一标识
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
redisCache.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 生成图片
int w = 111, h = 36;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
VerifyCodeUtils.outputImage(w, h, stream, verifyCode);
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
AjaxResult ajax = AjaxResult.success();
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(stream.toByteArray()));
return ajax;
ImageIO.write(image, "jpg", os);
}
catch (Exception e)
catch (IOException e)
{
e.printStackTrace();
return AjaxResult.error(e.getMessage());
}
finally
{
stream.close();
}
AjaxResult ajax = AjaxResult.success();
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
}
}

View File

@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@ -41,17 +42,15 @@ public class CommonController
{
try
{
if (!FileUtils.isValidFilename(fileName))
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
String filePath = RuoYiConfig.getDownloadPath() + fileName;
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition",
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName);
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
@ -92,18 +91,28 @@ public class CommonController
* 本地资源通用下载
*/
@GetMapping("/common/download/resource")
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
throws Exception
{
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
// 数据库资源地址
String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
// 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition",
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
FileUtils.writeBytes(downloadPath, response.getOutputStream());
try
{
if (!FileUtils.checkAllowDownload(resource))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
}
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
// 数据库资源地址
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
// 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, downloadName);
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
}

View File

@ -0,0 +1,53 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
/**
* 缓存监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/cache")
public class CacheController
{
@Autowired
private RedisTemplate<String, String> redisTemplate;
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping()
public AjaxResult getInfo() throws Exception
{
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
Map<String, Object> result = new HashMap<>(3);
result.put("info", info);
result.put("dbSize", dbSize);
List<Map<String, String>> pieList = new ArrayList<>();
commandStats.stringPropertyNames().forEach(key -> {
Map<String, String> data = new HashMap<>(2);
String property = commandStats.getProperty(key);
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
pieList.add(data);
});
result.put("commandStats", pieList);
return AjaxResult.success(result);
}
}

View File

@ -4,7 +4,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Server;
@ -15,7 +14,7 @@ import com.ruoyi.framework.web.domain.Server;
*/
@RestController
@RequestMapping("/monitor/server")
public class ServerController extends BaseController
public class ServerController
{
@PreAuthorize("@ss.hasPermi('monitor:server:list')")
@GetMapping()

View File

@ -38,18 +38,18 @@ public class SysLogininforController extends BaseController
return getDataTable(list);
}
@Log(title = "日志", businessType = BusinessType.EXPORT)
@Log(title = "日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@GetMapping("/export")
public AjaxResult export(SysLogininfor logininfor)
{
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
return util.exportExcel(list, "日志");
return util.exportExcel(list, "日志");
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "日志", businessType = BusinessType.DELETE)
@Log(title = "日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds)
{
@ -57,7 +57,7 @@ public class SysLogininforController extends BaseController
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "日志", businessType = BusinessType.CLEAN)
@Log(title = "日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean")
public AjaxResult clean()
{

View File

@ -82,7 +82,7 @@ public class SysUserOnlineController extends BaseController
* 强退用户
*/
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.DELETE)
@Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId)
{

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@ -19,6 +20,7 @@ import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
@ -73,7 +75,12 @@ public class SysDictDataController extends BaseController
@GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType)
{
return AjaxResult.success(dictTypeService.selectDictDataByType(dictType));
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data))
{
data = new ArrayList<SysDictData>();
}
return AjaxResult.success(data);
}
/**

View File

@ -126,7 +126,11 @@ public class SysMenuController extends BaseController
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
menu.setUpdateBy(SecurityUtils.getUsername());
return toAjax(menuService.updateMenu(menu));

View File

@ -17,11 +17,17 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
* 角色信息
@ -35,6 +41,15 @@ public class SysRoleController extends BaseController
@Autowired
private ISysRoleService roleService;
@Autowired
private TokenService tokenService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private ISysUserService userService;
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role)
@ -103,7 +118,20 @@ public class SysRoleController extends BaseController
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setUpdateBy(SecurityUtils.getUsername());
return toAjax(roleService.updateRole(role));
if (roleService.updateRole(role) > 0)
{
// 更新缓存用户权限
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
tokenService.setLoginUser(loginUser);
}
return AjaxResult.success();
}
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
}
/**

View File

@ -127,11 +127,13 @@ public class SysUserController extends BaseController
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
else if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
@ -149,11 +151,13 @@ public class SysUserController extends BaseController
public AjaxResult edit(@Validated @RequestBody SysUser user)
{
userService.checkUserAllowed(user);
if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
@ -175,7 +179,7 @@ public class SysUserController extends BaseController
/**
* 重置密码
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
public AjaxResult resetPwd(@RequestBody SysUser user)

View File

@ -3,15 +3,17 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.0.0
version: 3.3.0
# 版权年份
copyrightYear: 2019
copyrightYear: 2020
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数组计算 char 字符验证
captchaType: math
# 开发环境配置
server:

View File

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

View File

@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
/**
* 自定义导出Excel数据注解
@ -29,11 +30,31 @@ public @interface Excel
*/
public String dateFormat() default "";
/**
* 如果是字典类型请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
public String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型0数字 1字符串
*/
@ -79,6 +100,32 @@ public @interface Excel
*/
public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 导出字段对齐方式0默认1靠左2居中3靠右
*/
Align align() default Align.AUTO;
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 字段类型0导出导入1仅导出2仅导入
*/
@ -115,4 +162,4 @@ public @interface Excel
return this.value;
}
}
}
}

View File

@ -61,6 +61,11 @@ public class Constants
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 验证码有效期(分钟)

View File

@ -22,8 +22,14 @@ public class GenConstants
/** 树名称字段 */
public static final String TREE_NAME = "treeName";
/** 上级菜单ID字段 */
public static final String PARENT_MENU_ID = "parentMenuId";
/** 上级菜单名称字段 */
public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2", "tinytext", "text",
"mediumtext", "longtext" };
/** 数据库时间类型 */
@ -31,7 +37,7 @@ public class GenConstants
/** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bigint", "float", "float", "double", "decimal" };
"bit", "bigint", "float", "double", "decimal" };
/** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
@ -68,6 +74,12 @@ public class GenConstants
/** 日期控件 */
public static final String HTML_DATETIME = "datetime";
/** 上传控件 */
public static final String HTML_UPLOAD_IMAGE = "uploadImage";
/** 富文本控件 */
public static final String HTML_EDITOR = "editor";
/** 字符串类型 */
public static final String TYPE_STRING = "String";

View File

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

View File

@ -5,7 +5,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* Entity基类
@ -36,14 +35,6 @@ public class BaseEntity implements Serializable
/** 备注 */
private String remark;
/** 开始时间 */
@JsonIgnore
private String beginTime;
/** 结束时间 */
@JsonIgnore
private String endTime;
/** 请求参数 */
private Map<String, Object> params;
@ -107,26 +98,6 @@ public class BaseEntity implements Serializable
this.remark = remark;
}
public String getBeginTime()
{
return beginTime;
}
public void setBeginTime(String beginTime)
{
this.beginTime = beginTime;
}
public String getEndTime()
{
return endTime;
}
public void setEndTime(String endTime)
{
this.endTime = endTime;
}
public Map<String, Object> getParams()
{
if (params == null)

View File

@ -41,6 +41,9 @@ public class SysMenu extends BaseEntity
/** 是否为外链0是 1否 */
private String isFrame;
/** 是否缓存0缓存 1不缓存 */
private String isCache;
/** 类型M目录 C菜单 F按钮 */
private String menuType;
@ -144,6 +147,16 @@ public class SysMenu extends BaseEntity
this.isFrame = isFrame;
}
public String getIsCache()
{
return isCache;
}
public void setIsCache(String isCache)
{
this.isCache = isCache;
}
@NotBlank(message = "菜单类型不能为空")
public String getMenuType()
{
@ -216,6 +229,7 @@ public class SysMenu extends BaseEntity
.append("path", getPath())
.append("component", getComponent())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())
.append("visible", getVisible())
.append("status ", getStatus())

View File

@ -37,6 +37,12 @@ public class SysRole extends BaseEntity
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限")
private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 */
private boolean deptCheckStrictly;
/** 角色状态0正常 1停用 */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
@ -128,6 +134,26 @@ public class SysRole extends BaseEntity
this.dataScope = dataScope;
}
public boolean isMenuCheckStrictly()
{
return menuCheckStrictly;
}
public void setMenuCheckStrictly(boolean menuCheckStrictly)
{
this.menuCheckStrictly = menuCheckStrictly;
}
public boolean isDeptCheckStrictly()
{
return deptCheckStrictly;
}
public void setDeptCheckStrictly(boolean deptCheckStrictly)
{
this.deptCheckStrictly = deptCheckStrictly;
}
public String getStatus()
{
return status;
@ -186,6 +212,8 @@ public class SysRole extends BaseEntity
.append("roleKey", getRoleKey())
.append("roleSort", getRoleSort())
.append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())

View File

@ -68,12 +68,12 @@ public class SysUser extends BaseEntity
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 最后登IP */
@Excel(name = "最后登IP", type = Type.EXPORT)
/** 最后登IP */
@Excel(name = "最后登IP", type = Type.EXPORT)
private String loginIp;
/** 最后登时间 */
@Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
/** 最后登时间 */
@Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate;
/** 部门对象 */

View File

@ -22,7 +22,7 @@ public class LoginUser implements UserDetails
private String token;
/**
* 登时间
* 登时间
*/
private Long loginTime;

View File

@ -18,8 +18,8 @@ public class PageDomain
/** 排序列 */
private String orderByColumn;
/** 排序的方向 "desc" 或者 "asc". */
private String isAsc;
/** 排序的方向desc或者asc */
private String isAsc = "asc";
public String getOrderBy()
{

View File

@ -1,11 +1,13 @@
package com.ruoyi.common.core.redis;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@ -13,7 +15,7 @@ import org.springframework.stereotype.Component;
/**
* spring redis 工具类
*
*
* @author ruoyi
**/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@ -109,7 +111,7 @@ public class RedisCache
* 缓存List数据
*
* @param key 缓存的键值
* @param values 待缓存的List数据
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
@ -136,10 +138,15 @@ public class RedisCache
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> long setCacheSet(final String key, final Set<T> dataSet)
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
Long count = redisTemplate.opsForSet().add(key, dataSet);
return count == null ? 0 : count;
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
@ -216,7 +223,7 @@ public class RedisCache
/**
* 获得缓存的基本对象列表
*
*
* @param pattern 字符串前缀
* @return 对象列表
*/

View File

@ -66,7 +66,7 @@ public class CharsetKit
if (null == destCharset)
{
srcCharset = StandardCharsets.UTF_8;
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))

View File

@ -2,7 +2,6 @@ package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.List;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
@ -15,6 +14,11 @@ import com.ruoyi.common.utils.spring.SpringUtils;
*/
public class DictUtils
{
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/**
* 设置字典缓存
*
@ -37,12 +41,116 @@ public class DictUtils
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj))
{
List<SysDictData> DictDatas = StringUtils.cast(cacheObj);
return DictDatas;
List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
return dictDatas;
}
return null;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue)
{
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel)
{
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String value : dictValue.split(separator))
{
if (value.equals(dict.getDictValue()))
{
propertyString.append(dict.getDictLabel() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictValue.equals(dict.getDictValue()))
{
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
{
for (SysDictData dict : datas)
{
for (String label : dictLabel.split(separator))
{
if (label.equals(dict.getDictLabel()))
{
propertyString.append(dict.getDictValue() + separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictLabel.equals(dict.getDictLabel()))
{
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 清空字典缓存
*/

View File

@ -0,0 +1,47 @@
package com.ruoyi.common.utils.file;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
/**
* 文件类型工具类
*
* @author ruoyi
*/
public class FileTypeUtils
{
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param file 文件名
* @return 后缀(不含".")
*/
public static String getFileType(File file)
{
if (null == file)
{
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName)
{
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0)
{
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
}

View File

@ -15,7 +15,7 @@ import com.ruoyi.common.utils.uuid.IdUtils;
/**
* 文件上传工具类
*
*
* @author ruoyi
*/
public class FileUploadUtils
@ -89,7 +89,7 @@ public class FileUploadUtils
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param extension 上传文件类型
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
@ -215,7 +215,7 @@ public class FileUploadUtils
/**
* 获取文件名的后缀
*
*
* @param file 表单文件
* @return 后缀名
*/
@ -228,4 +228,4 @@ public class FileUploadUtils
}
return extension;
}
}
}

View File

@ -7,14 +7,18 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* 文件处理工具类
*
* @author ruoyi
*/
public class FileUtils
public class FileUtils extends org.apache.commons.io.FileUtils
{
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
@ -104,6 +108,30 @@ public class FileUtils
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StringUtils.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
/**
* 下载文件名重新编码
*
@ -111,8 +139,7 @@ public class FileUtils
* @param fileName 文件名
* @return 编码后的文件名
*/
public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
throws UnsupportedEncodingException
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
{
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
@ -139,4 +166,38 @@ public class FileUtils
}
return filename;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
* @return
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.setHeader("Content-disposition", contentDispositionValue.toString());
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException
{
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
}

View File

@ -144,7 +144,10 @@ public class EscapeUtil
public static void main(String[] args)
{
String html = "alert('11111');";
String html = "<script>alert(1);</script>";
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123";
// String html = "123>";
System.out.println(EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html));
System.out.println(EscapeUtil.unescape(html));

View File

@ -131,7 +131,7 @@ public final class HTMLFilter
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
alwaysMakeTags = false;
}
/**
@ -208,7 +208,7 @@ public final class HTMLFilter
s = processRemoveBlanks(s);
s = validateEntities(s);
// s = validateEntities(s);
return s;
}
@ -245,6 +245,7 @@ public final class HTMLFilter
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
// 不追加结束标签
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);

View File

@ -6,7 +6,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
@ -16,9 +15,9 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
@ -50,6 +49,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
@ -102,6 +102,16 @@ public class ExcelUtil<T>
*/
private List<Object[]> fields;
/**
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 实体对象
*/
@ -199,7 +209,10 @@ public class ExcelUtil<T>
// 设置类的私有字段属性可访问.
field.setAccessible(true);
Integer column = cellMap.get(attr.name());
fieldsMap.put(column, field);
if (column != null)
{
fieldsMap.put(column, field);
}
}
}
for (int i = 1; i < rows; i++)
@ -229,19 +242,19 @@ public class ExcelUtil<T>
val = Convert.toStr(val);
}
}
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
{
val = Convert.toInt(val);
}
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
else if (Long.TYPE == fieldType || Long.class == fieldType)
{
val = Convert.toLong(val);
}
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
else if (Double.TYPE == fieldType || Double.class == fieldType)
{
val = Convert.toDouble(val);
}
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
else if (Float.TYPE == fieldType || Float.class == fieldType)
{
val = Convert.toFloat(val);
}
@ -260,6 +273,10 @@ public class ExcelUtil<T>
val = DateUtil.getJavaDate((Double) val);
}
}
else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
{
val = Convert.toBool(val, false);
}
if (StringUtils.isNotNull(fieldType))
{
Excel attr = field.getAnnotation(Excel.class);
@ -270,7 +287,11 @@ public class ExcelUtil<T>
}
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
{
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
@ -334,6 +355,7 @@ public class ExcelUtil<T>
if (Type.EXPORT.equals(type))
{
fillExcelData(index, row);
addStatisticsRow();
}
}
String filename = encodingFilename(sheetName);
@ -440,6 +462,30 @@ public class ExcelUtil<T>
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font totalFont = wb.createFont();
totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10);
style.setFont(totalFont);
styles.put("total", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
return styles;
}
@ -469,13 +515,11 @@ public class ExcelUtil<T>
{
if (ColumnType.STRING == attr.cellType())
{
cell.setCellType(CellType.NUMERIC);
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
}
else if (ColumnType.NUMERIC == attr.cellType())
{
cell.setCellType(CellType.NUMERIC);
cell.setCellValue(Integer.parseInt(value + ""));
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
}
}
@ -523,25 +567,37 @@ public class ExcelUtil<T>
{
// 创建cell
cell = row.createCell(column);
cell.setCellStyle(styles.get("data"));
int align = attr.align().value();
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp();
String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
}
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{
cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
}
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
}
else
{
// 设置列类型
setCellVo(value, attr, cell);
}
addStatisticsData(column, Convert.toStr(value), attr);
}
}
catch (Exception e)
@ -613,28 +669,36 @@ public class ExcelUtil<T>
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
* @throws Exception
*/
public static String convertByExp(String propertyValue, String converterExp) throws Exception
public static String convertByExp(String propertyValue, String converterExp, String separator)
{
try
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[0].equals(value))
{
propertyString.append(itemArray[1] + separator);
break;
}
}
}
else
{
String[] itemArray = item.split("=");
if (itemArray[0].equals(propertyValue))
{
return itemArray[1];
}
}
}
catch (Exception e)
{
throw e;
}
return propertyValue;
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
@ -642,28 +706,109 @@ public class ExcelUtil<T>
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
* @throws Exception
*/
public static String reverseByExp(String propertyValue, String converterExp) throws Exception
public static String reverseByExp(String propertyValue, String converterExp, String separator)
{
try
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[1].equals(value))
{
propertyString.append(itemArray[0] + separator);
break;
}
}
}
else
{
String[] itemArray = item.split("=");
if (itemArray[1].equals(propertyValue))
{
return itemArray[0];
}
}
}
catch (Exception e)
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public static String convertDictByExp(String dictValue, String dictType, String separator)
{
return DictUtils.getDictLabel(dictType, dictValue, separator);
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典值
*/
public static String reverseDictByExp(String dictLabel, String dictType, String separator)
{
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/**
* 合计统计信息
*/
private void addStatisticsData(Integer index, String text, Excel entity)
{
if (entity != null && entity.isStatistics())
{
throw e;
Double temp = 0D;
if (!statistics.containsKey(index))
{
statistics.put(index, temp);
}
try
{
temp = Double.valueOf(text);
}
catch (NumberFormatException e)
{
}
statistics.put(index, statistics.get(index) + temp);
}
}
/**
* 创建统计行
*/
public void addStatisticsRow()
{
if (statistics.size() > 0)
{
Cell cell = null;
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
Set<Integer> keys = statistics.keySet();
cell = row.createCell(0);
cell.setCellStyle(styles.get("total"));
cell.setCellValue("合计");
for (Integer key : keys)
{
cell = row.createCell(key);
cell.setCellStyle(styles.get("total"));
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
}
statistics.clear();
}
return propertyValue;
}
/**
@ -732,12 +877,12 @@ public class ExcelUtil<T>
*/
private Object getValue(Object o, String name) throws Exception
{
if (StringUtils.isNotEmpty(name))
if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
{
Class<?> clazz = o.getClass();
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method method = clazz.getMethod(methodName);
o = method.invoke(o);
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
o = field.get(o);
}
return o;
}
@ -832,10 +977,10 @@ public class ExcelUtil<T>
Cell cell = row.getCell(column);
if (StringUtils.isNotNull(cell))
{
if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA)
if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
{
val = cell.getNumericCellValue();
if (HSSFDateUtil.isCellDateFormatted(cell))
if (DateUtil.isCellDateFormatted(cell))
{
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
}
@ -843,7 +988,7 @@ public class ExcelUtil<T>
{
if ((Double) val % 1 > 0)
{
val = new DecimalFormat("0.00").format(val);
val = new BigDecimal(val.toString());
}
else
{
@ -851,15 +996,15 @@ public class ExcelUtil<T>
}
}
}
else if (cell.getCellTypeEnum() == CellType.STRING)
else if (cell.getCellType() == CellType.STRING)
{
val = cell.getStringCellValue();
}
else if (cell.getCellTypeEnum() == CellType.BOOLEAN)
else if (cell.getCellType() == CellType.BOOLEAN)
{
val = cell.getBooleanCellValue();
}
else if (cell.getCellTypeEnum() == CellType.ERROR)
else if (cell.getCellType() == CellType.ERROR)
{
val = cell.getErrorCellValue();
}

View File

@ -204,6 +204,10 @@ public class ReflectUtils
args[i] = DateUtil.getJavaDate((Double) args[i]);
}
}
else if (cs[i] == boolean.class || cs[i] == Boolean.class)
{
args[i] = Convert.toBool(args[i]);
}
}
}
return (E) method.invoke(obj, args);

View File

@ -5,7 +5,10 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
/**
* spring工具类 方便在非spring管理环境中获取bean
@ -13,17 +16,25 @@ import org.springframework.stereotype.Component;
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
@ -111,4 +122,25 @@ public final class SpringUtils implements BeanFactoryPostProcessor
{
return (T) AopContext.currentProxy();
}
/**
* 获取当前的环境配置无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile()
{
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.common.utils.sql;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.StringUtils;
/**
@ -10,9 +11,9 @@ import com.ruoyi.common.utils.StringUtils;
public class SqlUtil
{
/**
* 仅支持字母、数字、下划线、空格、逗号(支持多个字段排序)
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,]+";
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 检查字符,防止注入绕过
@ -21,7 +22,7 @@ public class SqlUtil
{
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
return StringUtils.EMPTY;
throw new BaseException("参数不符合规范,不能进行查询");
}
return value;
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.0.0</version>
<version>3.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -35,22 +35,24 @@
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<exclusions>
<exclusion>
<artifactId>javax.servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 获取系统信息 -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>

View File

@ -20,7 +20,7 @@ import com.ruoyi.framework.web.service.TokenService;
/**
* 数据过滤处理
*
*
* @author ruoyi
*/
@Aspect
@ -79,11 +79,11 @@ public class DataScopeAspect
}
// 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
SysUser currentUser = loginUser.getUser();
if (currentUser != null)
if (StringUtils.isNotNull(loginUser))
{
SysUser currentUser = loginUser.getUser();
// 如果是超级管理员,则不过滤数据
if (!currentUser.isAdmin())
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias());
@ -93,10 +93,10 @@ public class DataScopeAspect
/**
* 数据范围过滤
*
*
* @param joinPoint 切点
* @param user 用户
* @param alias 别名
* @param userAlias 别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{
@ -142,8 +142,12 @@ public class DataScopeAspect
if (StringUtils.isNotBlank(sqlString.toString()))
{
BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0];
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}

View File

@ -1,6 +1,8 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -210,8 +212,31 @@ public class LogAspect
* @param o 对象信息。
* @return 如果是需要过滤的对象则返回true否则返回false。
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object o)
{
Class<?> clazz = o.getClass();
if (clazz.isArray())
{
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
}
else if (Collection.class.isAssignableFrom(clazz))
{
Collection collection = (Collection) o;
for (Iterator iter = collection.iterator(); iter.hasNext();)
{
return iter.next() instanceof MultipartFile;
}
}
else if (Map.class.isAssignableFrom(clazz))
{
Map map = (Map) o;
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
return entry.getValue() instanceof MultipartFile;
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
}
}

View File

@ -0,0 +1,83 @@
package com.ruoyi.framework.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import static com.google.code.kaptcha.Constants.*;
/**
* 验证码配置
*
* @author ruoyi
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@ -0,0 +1,75 @@
package com.ruoyi.framework.config;
import java.util.Random;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
* 验证码文本生成器
*
* @author ruoyi
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.framework.config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.sql.DataSource;
@ -21,6 +22,7 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* Mybatis支持*匹配扫描包
@ -89,6 +91,28 @@ public class MyBatisConfig
return typeAliasesPackage;
}
public Resource[] resolveMapperLocations(String[] mapperLocations)
{
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<Resource>();
if (mapperLocations != null)
{
for (String mapperLocation : mapperLocations)
{
try
{
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
}
catch (IOException e)
{
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
{
@ -101,7 +125,7 @@ public class MyBatisConfig
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
return sessionFactory.getObject();
}

View File

@ -1,7 +1,11 @@
package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -39,4 +43,24 @@ public class ResourcesConfig implements WebMvcConfigurer
{
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
}
/**
* 跨域配置
*/
@Bean
public CorsFilter corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置访问源地址
config.addAllowedOrigin("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 对接口配置跨域设置
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

View File

@ -12,6 +12,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
@ -47,6 +49,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@Autowired
private CorsFilter corsFilter;
/**
* 解决 无法直接注入 AuthenticationManager
@ -80,7 +88,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
// CRSF禁用因为不使用session
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
@ -112,6 +120,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}

View File

@ -13,7 +13,7 @@ import com.ruoyi.common.utils.ServletUtils;
/**
* 防止重复提交拦截器
*
*
* @author ruoyi
*/
@Component
@ -46,8 +46,8 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*
* @param httpServletRequest
*
* @param request
* @return
* @throws Exception
*/

View File

@ -5,8 +5,10 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.StringUtils;
@ -26,7 +28,9 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
public final String REPEAT_TIME = "repeatTime";
public final String CACHE_REPEAT_KEY = "repeatData";
// 令牌自定义标识
@Value("${token.header}")
private String header;
@Autowired
private RedisCache redisCache;
@ -47,8 +51,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
@Override
public boolean isRepeatSubmit(HttpServletRequest request)
{
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
String nowParams = HttpHelper.getBodyString(repeatedlyRequest);
String nowParams = "";
if (request instanceof RepeatedlyRequestWrapper)
{
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
nowParams = HttpHelper.getBodyString(repeatedlyRequest);
}
// body参数为空获取Parameter的数据
if (StringUtils.isEmpty(nowParams))
@ -62,7 +70,17 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
// 请求地址作为存放cache的key值
String url = request.getRequestURI();
Object sessionObj = redisCache.getCacheObject(CACHE_REPEAT_KEY);
// 唯一值(没有消息头则使用请求地址)
String submitKey = request.getHeader(header);
if (StringUtils.isEmpty(submitKey))
{
submitKey = url;
}
// 唯一标识指定key + 消息头)
String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cache_repeat_key);
if (sessionObj != null)
{
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
@ -77,7 +95,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
}
Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(CACHE_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS);
redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS);
return false;
}

View File

@ -25,7 +25,7 @@ public class AsyncFactory
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
/**
* 记录登信息
* 记录登信息
*
* @param username 用户名
* @param status 状态

View File

@ -189,7 +189,7 @@ public class Server
private void setSysFiles(OperatingSystem os)
{
FileSystem fileSystem = os.getFileSystem();
OSFileStore[] fsArray = fileSystem.getFileStores();
List<OSFileStore> fsArray = fileSystem.getFileStores();
for (OSFileStore fs : fsArray)
{
long free = fs.getUsableSpace();

View File

@ -109,7 +109,7 @@ public class PermissionService
for (SysRole sysRole : loginUser.getUser().getRoles())
{
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(StringUtils.trim(role)))
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
{
return true;
}

View File

@ -22,7 +22,7 @@ import io.jsonwebtoken.SignatureAlgorithm;
/**
* token验证处理
*
*
* @author ruoyi
*/
@Component
@ -51,7 +51,7 @@ public class TokenService
/**
* 获取用户身份信息
*
*
* @return 用户信息
*/
public LoginUser getLoginUser(HttpServletRequest request)
@ -95,7 +95,7 @@ public class TokenService
/**
* 创建令牌
*
*
* @param loginUser 用户信息
* @return 令牌
*/
@ -113,8 +113,8 @@ public class TokenService
/**
* 验证令牌有效期相差不足20分钟自动刷新缓存
*
* @param token 令牌
*
* @param loginUser
* @return 令牌
*/
public void verifyToken(LoginUser loginUser)
@ -129,7 +129,7 @@ public class TokenService
/**
* 刷新令牌有效期
*
*
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser)
@ -140,10 +140,10 @@ public class TokenService
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
/**
* 设置用户代理信息
*
*
* @param loginUser 登录信息
*/
public void setUserAgent(LoginUser loginUser)
@ -155,7 +155,7 @@ public class TokenService
loginUser.setBrowser(userAgent.getBrowser().getName());
loginUser.setOs(userAgent.getOperatingSystem().getName());
}
/**
* 从数据声明生成令牌
*

View File

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

View File

@ -148,15 +148,39 @@ public class GenController extends BaseController
}
/**
* 生成代码
* 生成代码(下载方式)
*/
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/download/{tableName}")
public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
{
byte[] data = genTableService.downloadCode(tableName);
genCode(response, data);
}
/**
* 生成代码(自定义路径)
*/
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/genCode/{tableName}")
public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
public AjaxResult genCode(@PathVariable("tableName") String tableName)
{
byte[] data = genTableService.generatorCode(tableName);
genCode(response, data);
genTableService.generatorCode(tableName);
return AjaxResult.success();
}
/**
* 同步数据库
*/
@PreAuthorize("@ss.hasPermi('tool:gen:edit')")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@GetMapping("/synchDb/{tableName}")
public AjaxResult synchDb(@PathVariable("tableName") String tableName)
{
genTableService.synchDb(tableName);
return AjaxResult.success();
}
/**
@ -168,7 +192,7 @@ public class GenController extends BaseController
public void batchGenCode(HttpServletResponse response, String tables) throws IOException
{
String[] tableNames = Convert.toStrArray(tables);
byte[] data = genTableService.generatorCode(tableNames);
byte[] data = genTableService.downloadCode(tableNames);
genCode(response, data);
}
@ -178,9 +202,11 @@ public class GenController extends BaseController
private void genCode(HttpServletResponse response, byte[] data) throws IOException
{
response.reset();
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream());
}
}
}

View File

@ -55,6 +55,12 @@ public class GenTable extends BaseEntity
@NotBlank(message = "作者不能为空")
private String functionAuthor;
/** 生成代码方式0zip压缩包 1自定义路径 */
private String genType;
/** 生成路径(不填默认项目路径) */
private String genPath;
/** 主键信息 */
private GenTableColumn pkColumn;
@ -74,6 +80,12 @@ public class GenTable extends BaseEntity
/** 树名称字段 */
private String treeName;
/** 上级菜单ID字段 */
private String parentMenuId;
/** 上级菜单名称字段 */
private String parentMenuName;
public Long getTableId()
{
return tableId;
@ -174,6 +186,26 @@ public class GenTable extends BaseEntity
this.functionAuthor = functionAuthor;
}
public String getGenType()
{
return genType;
}
public void setGenType(String genType)
{
this.genType = genType;
}
public String getGenPath()
{
return genPath;
}
public void setGenPath(String genPath)
{
this.genPath = genPath;
}
public GenTableColumn getPkColumn()
{
return pkColumn;
@ -234,6 +266,26 @@ public class GenTable extends BaseEntity
this.treeName = treeName;
}
public String getParentMenuId()
{
return parentMenuId;
}
public void setParentMenuId(String parentMenuId)
{
this.parentMenuId = parentMenuId;
}
public String getParentMenuName()
{
return parentMenuName;
}
public void setParentMenuName(String parentMenuName)
{
this.parentMenuName = parentMenuName;
}
public boolean isTree()
{
return isTree(this.tplCategory);
@ -268,4 +320,4 @@ public class GenTable extends BaseEntity
}
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
}
}
}

View File

@ -59,7 +59,7 @@ public class GenTableColumn extends BaseEntity
/** 查询方式EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围 */
private String queryType;
/** 显示类型input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件 */
/** 显示类型input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、upload上传控件、editor富文本控件 */
private String htmlType;
/** 字典类型 */
@ -340,7 +340,7 @@ public class GenTableColumn extends BaseEntity
public static boolean isUsableColumn(String javaField)
{
// isSuperColumn()中的名单用于避免生成多余Domain属性若某些属性在生成页面时需要用到不能忽略则放在此处白名单
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum");
return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
}
public String readConverterExp()

View File

@ -17,7 +17,7 @@ public interface GenTableColumnMapper
* @return 列信息
*/
public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
/**
* 查询业务字段列表
*
@ -42,6 +42,14 @@ public interface GenTableColumnMapper
*/
public int updateGenTableColumn(GenTableColumn genTableColumn);
/**
* 删除业务字段
*
* @param genTableColumns 列数据
* @return 结果
*/
public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
/**
* 批量删除业务字段
*

View File

@ -1,11 +1,13 @@
package com.ruoyi.generator.service;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
@ -21,9 +23,11 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.text.CharsetKit;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.mapper.GenTableColumnMapper;
@ -202,13 +206,13 @@ public class GenTableServiceImpl implements IGenTableService
}
/**
* 生成代码
* 生成代码(下载方式)
*
* @param tableName 表名称
* @return 数据
*/
@Override
public byte[] generatorCode(String tableName)
public byte[] downloadCode(String tableName)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
@ -218,13 +222,85 @@ public class GenTableServiceImpl implements IGenTableService
}
/**
* 批量生成代码
* 生成代码(自定义路径)
*
* @param tableName 表名称
*/
@Override
public void generatorCode(String tableName)
{
// 查询表信息
GenTable table = genTableMapper.selectGenTableByName(tableName);
// 查询列信息
List<GenTableColumn> columns = table.getColumns();
setPkColumn(table, columns);
VelocityInitializer.initVelocity();
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates)
{
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
{
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try
{
String path = getGenPath(table, template);
FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
}
catch (IOException e)
{
throw new CustomException("渲染模板失败,表名:" + table.getTableName());
}
}
}
}
/**
* 同步数据库
*
* @param tableName 表名称
*/
@Override
@Transactional
public void synchDb(String tableName)
{
GenTable table = genTableMapper.selectGenTableByName(tableName);
List<GenTableColumn> tableColumns = table.getColumns();
List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
dbTableColumns.forEach(column -> {
if (!tableColumnNames.contains(column.getColumnName()))
{
GenUtils.initColumnField(column, table);
genTableColumnMapper.insertGenTableColumn(column);
}
});
List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
if (StringUtils.isNotEmpty(delColumns))
{
genTableColumnMapper.deleteGenTableColumns(delColumns);
}
}
/**
* 批量生成代码(下载方式)
*
* @param tableNames 表数组
* @return 数据
*/
@Override
public byte[] generatorCode(String[] tableNames)
public byte[] downloadCode(String[] tableNames)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
@ -337,9 +413,31 @@ public class GenTableServiceImpl implements IGenTableService
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
genTable.setTreeCode(treeCode);
genTable.setTreeParentCode(treeParentCode);
genTable.setTreeName(treeName);
genTable.setParentMenuId(parentMenuId);
genTable.setParentMenuName(parentMenuName);
}
}
}
/**
* 获取代码生成地址
*
* @param table 业务表信息
* @param template 模板文件路径
* @return 生成地址
*/
public static String getGenPath(GenTable table, String template)
{
String genPath = table.getGenPath();
if (StringUtils.equals(genPath, "/"))
{
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
}
return genPath + File.separator + VelocityUtils.getFileName(template, table);
}
}

View File

@ -75,20 +75,35 @@ public interface IGenTableService
public Map<String, String> previewCode(Long tableId);
/**
* 生成代码
* 生成代码(下载方式)
*
* @param tableName 表名称
* @return 数据
*/
public byte[] generatorCode(String tableName);
public byte[] downloadCode(String tableName);
/**
* 批量生成代码
* 生成代码(自定义路径)
*
* @param tableName 表名称
* @return 数据
*/
public void generatorCode(String tableName);
/**
* 同步数据库
*
* @param tableName 表名称
*/
public void synchDb(String tableName);
/**
* 批量生成代码(下载方式)
*
* @param tableNames 表数组
* @return 数据
*/
public byte[] generatorCode(String[] tableNames);
public byte[] downloadCode(String[] tableNames);
/**
* 修改保存参数校验

View File

@ -111,6 +111,16 @@ public class GenUtils
{
column.setHtmlType(GenConstants.HTML_SELECT);
}
// 文件字段设置上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
{
column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE);
}
// 内容字段设置富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{
column.setHtmlType(GenConstants.HTML_EDITOR);
}
}
/**
@ -195,7 +205,7 @@ public class GenUtils
/**
* 关键字替换
*
* @param name 需要被替换的名字
* @param text 需要被替换的名字
* @return 替换后的名字
*/
public static String replaceText(String text)

View File

@ -12,7 +12,7 @@ import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
/**
* 代码生成模板处理
* 模板处理工具类
*
* @author ruoyi
*/
@ -24,9 +24,12 @@ public class VelocityUtils
/** mybatis空间路径 */
private static final String MYBATIS_PATH = "main/resources/mapper";
/** 默认上级菜单,系统工具 */
private static final String DEFAULT_PARENT_MENU_ID = "3";
/**
* 设置模板变量信息
*
*
* @return 模板列表
*/
public static VelocityContext prepareContext(GenTable genTable)
@ -55,6 +58,7 @@ public class VelocityUtils
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
velocityContext.put("columns", genTable.getColumns());
velocityContext.put("table", genTable);
setMenuVelocityContext(velocityContext, genTable);
if (GenConstants.TPL_TREE.equals(tplCategory))
{
setTreeVelocityContext(velocityContext, genTable);
@ -62,6 +66,14 @@ public class VelocityUtils
return velocityContext;
}
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
{
String options = genTable.getOptions();
JSONObject paramsObj = JSONObject.parseObject(options);
String parentMenuId = getParentMenuId(paramsObj);
context.put("parentMenuId", parentMenuId);
}
public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
{
String options = genTable.getOptions();
@ -86,7 +98,7 @@ public class VelocityUtils
/**
* 获取模板信息
*
*
* @return 模板列表
*/
public static List<String> getTemplateList(String tplCategory)
@ -176,7 +188,7 @@ public class VelocityUtils
/**
* 获取包前缀
*
*
* @param packageName 包名称
* @return 包前缀名称
*/
@ -189,8 +201,8 @@ public class VelocityUtils
/**
* 根据列类型获取导入包
*
* @param column 列集合
*
* @param columns 列集合
* @return 返回需要导入的包列表
*/
public static HashSet<String> getImportList(List<GenTableColumn> columns)
@ -213,7 +225,7 @@ public class VelocityUtils
/**
* 获取权限前缀
*
*
* @param moduleName 模块名称
* @param businessName 业务名称
* @return 返回权限前缀
@ -221,13 +233,27 @@ public class VelocityUtils
public static String getPermissionPrefix(String moduleName, String businessName)
{
return StringUtils.format("{}:{}", moduleName, businessName);
}
/**
* 获取上级菜单ID字段
*
* @param paramsObj 生成其他选项
* @return 上级菜单ID字段
*/
public static String getParentMenuId(JSONObject paramsObj)
{
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
{
return paramsObj.getString(GenConstants.PARENT_MENU_ID);
}
return DEFAULT_PARENT_MENU_ID;
}
/**
* 获取树编码
*
* @param options 生成其他选项
*
* @param paramsObj 生成其他选项
* @return 树编码
*/
public static String getTreecode(JSONObject paramsObj)
@ -236,13 +262,13 @@ public class VelocityUtils
{
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
}
return "";
return StringUtils.EMPTY;
}
/**
* 获取树父编码
*
* @param options 生成其他选项
*
* @param paramsObj 生成其他选项
* @return 树父编码
*/
public static String getTreeParentCode(JSONObject paramsObj)
@ -251,13 +277,13 @@ public class VelocityUtils
{
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
}
return "";
return StringUtils.EMPTY;
}
/**
* 获取树名称
*
* @param options 生成其他选项
*
* @param paramsObj 生成其他选项
* @return 树名称
*/
public static String getTreeName(JSONObject paramsObj)
@ -266,12 +292,12 @@ public class VelocityUtils
{
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
}
return "";
return StringUtils.EMPTY;
}
/**
* 获取需要在哪一列上面显示展开按钮
*
*
* @param genTable 业务表对象
* @return 展开按钮列序号
*/

View File

@ -117,4 +117,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
<delete id="deleteGenTableColumns">
delete from gen_table_column where column_id in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.columnId}
</foreach>
</delete>
</mapper>

View File

@ -15,6 +15,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="businessName" column="business_name" />
<result property="functionName" column="function_name" />
<result property="functionAuthor" column="function_author" />
<result property="genType" column="gen_type" />
<result property="genPath" column="gen_path" />
<result property="options" column="options" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
@ -50,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectGenTableVo">
select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, options, create_by, create_time, update_by, update_time, remark from gen_table
select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
</sql>
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
@ -62,11 +64,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
AND date_format(create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
</select>
@ -82,11 +84,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
AND date_format(create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</select>
@ -106,7 +108,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
@ -114,7 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
FROM gen_table t
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
@ -132,6 +134,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="businessName != null and businessName != ''">business_name,</if>
<if test="functionName != null and functionName != ''">function_name,</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
<if test="genType != null and genType != ''">gen_type,</if>
<if test="genPath != null and genPath != ''">gen_path,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
@ -145,6 +149,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="businessName != null and businessName != ''">#{businessName},</if>
<if test="functionName != null and functionName != ''">#{functionName},</if>
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
<if test="genType != null and genType != ''">#{genType},</if>
<if test="genPath != null and genPath != ''">#{genPath},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate()
@ -158,6 +164,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
<if test="className != null and className != ''">class_name = #{className},</if>
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
@ -178,4 +186,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
</mapper>
</mapper>

View File

@ -1,22 +1,22 @@
-- 菜单 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}查询', @parentId, '1', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}新增', @parentId, '2', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}修改', @parentId, '3', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}删除', @parentId, '4', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}导出', @parentId, '5', '#', '', 1, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, '');

View File

@ -1,6 +1,6 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns)
#if($column.query)
#set($dictType=$column.dictType)
@ -51,23 +51,23 @@
#end
#end
<el-form-item>
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
class="filter-item"
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button>
<el-button
class="filter-item"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
</el-form-item>
</el-form>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
@ -139,8 +139,16 @@
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
#elseif($column.htmlType == "uploadImage")
<el-form-item label="${comment}">
<uploadImage v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
<el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option
v-for="dict in ${field}Options"
@ -152,11 +160,28 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${field}Options"
:key="dict.dictValue"
:label="dict.dictValue">
{{dict.dictLabel}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
@ -204,14 +229,42 @@
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
import UploadImage from '@/components/UploadImage';
#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 {
name: "${BusinessName}",
components: { Treeselect },
components: {
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
UploadImage,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
Treeselect
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// ${functionName}表格数据
${businessName}List: [],
// ${functionName}树选项
@ -236,7 +289,7 @@ export default {
queryParams: {
#foreach ($column in $columns)
#if($column.query)
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
$column.javaField: null#if($velocityCount != $columns.size()),#end
#end
#end
@ -253,9 +306,8 @@ export default {
#else
#set($comment=$column.columnComment)
#end
#set($comment=$column.columnComment)
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: "blur" }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($velocityCount != $columns.size()),#end
#end
@ -312,7 +364,7 @@ export default {
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
@ -326,10 +378,13 @@ export default {
this.form = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($velocityCount != $columns.size()),#end
#else
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
$column.javaField: null#if($velocityCount != $columns.size()),#end
#end
#end
@ -356,34 +411,40 @@ export default {
handleUpdate(row) {
this.reset();
this.getTreeselect();
if (row != undefined) {
if (row != null) {
this.form.${treeParentCode} = row.${treeCode};
}
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
this.form = response.data;
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end
#end
this.open = true;
this.title = "修改${functionName}";
});
},
/** 提交按钮 */
submitForm: function() {
submitForm() {
this.#[[$]]#refs["form"].validate(valid => {
if (valid) {
if (this.form.${pkColumn.javaField} != undefined) {
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end
#end
if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => {
if (response.code === 200) {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
}
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
add${BusinessName}(this.form).then(response => {
if (response.code === 200) {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
}
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
@ -400,8 +461,8 @@ export default {
}).then(() => {
this.getList();
this.msgSuccess("删除成功");
}).catch(function() {});
})
}
}
};
</script>
</script>

View File

@ -1,6 +1,6 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns)
#if($column.query)
#set($dictType=$column.dictType)
@ -51,7 +51,7 @@
#end
#end
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
@ -95,6 +95,7 @@
v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
@ -167,8 +168,16 @@
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
#elseif($column.htmlType == "uploadImage")
<el-form-item label="${comment}">
<uploadImage v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
<el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option
v-for="dict in ${field}Options"
@ -180,11 +189,28 @@
</el-select>
</el-form-item>
#elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}">
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${field}Options"
:key="dict.dictValue"
:label="dict.dictValue">
{{dict.dictLabel}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
@ -230,9 +256,35 @@
<script>
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 == "uploadImage")
import UploadImage from '@/components/UploadImage';
#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 {
name: "${BusinessName}",
components: {
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
UploadImage,
#break
#end
#end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
},
data() {
return {
// 遮罩层
@ -243,6 +295,8 @@ export default {
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// ${functionName}表格数据
@ -269,7 +323,7 @@ export default {
pageSize: 10,
#foreach ($column in $columns)
#if($column.query)
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
$column.javaField: null#if($velocityCount != $columns.size()),#end
#end
#end
@ -286,9 +340,8 @@ export default {
#else
#set($comment=$column.columnComment)
#end
#set($comment=$column.columnComment)
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: "blur" }
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($velocityCount != $columns.size()),#end
#end
@ -326,7 +379,7 @@ export default {
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
@ -340,10 +393,13 @@ export default {
this.form = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($velocityCount != $columns.size()),#end
#else
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
$column.javaField: null#if($velocityCount != $columns.size()),#end
#end
#end
@ -363,7 +419,7 @@ export default {
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.${pkColumn.javaField})
this.single = selection.length!=1
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
@ -378,29 +434,35 @@ export default {
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
get${BusinessName}(${pkColumn.javaField}).then(response => {
this.form = response.data;
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end
#end
this.open = true;
this.title = "修改${functionName}";
});
},
/** 提交按钮 */
submitForm: function() {
submitForm() {
this.#[[$]]#refs["form"].validate(valid => {
if (valid) {
if (this.form.${pkColumn.javaField} != undefined) {
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end
#end
if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => {
if (response.code === 200) {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
}
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
add${BusinessName}(this.form).then(response => {
if (response.code === 200) {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
}
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
@ -418,7 +480,7 @@ export default {
}).then(() => {
this.getList();
this.msgSuccess("删除成功");
}).catch(function() {});
})
},
/** 导出按钮操作 */
handleExport() {
@ -431,8 +493,8 @@ export default {
return export${BusinessName}(queryParams);
}).then(response => {
this.download(response.msg);
}).catch(function() {});
})
}
}
};
</script>
</script>

View File

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

View File

@ -88,7 +88,7 @@ public class SysJob extends BaseEntity implements Serializable
}
@NotBlank(message = "调用目标字符串不能为空")
@Size(min = 0, max = 1000, message = "调用目标字符串长度不能超过500个字符")
@Size(min = 0, max = 500, message = "调用目标字符串长度不能超过500个字符")
public String getInvokeTarget()
{
return invokeTarget;

View File

@ -66,7 +66,7 @@ public abstract class AbstractQuartzJob implements Job
* 执行后
*
* @param context 工作执行上下文对象
* @param sysScheduleJob 系统计划任务
* @param sysJob 系统计划任务
*/
protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
{

View File

@ -35,11 +35,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="invokeTarget != null and invokeTarget != ''">
AND invoke_target like concat('%', #{invokeTarget}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
</select>

View File

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

View File

@ -13,10 +13,15 @@ public class MetaVo
private String title;
/**
* 设置该路由的图标对应路径src/icons/svg
* 设置该路由的图标对应路径src/assets/icons/svg
*/
private String icon;
/**
* 设置为true则不会被 <keep-alive>缓存
*/
private boolean noCache;
public MetaVo()
{
}
@ -27,6 +32,23 @@ public class MetaVo
this.icon = icon;
}
public MetaVo(String title, String icon, boolean noCache)
{
this.title = title;
this.icon = icon;
this.noCache = noCache;
}
public boolean isNoCache()
{
return noCache;
}
public void setNoCache(boolean noCache)
{
this.noCache = noCache;
}
public String getTitle()
{
return title;

View File

@ -23,9 +23,10 @@ public interface SysDeptMapper
* 根据角色ID查询部门树信息
*
* @param roleId 角色ID
* @param deptCheckStrictly 部门树选择项是否关联显示
* @return 选中部门列表
*/
public List<Integer> selectDeptListByRoleId(Long roleId);
public List<Integer> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
/**
* 根据部门ID查询信息

View File

@ -6,14 +6,14 @@ import com.ruoyi.common.core.domain.entity.SysMenu;
/**
* 菜单表 数据层
*
*
* @author ruoyi
*/
public interface SysMenuMapper
{
/**
* 查询系统菜单列表
*
*
* @param menu 菜单信息
* @return 菜单列表
*/
@ -21,14 +21,14 @@ public interface SysMenuMapper
/**
* 根据用户所有权限
*
*
* @return 权限列表
*/
public List<String> selectMenuPerms();
/**
* 根据用户查询系统菜单列表
*
*
* @param menu 菜单信息
* @return 菜单列表
*/
@ -36,7 +36,7 @@ public interface SysMenuMapper
/**
* 根据用户ID查询权限
*
*
* @param userId 用户ID
* @return 权限列表
*/
@ -44,15 +44,15 @@ public interface SysMenuMapper
/**
* 根据用户ID查询菜单
*
*
* @return 菜单列表
*/
public List<SysMenu> selectMenuTreeAll();
/**
* 根据用户ID查询菜单
*
* @param username 用户ID
*
* @param userId 用户ID
* @return 菜单列表
*/
public List<SysMenu> selectMenuTreeByUserId(Long userId);
@ -61,13 +61,14 @@ public interface SysMenuMapper
* 根据角色ID查询菜单树信息
*
* @param roleId 角色ID
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表
*/
public List<Integer> selectMenuListByRoleId(Long roleId);
public List<Integer> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
/**
* 根据菜单ID查询信息
*
*
* @param menuId 菜单ID
* @return 菜单信息
*/
@ -75,7 +76,7 @@ public interface SysMenuMapper
/**
* 是否存在菜单子节点
*
*
* @param menuId 菜单ID
* @return 结果
*/
@ -83,7 +84,7 @@ public interface SysMenuMapper
/**
* 新增菜单信息
*
*
* @param menu 菜单信息
* @return 结果
*/
@ -91,7 +92,7 @@ public interface SysMenuMapper
/**
* 修改菜单信息
*
*
* @param menu 菜单信息
* @return 结果
*/
@ -99,7 +100,7 @@ public interface SysMenuMapper
/**
* 删除菜单管理信息
*
*
* @param menuId 菜单ID
* @return 结果
*/
@ -107,7 +108,7 @@ public interface SysMenuMapper
/**
* 校验菜单名称是否唯一
*
*
* @param menuName 菜单名称
* @param parentId 父菜单ID
* @return 结果

View File

@ -26,6 +26,14 @@ public interface SysRoleMenuMapper
*/
public int deleteRoleMenuByRoleId(Long roleId);
/**
* 批量删除角色菜单关联信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteRoleMenu(Long[] ids);
/**
* 批量新增角色菜单信息
*

View File

@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
@ -138,6 +139,14 @@ public class SysConfigServiceImpl implements ISysConfigService
@Override
public int deleteConfigByIds(Long[] configIds)
{
for (Long configId : configIds)
{
SysConfig config = selectConfigById(configId);
if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
{
throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
}
}
int count = configMapper.deleteConfigByIds(configIds);
if (count > 0)
{

View File

@ -10,9 +10,11 @@ import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysDeptService;
/**
@ -26,6 +28,9 @@ public class SysDeptServiceImpl implements ISysDeptService
@Autowired
private SysDeptMapper deptMapper;
@Autowired
private SysRoleMapper roleMapper;
/**
* 查询部门管理数据
*
@ -93,7 +98,8 @@ public class SysDeptServiceImpl implements ISysDeptService
@Override
public List<Integer> selectDeptListByRoleId(Long roleId)
{
return deptMapper.selectDeptListByRoleId(roleId);
SysRole role = roleMapper.selectRoleById(roleId);
return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
}
/**
@ -267,13 +273,7 @@ public class SysDeptServiceImpl implements ISysDeptService
{
if (hasChild(list, tChild))
{
// 判断是否有子节点
Iterator<SysDept> it = childList.iterator();
while (it.hasNext())
{
SysDept n = (SysDept) it.next();
recursionFn(list, n);
}
recursionFn(list, tChild);
}
}
}

View File

@ -76,12 +76,12 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
public List<SysDictData> selectDictDataByType(String dictType)
{
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
if (StringUtils.isNotNull(dictDatas))
if (StringUtils.isNotEmpty(dictDatas))
{
return dictDatas;
}
dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (StringUtils.isNotNull(dictDatas))
if (StringUtils.isNotEmpty(dictDatas))
{
DictUtils.setDictCache(dictType, dictDatas);
return dictDatas;

View File

@ -13,12 +13,14 @@ import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper;
import com.ruoyi.system.service.ISysMenuService;
@ -35,6 +37,9 @@ public class SysMenuServiceImpl implements ISysMenuService
@Autowired
private SysMenuMapper menuMapper;
@Autowired
private SysRoleMapper roleMapper;
@Autowired
private SysRoleMenuMapper roleMenuMapper;
@ -124,7 +129,8 @@ public class SysMenuServiceImpl implements ISysMenuService
@Override
public List<Integer> selectMenuListByRoleId(Long roleId)
{
return menuMapper.selectMenuListByRoleId(roleId);
SysRole role = roleMapper.selectRoleById(roleId);
return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
}
/**
@ -144,7 +150,7 @@ public class SysMenuServiceImpl implements ISysMenuService
router.setName(getRouteName(menu));
router.setPath(getRouterPath(menu));
router.setComponent(getComponent(menu));
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache())));
List<SysMenu> cMenus = menu.getChildren();
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
{
@ -159,7 +165,7 @@ public class SysMenuServiceImpl implements ISysMenuService
children.setPath(menu.getPath());
children.setComponent(menu.getComponent());
children.setName(StringUtils.capitalize(menu.getPath()));
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache())));
childrenList.add(children);
router.setChildren(childrenList);
}
@ -178,14 +184,19 @@ public class SysMenuServiceImpl implements ISysMenuService
public List<SysMenu> buildMenuTree(List<SysMenu> menus)
{
List<SysMenu> returnList = new ArrayList<SysMenu>();
List<Long> tempList = new ArrayList<Long>();
for (SysMenu dept : menus)
{
tempList.add(dept.getMenuId());
}
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
{
SysMenu t = (SysMenu) iterator.next();
// 根据传入的某个父节点ID,遍历该父节点的所有子节点
if (t.getParentId() == 0)
SysMenu menu = (SysMenu) iterator.next();
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(menu.getParentId()))
{
recursionFn(menus, t);
returnList.add(t);
recursionFn(menus, menu);
returnList.add(menu);
}
}
if (returnList.isEmpty())
@ -353,6 +364,10 @@ public class SysMenuServiceImpl implements ISysMenuService
{
component = menu.getComponent();
}
else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
{
component = UserConstants.PARENT_VIEW;
}
return component;
}
@ -368,6 +383,17 @@ public class SysMenuServiceImpl implements ISysMenuService
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
}
/**
* 是否为parent_view组件
*
* @param menu 菜单信息
* @return 结果
*/
public boolean isParentView(SysMenu menu)
{
return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
}
/**
* 根据父节点的ID获取所有子节点
*
@ -406,13 +432,7 @@ public class SysMenuServiceImpl implements ISysMenuService
{
if (hasChild(list, tChild))
{
// 判断是否有子节点
Iterator<SysMenu> it = childList.iterator();
while (it.hasNext())
{
SysMenu n = (SysMenu) it.next();
recursionFn(list, n);
}
recursionFn(list, tChild);
}
}
}

View File

@ -290,8 +290,13 @@ public class SysRoleServiceImpl implements ISysRoleService
* @return 结果
*/
@Override
@Transactional
public int deleteRoleById(Long roleId)
{
// 删除角色与菜单关联
roleMenuMapper.deleteRoleMenuByRoleId(roleId);
// 删除角色与部门关联
roleDeptMapper.deleteRoleDeptByRoleId(roleId);
return roleMapper.deleteRoleById(roleId);
}
@ -302,6 +307,7 @@ public class SysRoleServiceImpl implements ISysRoleService
* @return 结果
*/
@Override
@Transactional
public int deleteRoleByIds(Long[] roleIds)
{
for (Long roleId : roleIds)
@ -313,6 +319,10 @@ public class SysRoleServiceImpl implements ISysRoleService
throw new CustomException(String.format("%1$s已分配,不能删除", role.getRoleName()));
}
}
// 删除角色与菜单关联
roleMenuMapper.deleteRoleMenu(roleIds);
// 删除角色与部门关联
roleDeptMapper.deleteRoleDept(roleIds);
return roleMapper.deleteRoleByIds(roleIds);
}
}

View File

@ -75,7 +75,7 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
@Override
public SysUserOnline loginUserToUserOnline(LoginUser user)
{
if (StringUtils.isNull(user) && StringUtils.isNull(user.getUser()))
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser()))
{
return null;
}

View File

@ -363,6 +363,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果
*/
@Override
@Transactional
public int deleteUserById(Long userId)
{
// 删除用户与角色关联
@ -379,12 +380,17 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果
*/
@Override
@Transactional
public int deleteUserByIds(Long[] userIds)
{
for (Long userId : userIds)
{
checkUserAllowed(new SysUser(userId));
}
// 删除用户与角色关联
userRoleMapper.deleteUserRole(userIds);
// 删除用户与岗位关联
userPostMapper.deleteUserPost(userIds);
return userMapper.deleteUserByIds(userIds);
}

View File

@ -50,18 +50,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="configKey != null and configKey != ''">
AND config_key like concat('%', #{configKey}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
</select>
<select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
<include refid="selectConfigVo"/>
where config_key = #{configKey}
where config_key = #{configKey} limit 1
</select>
<insert id="insertConfig" parameterType="SysConfig">

View File

@ -44,12 +44,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by d.parent_id, d.order_num
</select>
<select id="selectDeptListByRoleId" parameterType="Long" resultType="Integer">
select d.dept_id, d.parent_id
<select id="selectDeptListByRoleId" resultType="Integer">
select d.dept_id
from sys_dept d
left join sys_role_dept rd on d.dept_id = rd.dept_id
where rd.role_id = #{roleId}
and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
<if test="deptCheckStrictly">
and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
</if>
order by d.parent_id, d.order_num
</select>
@ -64,7 +66,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="hasChildByDeptId" parameterType="Long" resultType="int">
select count(1) from sys_dept
where del_flag = '0' and parent_id = #{deptId}
where del_flag = '0' and parent_id = #{deptId} limit 1
</select>
<select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
@ -77,7 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkDeptNameUnique" resultMap="SysDeptResult">
<include refid="selectDeptVo"/>
where dept_name=#{deptName} and parent_id = #{parentId}
where dept_name=#{deptName} and parent_id = #{parentId} limit 1
</select>
<insert id="insertDept" parameterType="SysDept">

View File

@ -32,11 +32,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="dictType != null and dictType != ''">
AND dict_type like concat('%', #{dictType}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
</select>
@ -57,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult">
<include refid="selectDictTypeVo"/>
where dict_type = #{dictType}
where dict_type = #{dictType} limit 1
</select>
<delete id="deleteDictTypeById" parameterType="Long">

View File

@ -33,11 +33,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="userName != null and userName != ''">
AND user_name like concat('%', #{userName}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(login_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(login_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(login_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(login_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
order by info_id desc

View File

@ -13,6 +13,7 @@
<result property="path" column="path" />
<result property="component" column="component" />
<result property="isFrame" column="is_frame" />
<result property="isCache" column="is_cache" />
<result property="menuType" column="menu_type" />
<result property="visible" column="visible" />
<result property="status" column="status" />
@ -26,7 +27,7 @@
</resultMap>
<sql id="selectMenuVo">
select menu_id, menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
select menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
from sys_menu
</sql>
@ -47,13 +48,13 @@
</select>
<select id="selectMenuTreeAll" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
@ -72,7 +73,7 @@
</select>
<select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
@ -82,12 +83,14 @@
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByRoleId" parameterType="Long" resultType="Integer">
select m.menu_id, m.parent_id
<select id="selectMenuListByRoleId" resultType="Integer">
select m.menu_id
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
where rm.role_id = #{roleId}
and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
<if test="menuCheckStrictly">
and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
</if>
order by m.parent_id, m.order_num
</select>
@ -118,7 +121,7 @@
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
where menu_name=#{menuName} and parent_id = #{parentId}
where menu_name=#{menuName} and parent_id = #{parentId} limit 1
</select>
<update id="updateMenu" parameterType="SysMenu">
@ -130,6 +133,7 @@
<if test="path != null and path != ''">path = #{path},</if>
<if test="component != null and component != ''">component = #{component},</if>
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
<if test="visible != null">visible = #{visible},</if>
<if test="status != null">status = #{status},</if>
@ -151,6 +155,7 @@
<if test="path != null and path != ''">path,</if>
<if test="component != null and component != ''">component,</if>
<if test="isFrame != null and isFrame != ''">is_frame,</if>
<if test="isCache != null and isCache != ''">is_cache,</if>
<if test="menuType != null and menuType != ''">menu_type,</if>
<if test="visible != null">visible,</if>
<if test="status != null">status,</if>
@ -167,6 +172,7 @@
<if test="path != null and path != ''">#{path},</if>
<if test="component != null and component != ''">#{component},</if>
<if test="isFrame != null and isFrame != ''">#{isFrame},</if>
<if test="isCache != null and isCache != ''">#{isCache},</if>
<if test="menuType != null and menuType != ''">#{menuType},</if>
<if test="visible != null">#{visible},</if>
<if test="status != null">#{status},</if>

View File

@ -18,7 +18,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectNoticeVo">
select notice_id, notice_title, notice_type, notice_content, status, create_by, create_time, update_by, update_time, remark
select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark
from sys_notice
</sql>

View File

@ -54,11 +54,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="operName != null and operName != ''">
AND oper_name like concat('%', #{operName}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(oper_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(oper_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(oper_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(oper_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
order by oper_id desc

View File

@ -64,12 +64,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult">
<include refid="selectPostVo"/>
where post_name=#{postName}
where post_name=#{postName} limit 1
</select>
<select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult">
<include refid="selectPostVo"/>
where post_code=#{postCode}
where post_code=#{postCode} limit 1
</select>
<update id="updatePost" parameterType="SysPost">

View File

@ -5,22 +5,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.ruoyi.system.mapper.SysRoleMapper">
<resultMap type="SysRole" id="SysRoleResult">
<id property="roleId" column="role_id" />
<result property="roleName" column="role_name" />
<result property="roleKey" column="role_key" />
<result property="roleSort" column="role_sort" />
<result property="dataScope" column="data_scope" />
<result property="status" column="status" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<id property="roleId" column="role_id" />
<result property="roleName" column="role_name" />
<result property="roleKey" column="role_key" />
<result property="roleSort" column="role_sort" />
<result property="dataScope" column="data_scope" />
<result property="menuCheckStrictly" column="menu_check_strictly" />
<result property="deptCheckStrictly" column="dept_check_strictly" />
<result property="status" column="status" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectRoleVo">
select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope,
select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
r.status, r.del_flag, r.create_time, r.remark
from sys_role r
left join sys_user_role ur on ur.role_id = r.role_id
@ -40,11 +42,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">
AND r.role_key like concat('%', #{roleKey}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
and date_format(r.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(r.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
@ -80,12 +82,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
where r.role_name=#{roleName}
where r.role_name=#{roleName} limit 1
</select>
<select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
where r.role_key=#{roleKey}
where r.role_key=#{roleKey} limit 1
</select>
<insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId">
@ -95,6 +97,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">role_key,</if>
<if test="roleSort != null and roleSort != ''">role_sort,</if>
<if test="dataScope != null and dataScope != ''">data_scope,</if>
<if test="menuCheckStrictly != null">menu_check_strictly,</if>
<if test="deptCheckStrictly != null">dept_check_strictly,</if>
<if test="status != null and status != ''">status,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
@ -105,6 +109,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">#{roleKey},</if>
<if test="roleSort != null and roleSort != ''">#{roleSort},</if>
<if test="dataScope != null and dataScope != ''">#{dataScope},</if>
<if test="menuCheckStrictly != null">#{menuCheckStrictly},</if>
<if test="deptCheckStrictly != null">#{deptCheckStrictly},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
@ -119,6 +125,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="roleKey != null and roleKey != ''">role_key = #{roleKey},</if>
<if test="roleSort != null and roleSort != ''">role_sort = #{roleSort},</if>
<if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</if>
<if test="menuCheckStrictly != null">menu_check_strictly = #{menuCheckStrictly},</if>
<if test="deptCheckStrictly != null">dept_check_strictly = #{deptCheckStrictly},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>

View File

@ -10,13 +10,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<select id="checkMenuExistRole" resultType="Integer">
select count(1) from sys_role_menu where menu_id = #{menuId}
select count(1) from sys_role_menu where menu_id = #{menuId}
</select>
<delete id="deleteRoleMenuByRoleId" parameterType="Long">
delete from sys_role_menu where role_id=#{roleId}
</delete>
<delete id="deleteRoleMenu" parameterType="Long">
delete from sys_role_menu where role_id in
<foreach collection="array" item="roleId" open="(" separator="," close=")">
#{roleId}
</foreach>
</delete>
<insert id="batchRoleMenu">
insert into sys_role_menu(role_id, menu_id) values
<foreach item="item" index="index" collection="list" separator=",">

View File

@ -68,14 +68,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET (#{deptId},ancestors) ))
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
@ -92,15 +92,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="checkUserNameUnique" parameterType="String" resultType="int">
select count(1) from sys_user where user_name = #{userName}
select count(1) from sys_user where user_name = #{userName} limit 1
</select>
<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber}
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} limit 1
</select>
<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
select user_id, email from sys_user where email = #{email}
select user_id, email from sys_user where email = #{email} limit 1
</select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">

View File

@ -1,5 +1,13 @@
module.exports = {
presets: [
'@vue/app'
]
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
'@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
'plugins': ['dynamic-import-node']
}
}
}

View File

@ -1,19 +1,15 @@
{
"name": "ruoyi",
"version": "3.0.0",
"version": "3.3.0",
"description": "若依管理系统",
"author": "若依",
"license": "MIT",
"scripts": {
"dev": "vue-cli-service serve --open",
"dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"new": "plop"
"lint": "eslint --ext .js,.vue src"
},
"husky": {
"hooks": {
@ -41,59 +37,45 @@
},
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"axios": "0.18.1",
"clipboard": "2.0.4",
"echarts": "4.2.1",
"element-ui": "2.13.2",
"file-saver": "2.0.1",
"js-beautify": "^1.10.2",
"fuse.js": "3.4.4",
"js-cookie": "2.2.0",
"axios": "0.21.0",
"clipboard": "2.0.6",
"core-js": "3.8.1",
"echarts": "4.9.0",
"element-ui": "2.14.1",
"file-saver": "2.0.4",
"fuse.js": "6.4.3",
"highlight.js": "10.4.1",
"js-beautify": "1.13.0",
"js-cookie": "2.2.1",
"jsencrypt": "3.0.0-rc.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"screenfull": "4.2.0",
"sortablejs": "1.8.4",
"vue": "2.6.10",
"path-to-regexp": "6.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
"sortablejs": "1.10.2",
"vue": "2.6.12",
"vue-count-to": "1.0.13",
"vue-quill-editor": "3.0.6",
"vue-cropper": "0.4.9",
"vue-router": "3.0.2",
"vue-splitpane": "1.0.4",
"vuedraggable": "2.20.0",
"vuex": "3.1.0"
"vue-cropper": "0.5.5",
"vue-router": "3.4.9",
"vuedraggable": "2.24.3",
"vuex": "3.6.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "3.5.3",
"@vue/cli-plugin-eslint": "^3.9.1",
"@vue/cli-plugin-unit-jest": "3.5.3",
"@vue/cli-service": "3.5.3",
"@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "^9.5.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"chalk": "2.4.2",
"chokidar": "2.1.5",
"@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0",
"chalk": "4.1.0",
"connect": "3.6.6",
"eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2",
"html-webpack-plugin": "3.2.0",
"http-proxy-middleware": "^0.19.1",
"husky": "1.3.1",
"lint-staged": "8.1.5",
"mockjs": "1.0.1-beta3",
"node-sass": "^4.9.0",
"plop": "2.3.0",
"runjs": "^4.3.2",
"sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.0",
"vue-template-compiler": "2.6.10"
"eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0",
"lint-staged": "10.5.3",
"sass": "1.30.0",
"runjs": "4.4.2",
"sass-loader": "10.1.0",
"script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1",
"vue-template-compiler": "2.6.12"
},
"engines": {
"node": ">=8.9",

View File

@ -0,0 +1,9 @@
import request from '@/utils/request'
// 查询缓存详细
export function getCache() {
return request({
url: '/monitor/cache',
method: 'get'
})
}

View File

@ -42,6 +42,7 @@ export function importTable(data) {
params: data
})
}
// 预览生成代码
export function previewTable(tableId) {
return request({
@ -49,6 +50,7 @@ export function previewTable(tableId) {
method: 'get'
})
}
// 删除表数据
export function delTable(tableId) {
return request({
@ -57,3 +59,18 @@ export function delTable(tableId) {
})
}
// 生成代码(自定义路径)
export function genCode(tableName) {
return request({
url: '/tool/gen/genCode/' + tableName,
method: 'get'
})
}
// 同步数据库
export function synchDb(tableName) {
return request({
url: '/tool/gen/synchDb/' + tableName,
method: 'get'
})
}

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605865043777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="856" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1023.786667 611.84c-0.426667 9.770667-13.354667 20.693333-39.893334 34.56-54.613333 28.458667-337.749333 144.896-397.994666 176.298667-60.288 31.402667-93.738667 31.104-141.354667 8.32-47.616-22.741333-348.842667-144.469333-403.114667-170.368-27.093333-12.970667-40.917333-23.893333-41.386666-34.218667v103.509333c0 10.325333 14.250667 21.290667 41.386666 34.261334 54.272 25.941333 355.541333 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.362667 60.245333-31.402667 343.338667-147.797333 397.994666-176.298667 27.776-14.464 40.106667-25.728 40.106667-35.925333v-102.058667l-0.213333-0.085333z m0-168.746667c-0.512 9.770667-13.397333 20.650667-39.893334 34.517334-54.613333 28.458667-337.749333 144.896-397.994666 176.298666-60.288 31.402667-93.738667 31.104-141.354667 8.362667-47.616-22.741333-348.842667-144.469333-403.114667-170.410667-27.093333-12.928-40.917333-23.893333-41.386666-34.176v103.509334c0 10.325333 14.250667 21.248 41.386666 34.218666 54.272 25.941333 355.498667 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.32 60.245333-31.402667 343.338667-147.84 397.994666-176.298666 27.776-14.506667 40.106667-25.770667 40.106667-35.968v-102.058667l-0.256-0.042667z m0-175.018666c0.469333-10.410667-13.141333-19.541333-40.533334-29.610667-53.248-19.498667-334.634667-131.498667-388.522666-151.253333-53.888-19.712-75.818667-18.901333-139.093334 3.84C392.234667 113.706667 92.629333 231.253333 39.338667 252.074667c-26.666667 10.496-39.68 20.181333-39.253334 30.506666V386.133333c0 10.325333 14.250667 21.248 41.386667 34.218667 54.272 25.941333 355.498667 147.669333 403.114667 170.410667 47.616 22.741333 81.066667 23.04 141.354666-8.362667 60.245333-31.402667 343.338667-147.84 397.994667-176.298667 27.776-14.506667 40.106667-25.770667 40.106667-35.968V268.074667h-0.341334zM366.677333 366.08l237.269334-36.437333-71.68 105.088-165.546667-68.650667z m524.8-94.634667l-140.330666 55.466667-15.232 5.973333-140.245334-55.466666 155.392-61.44 140.373334 55.466666z m-411.989333-101.674666l-22.954667-42.325334 71.594667 27.989334 67.498667-22.101334-18.261334 43.733334 68.778667 25.770666-88.704 9.216-19.882667 47.786667-32.085333-53.290667-102.4-9.216 76.416-27.562666z m-176.768 59.733333c70.058667 0 126.805333 21.973333 126.805333 49.109333s-56.746667 49.152-126.805333 49.152-126.848-22.058667-126.848-49.152c0-27.136 56.789333-49.152 126.848-49.152z" p-id="857"></path></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<g id="Rectangle-18">
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
</g>
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

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