Compare commits

...

75 Commits

Author SHA1 Message Date
thinkgem
57c1cb3289 upgrade shiro 1.7.0 2020-11-03 17:30:50 +08:00
thinkgem
9d32a7f17d 删除无用的代码 2020-10-30 20:53:33 +08:00
thinkgem
eabaf8b0d6 topMenu 引用 子模板文件 路径改为绝对路径 2020-10-29 16:13:58 +08:00
thinkgem
53bf08eeca layer get method 支持 contentFormData 参数 2020-10-29 15:56:09 +08:00
thinkgem
b23e65fed9 Double-checked locking and volatile 2020-10-28 12:36:38 +08:00
thinkgem
f48a7b38d2 Merge branch 'master' of https://gitee.com/thinkgem/jeesite4 into master
# Conflicts:
#	parent/pom.xml
2020-10-27 22:17:38 +08:00
thinkgem
4e1c54435b Merge branch 'v4.2_dev' of https://gitee.com/thinkgem/jeesite4 into v4.2_dev 2020-10-27 21:12:42 +08:00
thinkgem
c54a21cfd6 兼容 spring cloud config 2020-10-27 21:12:05 +08:00
thinkgem
913a77d01f 兼容 spring cloud config 2020-10-26 14:17:15 +08:00
thinkgem
2747e0d5d3 update 2020-10-23 15:58:06 +08:00
thinkgem
fa2b3d92ca 更改cookie默认存储路径为contextpath 2020-10-14 22:55:29 +08:00
thinkgem
629b1b963f 个人信息保存即时显示最新信息的问题 2020-10-14 17:56:30 +08:00
thinkgem
5e346c6d72 找回密码和注册用户敏感信息加密处理 2020-09-29 16:07:47 +08:00
thinkgem
ac4c092a1c 泛型函数返回类型优化 2020-09-28 15:12:49 +08:00
thinkgem
4e6e22e4dc sql过滤优化增加|sleep|union|load_file函数的过滤 2020-09-28 15:11:27 +08:00
thinkgem
a95d663db3 新增 listselect 代码生成模板。 2020-09-25 22:37:39 +08:00
thinkgem
40169ac7a9 新增 Cloud 微服务模块的代码生成模板。 2020-09-25 16:22:33 +08:00
thinkgem
9e62a3b259 增加 shell 打包和部署脚本 2020-09-25 14:30:14 +08:00
thinkgem
63fa05b440 新增创建模块的代码生成功能,模块代码生成模板。 2020-09-24 10:12:32 +08:00
thinkgem
3dd8ec03b9 优化ueditor设置高度的时候出现不必要的滚动条。 2020-09-24 10:05:00 +08:00
thinkgem
32f81e1fee userSelect、empUserSelect的json验证优化 2020-09-24 10:04:27 +08:00
thinkgem
37675bac9d 点击右上角【Star】收藏本软件 ^_^ 2020-09-24 10:03:30 +08:00
thinkgem
f9842c3c86 upgrade spring boot 2.3.4、spring 5.2.9 2020-09-22 10:48:58 +08:00
卓源软件
b8cae70933 upgrade spring boot 2.2.10spring 5.2.9 2020-09-22 10:47:18 +08:00
thinkgem
0f0ff4af1a 新增 BPM 表单代码生成模板;Cloud 代码生成模块迁移到核心模块; 2020-09-21 14:29:25 +08:00
thinkgem
3539230d44 代码优化 2020-09-21 13:38:44 +08:00
thinkgem
af56d05847 登录界面 user.loginByValidCode 优化 2020-09-21 13:38:15 +08:00
thinkgem
75c1c74fea 优化模拟短信发送提示 2020-09-20 19:17:48 +08:00
thinkgem
202e9d8918 新增手机号短信验证码登录 user.loginByValidCode=true;调整
sysLogin、sysIndex、menuTree、forgetPwd、registerUser 的目录,方便覆写和理解;增加 自定义主题视图
的 readme.txt 帮助文件。
2020-09-20 18:42:25 +08:00
thinkgem
faeb49ee98 新增手机号短信验证码登录 user.loginByValidCode=true;调整
sysLogin、sysIndex、menuTree、forgetPwd、registerUser 的目录,方便覆写和理解;增加 自定义主题视图
的 readme.txt 帮助文件。
2020-09-20 18:28:48 +08:00
thinkgem
bbb37722d6 单点登录接口和无条件登录接口优化改进,并在调用登录时统一增加登录成功和失败事件,方便返回登录信息。 2020-09-20 17:38:54 +08:00
thinkgem
f3bb96d719 如果是在个性化用户类型的登录界面,登录的系统,则在退出时返回对应用户类型的登录界面。 2020-09-20 09:41:54 +08:00
thinkgem
055d791c44 不允许上传空文件友情提示 2020-09-18 16:55:11 +08:00
thinkgem
bf01c76167 升级工具依赖;去掉一些极少用的依赖,按需加入; 2020-09-17 15:12:34 +08:00
thinkgem
df98f266b9 初始化数据库脚本优化 2020-09-14 23:01:25 +08:00
thinkgem
9daef68787 升级到 spring boot 2.3.3;依赖模块 es 升级到 7.x 利用 RestHighLevelClient
实现检索;菜单优化,选择模块改为多选下拉框;其它优化
2020-09-11 18:51:00 +08:00
thinkgem
663a66b571 点击右上角【Star】收藏本软件 ^_^ 2020-09-09 21:00:27 +08:00
thinkgem
687dbe0f93 生成模板的树表没有状态字段的时候不判断状态 2020-09-09 20:56:59 +08:00
thinkgem
9063996fd0 主题优化,全屏桌面,性能及体验再此提升。 2020-09-09 19:16:37 +08:00
thinkgem
1fef63126d 文件管理增加租户支持 2020-09-08 17:13:20 +08:00
thinkgem
add7294529 细节优化 2020-09-06 23:44:09 +08:00
thinkgem
93652a25ae 点击右上角【Star】收藏本软件 ^_^ 2020-09-06 23:43:41 +08:00
thinkgem
0ed597e1f1 start 4.2.2 2020-09-06 23:43:09 +08:00
thinkgem
b799b92cf1 登录页图标显示优化 2020-09-01 11:27:37 +08:00
thinkgem
70f2b5fefc 点击右上角【Star】收藏本软件 ^_^ 2020-09-01 11:27:17 +08:00
thinkgem
07c50de54a 点击右上角【Star】收藏本软件 ^_^ 2020-08-25 15:12:22 +08:00
thinkgem
a11fd3a645 微不足道,按登录设备自定义会话超时时间的例子。 2020-08-25 15:08:06 +08:00
thinkgem
39ffa1c449 点击右上角【Star】收藏本软件 ^_^ 2020-08-24 21:43:52 +08:00
thinkgem
36f7640a83 优化isAjaxRequest增加个性化配置开关 2020-08-24 09:06:26 +08:00
thinkgem
4ac34013b3 当使用 __ajax=json 参数的时候 403 页面返回空字符的优化。 2020-08-23 23:59:49 +08:00
thinkgem
78c3f02f41 用户管理新增附属部门及岗位的查询 2020-08-20 14:21:19 +08:00
thinkgem
7750bfd49a 性能提升 2020-08-20 14:20:54 +08:00
thinkgem
f46b42d28e upgrade shiro 1.6.0 2020-08-18 19:25:30 +08:00
thinkgem
14f0cc5811 支持匿名访问swagger文档 2020-08-18 18:37:44 +08:00
thinkgem
3a9e0d5dc1 use jackson xml instead jaxb 2020-08-15 23:21:38 +08:00
thinkgem
f56b92ba5f remove jaxb dependency 2020-08-14 17:46:17 +08:00
thinkgem
98f57a2511 update 2020-08-14 12:02:16 +08:00
thinkgem
9e53433922 审核状态的用户显示启用按钮 2020-08-14 12:02:08 +08:00
thinkgem
1726e5af57 Merge branch 'master' of https://gitee.com/thinkgem/jeesite4 into master 2020-08-13 14:53:48 +08:00
thinkgem
1174723bc0 Merge branch 'v4.2_dev' into master 2020-08-13 14:51:54 +08:00
thinkgem
7654cdc6c8 v4.2.1 2020-08-13 14:48:58 +08:00
thinkgem
c03c75609a 导入的数据进行 xss 过滤 2020-08-12 11:17:21 +08:00
thinkgem
32ce44dac4 登录提交信息非法请求解析错误则忽略异常 2020-08-12 11:05:02 +08:00
thinkgem
c068718fa0 修正 ueditor 快速图片上传 session 丢失问题 2020-08-07 12:50:08 +08:00
thinkgem
44b25989d6 jdk11下默认不加载jaxb模块,因此加载实现。 2020-08-03 21:45:45 +08:00
thinkgem
b9808181d5 upgrade boot 2.2.9 2020-07-30 11:59:16 +08:00
thinkgem
769f89ea67 add plugin repos 2020-07-30 10:45:27 +08:00
卓源软件
8486aa1909 update plugin repos 2020-07-30 10:44:05 +08:00
thinkgem
a4ca4aeb18 Tab页签支持拖拽排序;Grid列支持拖拽排序;Grid列支持显示隐藏;表头下放搜索工具条演示; 2020-07-29 17:56:48 +08:00
thinkgem
38ee55bd38 快捷日期选择新增近1周,近n天参数。 2020-07-27 23:36:29 +08:00
thinkgem
d9c3b036f3 修正 laydate.js 的 done 事件,当下一个日期弹出前,可能上一个还未设置,导致选择不上的问题。 2020-07-27 19:14:39 +08:00
卓源软件
a6cbbbfd16 修正 laydate.js 的 done 事件,当下一个日期弹出前,可能上一个还未设置,导致选择不上的问题。 2020-07-27 19:14:12 +08:00
thinkgem
91452fdd93 4.2.1 2020-07-27 17:52:27 +08:00
thinkgem
34c47d1686 Merge remote-tracking branch 'remotes/origin/v4.2_dev' 2020-07-27 17:49:47 +08:00
thinkgem
8319ed58ed 点击右上角【Star】收藏本软件 ^_^ 2020-07-27 17:46:55 +08:00
157 changed files with 13981 additions and 933 deletions

View File

@@ -878,3 +878,4 @@ For more information on this, and how to apply and follow the GNU AGPL, see
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他
原作者规定需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品 http://jeesite.com
7. 您若套用本平台的一些代码或功能参考,需要在您的软件介绍明显位置说明出处。

View File

@@ -1,33 +1,61 @@
## 引言
JeeSite 是一个 Java EE 企业级快速开发平台基于经典技术组合Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE采用经典开发模式让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能包括核心模块如组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计界面无刷新一键换肤众多账号安全设置密码策略在线定时任务配置支持集群支持SAAS支持多数据源支持读写分离、分库分表支持微服务。
## 技术交流
* 交流 QQ 群(千人大群):`127515876``209330483``223507718``709534275``730390092``1373527``183903863(外包)`
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>  [【新手必读】](https://gitee.com/thinkgem/jeesite4/issues/I18ARR)
* 码云Gitee<https://gitee.com/thinkgem/jeesite4>
* GitHub<https://github.com/thinkgem/jeesite4>
* 作者博客:<https://my.oschina.net/thinkgem>
* **技术服务:**<http://s.jeesite.com>
* 官方网站:<http://jeesite.com>
* 官方论坛:<http://jeesite.net>
* 关注微信公众号,了解最新动态:
![JeeSite4微信公众号](https://images.gitee.com/uploads/images/2020/0727/091951_a3ab258c_6732.jpeg "JeeSite4微信公众号")
## 平台介绍
JeeSite 快速开发平台不仅仅是一个后台开发框架它是一个企业级快速开发解决方案基于经典技术组合Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE采用经典开发模式让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能包括模块如组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计模块增减便捷界面无刷新一键换肤众多账号安全设置密码策略文件在线预览消息推送多元化第三方登录在线定时任务配置支持集群支持SAAS支持多数据源支持读写分离、分库分表支持微服务应用。
JeeSite 快速开发平台的主要目的是能够让初级的研发人员快速的开发出复杂的业务功能(经典架构会的人多),让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
JeeSite 1.x 自 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中JeeSite 架构简单精良、易于扩展、大众思维的设计模式,深入开发者的内心,并荣获开源中国《最受欢迎中国开源软件》奖杯,期间也帮助了不少刚毕业的大学生,作为入门教材,快速的去实践。
JeeSite 自 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中JeeSite 架构精良、易于扩展、大众思维的设计模式、工匠精神打磨每一个细节,深入开发者的内心,并荣获开源中国《最受欢迎中国开源软件》奖杯,期间也帮助了不少刚毕业的大学生,教师作为入门教材,快速的去实践。
JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集。
JeeSite4 的升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集等众多安全选项供你选择。努力为大中小微企业打造全方位企业级快速开发解决方案
### 4.x 的新特性及优势:<http://jeesite.com/?t=281645>
## 平台优势
JeeSite 整体架构清晰、稳定技术先进、源代码书写规范、经典技术会的人多、易于维护、易于扩展、安全稳定。
JeeSite 功能全JeeSite 的知识点非常多,也非常少。因为她使用的都是一些通用的技术,通俗的设计风格,大多数基础知识点多数人都能掌握,所以每一个 JeeSite 的功能点都非常容易掌握。只要你学会使用这些功能和组件的应用,就可以顺利的完成系统开发了。
JeeSite 是一个低代码开发平台具有较高的封装度、扩展性封装不是限制你去做一些事情而是在便捷的同时也具有较好的扩展性在不具备一些功能的情况下JeeSite 提供了扩展接口,提供了原生调用方法。
大家都在用 Spring 在学习 Spring 架构的优点Spring 提供了较好的扩展性可又有多少人去修改它的源代码呢退一步说大家去修改了 Spring 的源码反而会对未来升级造成很大困扰您说不是呢这样的例子很多所以不要纠结JeeSite 也一样具备强大的扩展性。
发展至今 JeeSite 平台架构已经非常稳定JeeSite 是一个专业的平台,是一个让你使用放心的平台。
### v4 架构特点、安全方面等等的优势:<http://jeesite.com/docs/feature/>
## 技术选型
* 主框架Spring Boot 2.2、Spring Framework 5.2、Apache Shiro 1.5、J2Cache
* 主框架Spring Boot 2.2、Spring Framework 5.2、Apache Shiro 1.6、J2Cache
* 持久层Apache MyBatis 3.5、Hibernate Validator 6.0、Alibaba Druid 1.1
* 视图层Spring MVC 5.2、Beetl 3.1替换JSP、Bootstrap 3.3、AdminLTE 2.4
* 前端组件jQuery 3.4、jqGrid 4.7、layer 3.1、zTree 3.5、jquery validation
* 工作流引擎Flowable 6.5、符合 BPMN 规范、在线流程设计器、中国式工作流
* 技术选型详情:<http://jeesite.com/?t=273599>
* 技术选型详情:<http://jeesite.com/docs/technology/>
## 内置功能
* <http://jeesite.com/?t=270187>
* <http://jeesite.com/docs/function/>
## 生态系统
* 分布式微服务系统Spring Cloud<https://gitee.com/thinkgem/jeesite4-cloud>
* JFlow工作流引擎<https://gitee.com/thinkgem/jeesite4-jflow> <http://ccflow.org>
* 内容管理模块CMS<https://gitee.com/thinkgem/jeesite4-cms>【敬请期待】
* Flowable业务流程模块BPM<http://jeesite.com/docs/bpm/>
* 内容管理模块CMS<https://gitee.com/thinkgem/jeesite4-cms>
## 快速体验
@@ -40,21 +68,21 @@ JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面
### 本地运行
1. 环境准备:`JDK 1.8 or 11``Maven 3.6+``MySQL 5.7 or 8.0`
2. 下载源码:<https://gitee.com/thinkgem/jeesite4/attach_files>
3. 打开文件:/web`/src/main/resources/config/application.yml` 配置JDBC连接
4. 执行脚本:/web`/bin/init-data.bat` 初始化数据库
5. 执行脚本:/web`/bin/run-tomcat.bat` 启动服务即可
2. 执行命令:`git clone https://gitee.com/thinkgem/jeesite4.git` 下载源码
3. 打开文件:`/web/src/main/resources/config/application.yml` 配置JDBC连接
4. 执行脚本:`/web/bin/init-data.bat` 初始化数据库
5. 执行脚本:`/web/bin/run-tomcat.bat` 启动服务即可
6. 浏览器访问:<http://127.0.0.1:8980/js/> 账号 system 密码 admin
7. 部署常见问题:<http://jeesite.com/?t=284210>
7. 部署常见问题:<http://jeesite.com/docs/faq/>
### 开发环境
1. 部署运行:<http://jeesite.com/?t=267354>
2. 常见问题:<http://jeesite.com/?t=284210>
1. 部署运行文档<http://jeesite.com/docs/install-deploy/>
2. 部署常见问题:<http://jeesite.com/docs/faq/>
## 在线文档
* <http://docs.jeesite.com>
* 在线文档学习地址:<http://docs.jeesite.com>
## 授权协议声明
@@ -65,8 +93,9 @@ JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者规定
需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品)。
7. 关系平台的发展战略考虑,底层部分代码暂未开源,但这不影响您的二次开发
7. 您若套用本平台的一些代码或功能参考,需要在您的软件介绍明显位置说明出处
8. 请知悉社区版用户数不可超过100个最大允许20个用户同时在线不含匿名
9. 无限制版下载:<https://gitee.com/thinkgem/jeesite4/tree/v4.0_dev/>
## 技术服务与支持
@@ -74,27 +103,13 @@ JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面
* **联系方式官方商务QQ[1766571055](http://wpa.qq.com/msgrd?v=3&uin=1766571055&site=qq&menu=yes)**
* 技术服务支持网页:<http://s.jeesite.com>
# 技术交流方式
* QQ 群号:`127515876``209330483``223507718``709534275``730390092``1373527``183903863(外包)`
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>  [【新手必读】](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
* 码云Gitee<https://gitee.com/thinkgem/jeesite4>
* GitHub<https://github.com/thinkgem/jeesite4>
* 作者博客:<https://my.oschina.net/thinkgem>
* **技术服务:**<http://s.jeesite.com>
* 官方网站:<http://jeesite.com>
* 官方论坛:<http://jeesite.net>
* 微信公众号(关注动态):
![JeeSite4微信公众号](https://static.oschina.net/uploads/space/2018/0302/145133_OGZf_941661.jpg "JeeSite4微信公众号")
## 今后如何升级?
尽量不修改 web 项目以外的源码项目,如 jeesite-common、jeesite-modele-core如果修改了请 Pull Requests 上来,否则代码与官方不同步,会将对你的日后升级增加难度。
如果您修改了依赖模块代码,也没关系,这时你需要利用 Git 版本控制工具,与官方仓库代码进行同步,合并代码即可。
每个版本升级,我们都会附带详细更新日志:<http://jeesite.com/?t=273830>
每个版本升级,我们都会附带详细更新日志:<http://jeesite.com/docs/upgrade/>
在这里,你可以看到 JeeSite 新增哪些新功能和改进,在每个版本下都有对应升级方法。

15
common/bin/deploy.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 部署工程版本到Nexus服务器。"
echo ""
cd ..
mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin

View File

@@ -1,18 +0,0 @@
@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD><EBB9A4>Javadoc<6F><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>jar<61><72><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Pjavadoc
cd bin
pause

15
common/bin/package.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程生成war/jar包文件。"
echo ""
cd ..
mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-parent</artifactId>
<version>4.2.0-SNAPSHOT</version>
<version>4.2.2-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@@ -53,12 +53,12 @@
<version>${commons-text.version}</version>
</dependency>
<!-- Apache Tools Ant Tar Zip -->
<!-- Apache Zip Tools
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>${ant.version}</version>
</dependency>
</dependency> -->
<!-- Java serialization -->
<dependency>
@@ -88,12 +88,22 @@
<version>${fastjson.version}</version>
</dependency>
<!-- Java xml -->
<!-- Java xml
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency> -->
<!-- jdk11 JAXB module
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency> -->
<!-- XPath xml -->
<dependency>
@@ -113,12 +123,12 @@
<artifactId>httpclient</artifactId>
</dependency>
<!-- Jsoup HTTP -->
<!-- Jsoup HTTP
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
</dependency> -->
<!-- Email -->
<dependency>
@@ -126,11 +136,11 @@
<artifactId>commons-email</artifactId>
<version>${commons-email.version}</version>
</dependency>
<dependency>
<!-- <dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
</dependency> -->
<!-- User Agent -->
<dependency>
@@ -200,7 +210,7 @@
<version>${zxing.version}</version>
</dependency>
<!-- POI Office Tools -->
<!-- Office Tools -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>

View File

@@ -43,7 +43,11 @@ public class DesUtils {
return "";
}
if ("Base64".equals(secretKey)) {
return EncodeUtils.decodeBase64String(data);
try {
return EncodeUtils.decodeBase64String(data);
}catch (IllegalArgumentException e) {
return "";
}
}
String[] ks = StringUtils.split(secretKey, ",");
if (ks.length >= 3){

View File

@@ -263,7 +263,7 @@ public class EncodeUtils {
// 预编译SQL过滤正则表达式
private static Pattern sqlPattern = Pattern.compile(
"(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|((extractvalue|updatexml)([\\s]*?)\\()|"
+ "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|case when)\\b)",
+ "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|case when|sleep|union|load_file)\\b)",
Pattern.CASE_INSENSITIVE);
/**
@@ -286,8 +286,8 @@ public class EncodeUtils {
return null;
}
// public static void main(String[] args) {
// int i = 0;
public static void main(String[] args) {
int i = 0;
// xssFilter((++i)+"你好,<script>alert(document.cookie)</script>我还在。");
// xssFilter((++i)+"你好,<strong>加粗文字</strong>我还在。");
// xssFilter("<!--HTML-->"+(++i)+"你好,\"><strong>加粗文字</strong>我还在。");
@@ -313,10 +313,11 @@ public class EncodeUtils {
// xssFilter("<!--HTML-->"+(++i)+"你好,<a href='javascript:alert(\"abc\");'>hello</a>我还在。");
// xssFilter("<!--HTML-->"+(++i)+"你好,?abc=def&hello=123&world={\"a\":1}我还在。");
// xssFilter("<!--HTML-->"+(++i)+"你好,?abc=def&hello=123&world={'a':1}我还在。");
// sqlFilter((++i)+"你好select * from xxx where abc=def and 1=1我还在。");
// sqlFilter((++i)+"你好insert into xxx values(1,2,3,4,5)我还在。");
// sqlFilter((++i)+"你好delete from xxx我还在。");
// sqlFilter((++i)+"a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(11111111111111111) end then 1 else 1/0 end");
// }
sqlFilter((++i)+"你好select * from xxx where abc=def and 1=1我还在。");
sqlFilter((++i)+"你好insert into xxx values(1,2,3,4,5)我还在。");
sqlFilter((++i)+"你好delete from xxx我还在。");
sqlFilter((++i)+"你好,a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(11111111111111111) end then 1 else 1/0 end");
sqlFilter((++i)+"你好if(1=2,1,SLEEP(10))");
}
}

View File

@@ -46,6 +46,27 @@ public class ListUtils extends org.apache.commons.collections.ListUtils {
return false;
}
/**
* 是否包含字符串
* @param strs 验证字符串组
* @param strs2 字符串组
* @return 包含返回true
*/
public static boolean inString(List<String> strs, List<String> strs2){
if (strs != null && strs2 != null){
for (String s : strs){
if (s != null) {
for (String s2 : strs2){
if (StringUtils.trim(s).equals(StringUtils.trim(s2))){
return true;
}
}
}
}
}
return false;
}
public static <E> ArrayList<E> newArrayList() {
return new ArrayList<E>();
}

View File

@@ -31,7 +31,7 @@ import org.patchca.word.RandomWordFactory;
public class CaptchaUtils {
private static Random random = new Random();
private static ConfigurableCaptchaService ccs;
private volatile static ConfigurableCaptchaService ccs;
private static WobbleRippleFilterFactory wrff; // 摆波纹
private static DoubleRippleFilterFactory doff; // 双波纹
private static CurvesRippleFilterFactory crff; // 曲线波纹

View File

@@ -13,6 +13,9 @@ import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
@@ -21,9 +24,6 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
@@ -462,14 +462,18 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
}
}
// public static void main(String[] args) {
// zipFiles("target\\classes", "*", "target\\classes.zip");
// unZipFiles("target\\classes.zip", "target\\classes2");
// }
/**
* 压缩文件或目录
* @param srcDirName 压缩的根目录
* @param fileName 根目录下的待压缩的文件名或文件夹名,其中*或""表示跟目录下的全部文件
* @param descFileName 目标zip文件
*/
public static void zipFiles(String srcDirName, String fileName,
String descFileName) {
public static void zipFiles(String srcDirName, String fileName, String descFileName) {
// 判断目录是否存在
if (srcDirName == null) {
logger.debug("文件压缩失败,目录 " + srcDirName + " 不存在!");
@@ -483,8 +487,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
String dirPath = fileDir.getAbsolutePath();
File descFile = new File(descFileName);
try {
ZipOutputStream zouts = new ZipOutputStream(new FileOutputStream(
descFile));
ZipOutputStream zouts = new ZipOutputStream(new FileOutputStream(descFile));
if ("*".equals(fileName) || "".equals(fileName)) {
FileUtils.zipDirectoryToZipFile(dirPath, fileDir, zouts);
} else {
@@ -492,8 +495,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
if (file.isFile()) {
FileUtils.zipFilesToZipFile(dirPath, file, zouts);
} else {
FileUtils
.zipDirectoryToZipFile(dirPath, file, zouts);
FileUtils.zipDirectoryToZipFile(dirPath, file, zouts);
}
}
zouts.close();
@@ -525,7 +527,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
int readByte = 0;
// 获取ZIP文件里所有的entry
@SuppressWarnings("rawtypes")
Enumeration enums = zipFile.getEntries();
Enumeration enums = zipFile.entries();
// 遍历所有entry
while (enums.hasMoreElements()) {
entry = (ZipEntry) enums.nextElement();
@@ -585,12 +587,10 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
// 如果是文件,则调用文件压缩方法
FileUtils
.zipFilesToZipFile(dirPath, files[i], zouts);
FileUtils.zipFilesToZipFile(dirPath, files[i], zouts);
} else {
// 如果是目录,则递归调用
FileUtils.zipDirectoryToZipFile(dirPath, files[i],
zouts);
FileUtils.zipDirectoryToZipFile(dirPath, files[i], zouts);
}
}
}
@@ -646,7 +646,6 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
filePath += "/";
}
int index = filePath.indexOf(dirPaths);
return filePath.substring(index + dirPaths.length());
}
@@ -879,8 +878,9 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
if (f.exists()){
break;
}
if (file.getParentFile() != null){
file = file.getParentFile();
File p = file.getParentFile();
if (p != null){
file = p;
}else{
break;
}
@@ -917,8 +917,9 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
if (f.exists()){
return f.getPath();
}
if (file.getParentFile() != null){
file = file.getParentFile();
File p = file.getParentFile();
if (p != null){
file = p;
}else{
break;
}

View File

@@ -4,25 +4,30 @@
package com.jeesite.common.io;
import java.io.IOException;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.Ordered;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import com.alibaba.fastjson.parser.ParserConfig;
import com.jeesite.common.lang.StringUtils;
/**
* 配置文件加载Boot
* @author ThinkGem
* @version 2018-10-16
* @version 2020-10-26
*/
public class PropertyLoader implements org.springframework.boot.env.PropertySourceLoader, Ordered{
public class PropertyLoader extends PropertiesPropertySourceLoader implements org.springframework.boot.env.PropertySourceLoader, Ordered{
private static boolean isLoadPropertySource = false;
private static boolean isLoadJeeSitePropertySource = false;
private PropertiesPropertySourceLoader propertiesPropertySourceLoader = new PropertiesPropertySourceLoader();
private YamlPropertySourceLoader yamlPropertySourceLoader = new YamlPropertySourceLoader();
@Override
public String[] getFileExtensions() {
@@ -31,13 +36,21 @@ public class PropertyLoader implements org.springframework.boot.env.PropertySour
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
if (!isLoadPropertySource){
isLoadPropertySource = true;
List<PropertySource<?>> propertySources = new ArrayList<>();
if (!isLoadJeeSitePropertySource) {
isLoadJeeSitePropertySource = true;
ParserConfig.getGlobalInstance().setSafeMode(true); // 开启 FastJSON 安全模式
Properties properties = PropertiesUtils.getInstance().getProperties();
return Collections.singletonList(new OriginTrackedMapPropertySource("jeesite", properties));
propertySources.add(new OriginTrackedMapPropertySource("jeesite", properties));
} else {
String ext = FileUtils.getFileExtension(resource.getFilename());
if (StringUtils.inString(ext, propertiesPropertySourceLoader.getFileExtensions())) {
propertySources.addAll(propertiesPropertySourceLoader.load(name, resource));
}else if (StringUtils.inString(ext, yamlPropertySourceLoader.getFileExtensions())) {
propertySources.addAll(yamlPropertySourceLoader.load(name, resource));
}
}
return Collections.emptyList();
return propertySources;
}
@Override

View File

@@ -4,21 +4,9 @@
package com.jeesite.common.mapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@@ -124,167 +112,167 @@ public class XmlMapper extends com.fasterxml.jackson.dataformat.xml.XmlMapper{
return (T) XmlMapper.getInstance().fromXmlString(jsonString, clazz);
}
/**
* xml转map 不带属性
* @param xmlStr
* @param needRootKey 是否需要在返回的map里加根节点键
* @throws DocumentException
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> xmlToMap(String xmlStr, boolean needRootKey) {
try {
Document doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
Map<String, Object> map = (Map<String, Object>) xmlToMap(root);
if (root.elements().size() == 0 && root.attributes().size() == 0) {
return map;
}
if (needRootKey) {
//在返回的map里加根节点键如果需要
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put(root.getName(), map);
return rootMap;
}
return map;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
/**
* xml转map 带属性
* @param xmlStr
* @param needRootKey 是否需要在返回的map里加根节点键
* @return
* @throws DocumentException
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> xmlToMapWithAttr(String xmlStr, boolean needRootKey) {
try {
Document doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
Map<String, Object> map = (Map<String, Object>) xmlToMapWithAttr(root);
if (root.elements().size() == 0 && root.attributes().size() == 0) {
return map; //根节点只有一个文本内容
}
if (needRootKey) {
//在返回的map里加根节点键如果需要
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put(root.getName(), map);
return rootMap;
}
return map;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
/**
* xml转map 不带属性
* @param element
* @return
*/
private static Object xmlToMap(Element element) {
// System.out.println(element.getName());
Map<String, Object> map = new LinkedHashMap<String, Object>();
List<Element> elements = element.elements();
if (elements.size() == 0) {
map.put(element.getName(), element.getText());
if (!element.isRootElement()) {
return element.getText();
}
} else if (elements.size() == 1) {
map.put(elements.get(0).getName(), xmlToMap(elements.get(0)));
} else if (elements.size() > 1) {
// 多个子节点的话就得考虑list的情况了比如多个子节点有节点名称相同的
// 构造一个map用来去重
Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
for (Element ele : elements) {
tempMap.put(ele.getName(), ele);
}
Set<String> keySet = tempMap.keySet();
for (String string : keySet) {
Namespace namespace = tempMap.get(string).getNamespace();
List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// 如果同名的数目大于1则表示要构建list
if (elements2.size() > 1) {
List<Object> list = new ArrayList<Object>();
for (Element ele : elements2) {
list.add(xmlToMap(ele));
}
map.put(string, list);
} else {
// 同名的数量不大于1则直接递归去
map.put(string, xmlToMap(elements2.get(0)));
}
}
}
return map;
}
/**
* xml转map 带属性
* @param element
* @return
*/
private static Object xmlToMapWithAttr(Element element) {
// System.out.println(element.getName());
Map<String, Object> map = new LinkedHashMap<String, Object>();
List<Element> elements = element.elements();
List<Attribute> listAttr = element.attributes(); // 当前节点的所有属性的list
boolean hasAttributes = false;
for (Attribute attr : listAttr) {
hasAttributes = true;
map.put("@" + attr.getName(), attr.getValue());
}
if (elements.size() == 0) {
// map.put(element.getName(), element.getText());
if (hasAttributes) {
map.put("#text", element.getText());
} else {
map.put(element.getName(), element.getText());
}
if (!element.isRootElement()) {
// return element.getText();
if (!hasAttributes) {
return element.getText();
}
}
} else if (elements.size() == 1) {
map.put(elements.get(0).getName(), xmlToMapWithAttr(elements.get(0)));
} else if (elements.size() > 1) {
// 多个子节点的话就得考虑list的情况了比如多个子节点有节点名称相同的
// 构造一个map用来去重
Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
for (Element ele : elements) {
tempMap.put(ele.getName(), ele);
}
Set<String> keySet = tempMap.keySet();
for (String string : keySet) {
Namespace namespace = tempMap.get(string).getNamespace();
List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// 如果同名的数目大于1则表示要构建list
if (elements2.size() > 1) {
List<Object> list = new ArrayList<Object>();
for (Element ele : elements2) {
list.add(xmlToMapWithAttr(ele));
}
map.put(string, list);
} else {
// 同名的数量不大于1则直接递归去
map.put(string, xmlToMapWithAttr(elements2.get(0)));
}
}
}
return map;
}
// /**
// * xml转map 不带属性
// * @param xmlStr
// * @param needRootKey 是否需要在返回的map里加根节点键
// * @throws DocumentException
// */
// @SuppressWarnings("unchecked")
// public static Map<String, Object> xmlToMap(String xmlStr, boolean needRootKey) {
// try {
// Document doc = DocumentHelper.parseText(xmlStr);
// Element root = doc.getRootElement();
// Map<String, Object> map = (Map<String, Object>) xmlToMap(root);
// if (root.elements().size() == 0 && root.attributes().size() == 0) {
// return map;
// }
// if (needRootKey) {
// //在返回的map里加根节点键如果需要
// Map<String, Object> rootMap = new HashMap<String, Object>();
// rootMap.put(root.getName(), map);
// return rootMap;
// }
// return map;
// } catch (DocumentException e) {
// e.printStackTrace();
// }
// return null;
// }
//
// /**
// * xml转map 带属性
// * @param xmlStr
// * @param needRootKey 是否需要在返回的map里加根节点键
// * @return
// * @throws DocumentException
// */
// @SuppressWarnings("unchecked")
// public static Map<String, Object> xmlToMapWithAttr(String xmlStr, boolean needRootKey) {
// try {
// Document doc = DocumentHelper.parseText(xmlStr);
// Element root = doc.getRootElement();
// Map<String, Object> map = (Map<String, Object>) xmlToMapWithAttr(root);
// if (root.elements().size() == 0 && root.attributes().size() == 0) {
// return map; //根节点只有一个文本内容
// }
// if (needRootKey) {
// //在返回的map里加根节点键如果需要
// Map<String, Object> rootMap = new HashMap<String, Object>();
// rootMap.put(root.getName(), map);
// return rootMap;
// }
// return map;
// } catch (DocumentException e) {
// e.printStackTrace();
// }
// return null;
// }
//
// /**
// * xml转map 不带属性
// * @param element
// * @return
// */
// private static Object xmlToMap(Element element) {
// // System.out.println(element.getName());
// Map<String, Object> map = new LinkedHashMap<String, Object>();
// List<Element> elements = element.elements();
// if (elements.size() == 0) {
// map.put(element.getName(), element.getText());
// if (!element.isRootElement()) {
// return element.getText();
// }
// } else if (elements.size() == 1) {
// map.put(elements.get(0).getName(), xmlToMap(elements.get(0)));
// } else if (elements.size() > 1) {
// // 多个子节点的话就得考虑list的情况了比如多个子节点有节点名称相同的
// // 构造一个map用来去重
// Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
// for (Element ele : elements) {
// tempMap.put(ele.getName(), ele);
// }
// Set<String> keySet = tempMap.keySet();
// for (String string : keySet) {
// Namespace namespace = tempMap.get(string).getNamespace();
// List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// // 如果同名的数目大于1则表示要构建list
// if (elements2.size() > 1) {
// List<Object> list = new ArrayList<Object>();
// for (Element ele : elements2) {
// list.add(xmlToMap(ele));
// }
// map.put(string, list);
// } else {
// // 同名的数量不大于1则直接递归去
// map.put(string, xmlToMap(elements2.get(0)));
// }
// }
// }
//
// return map;
// }
//
// /**
// * xml转map 带属性
// * @param element
// * @return
// */
// private static Object xmlToMapWithAttr(Element element) {
// // System.out.println(element.getName());
// Map<String, Object> map = new LinkedHashMap<String, Object>();
// List<Element> elements = element.elements();
//
// List<Attribute> listAttr = element.attributes(); // 当前节点的所有属性的list
// boolean hasAttributes = false;
// for (Attribute attr : listAttr) {
// hasAttributes = true;
// map.put("@" + attr.getName(), attr.getValue());
// }
//
// if (elements.size() == 0) {
// // map.put(element.getName(), element.getText());
// if (hasAttributes) {
// map.put("#text", element.getText());
// } else {
// map.put(element.getName(), element.getText());
// }
//
// if (!element.isRootElement()) {
// // return element.getText();
// if (!hasAttributes) {
// return element.getText();
// }
// }
// } else if (elements.size() == 1) {
// map.put(elements.get(0).getName(), xmlToMapWithAttr(elements.get(0)));
// } else if (elements.size() > 1) {
// // 多个子节点的话就得考虑list的情况了比如多个子节点有节点名称相同的
// // 构造一个map用来去重
// Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
// for (Element ele : elements) {
// tempMap.put(ele.getName(), ele);
// }
// Set<String> keySet = tempMap.keySet();
// for (String string : keySet) {
// Namespace namespace = tempMap.get(string).getNamespace();
// List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// // 如果同名的数目大于1则表示要构建list
// if (elements2.size() > 1) {
// List<Object> list = new ArrayList<Object>();
// for (Element ele : elements2) {
// list.add(xmlToMapWithAttr(ele));
// }
// map.put(string, list);
// } else {
// // 同名的数量不大于1则直接递归去
// map.put(string, xmlToMapWithAttr(elements2.get(0)));
// }
// }
// }
//
// return map;
// }
// public static void main(String[] args) throws Exception {
//

View File

@@ -77,4 +77,9 @@ public class EmailUtils {
return false;
}
// public static void main(String[] args) {
// EmailUtils.send("jeesite_demo@163.com", "jeesitedemo1234", "smtp.163.com",
// "false", "465", "jeesite_demo@163.com", "测试邮件", "测试<b>邮件</b>的内容");
// }
}

View File

@@ -21,23 +21,23 @@ public class SmsUtils {
// String data = props.getProperty("msg.sms.data");
// String prefix = props.getProperty("msg.sms.prefix", "");
// String suffix = props.getProperty("msg.sms.suffix", "");
// Connection conn = Jsoup.connect(url);
// conn.postDataCharset("UTF-8");
// conn.method(Method.POST);
// Map<String, String> dataMap = MapUtils.newHashMap();
// for (String param : StringUtils.split(data, "&")){
// String[] ss = StringUtils.split(param, "=");
// if (ss.length == 1){
// conn.data(ss[0], "");
// dataMap.put(ss[0], "");
// }else if (ss.length == 2){
// conn.data(ss[0], ss[1]);
// dataMap.put(ss[0], ss[1]);
// }
// }
// // 手机号码
// conn.data("mobile", mobile);
// dataMap.put("mobile", mobile);
// // 短信内容
// conn.data("content", prefix + content + suffix);
logger.warn("模拟发送短信成功!请实现 "+SmsUtils.class+" 的 send 方法。内容:"+content);
return "{result:0,message:\"模拟发送短信成功!\"}";
// dataMap.put("content", prefix + content + suffix);
// HttpClientUtils.post(url, dataMap, "UTF-8");
logger.debug("短信内容:" + content + " 手机号码:" + mobile);
logger.warn("短信模拟发送成功!实际并未发送到手机,请实现 " + SmsUtils.class + " 的 send 方法。");
return "{result:0,message:\"短信模拟发送成功!\"}";
}
}

View File

@@ -296,7 +296,8 @@ public class ReflectUtils {
* 改变private/protected的方法为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
if ((!Modifier.isPublic(method.getModifiers())
|| !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
@@ -306,8 +307,9 @@ public class ReflectUtils {
* 改变private/protected的成员变量为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
.isFinal(field.getModifiers())) && !field.isAccessible()) {
if ((!Modifier.isPublic(field.getModifiers())
|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
@@ -333,16 +335,12 @@ public class ReflectUtils {
* @return the index generic declaration, or Object.class if cannot be determined
*/
public static Class getClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
@@ -352,7 +350,6 @@ public class ReflectUtils {
logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}

View File

@@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import com.jeesite.common.callback.MethodCallback;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.lang.DateUtils;
@@ -478,6 +479,10 @@ public class ExcelImport implements Closeable {
// 参数Exception ex, int rowNum, int columnNum
exceptionCallback.execute(ex, i, column);
}
// 导入的数据进行 xss 过滤
if (val != null && val instanceof String) {
val = EncodeUtils.xssFilter(val.toString());
}
// set entity value
if (StringUtils.isNotBlank(ef.attrName())){
ReflectUtils.invokeSetter(e, ef.attrName(), val);

View File

@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.web.http.ServletUtils;
/**
* Cookie工具类
@@ -45,7 +46,8 @@ public class CookieUtils {
* @param uri 路径
*/
public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
setCookie(response, name, value, "/", maxAge);
HttpServletRequest request = ServletUtils.getRequest();
setCookie(response, name, value, request != null ? request.getContextPath() : "", maxAge);
}
/**
@@ -94,7 +96,7 @@ public class CookieUtils {
* @return 值
*/
public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) {
return getCookie(request, response, name, "/", false);
return getCookie(request, response, name, request != null ? request.getContextPath() : "", false);
}
/**

View File

@@ -42,7 +42,11 @@ public class ServletUtils {
// 定义静态文件后缀静态文件排除URI地址
private static String[] staticFiles;
private static String[] staticFileExcludeUri;
private static Boolean favorPathExtension;
private static Boolean favorParameter;
private static Boolean favorHeader;
private static Boolean jsonp;
/**
* 获取当前请求对象
* web.xml: <listener><listener-class>
@@ -97,45 +101,10 @@ public class ServletUtils {
}
/**
* 是否是Ajax异步请求
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request){
String accept = request.getHeader("accept");
if (StringUtils.contains(accept, MediaType.APPLICATION_JSON_VALUE)){
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (StringUtils.contains(xRequestedWith, "XMLHttpRequest")){
return true;
}
String ajaxHeader = request.getHeader("__ajax");
if (StringUtils.inStringIgnoreCase(ajaxHeader, "json", "xml")){
return true;
}
String ajaxParameter = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajaxParameter, "json", "xml")){
return true;
}
String uri = request.getRequestURI();
if (StringUtils.endsWithIgnoreCase(uri, ".json")
|| StringUtils.endsWithIgnoreCase(uri, ".xml")){
return true;
}
return false;
}
/**
* 判断访问URI是否是静态文件请求
* 判断访问URI是否是静态文件请求
* @throws Exception
*/
public static boolean isStaticFile(String uri){
*/
public static boolean isStaticFile(String uri){
if (staticFiles == null){
PropertiesUtils pl = PropertiesUtils.getInstance();
try{
@@ -165,7 +134,64 @@ public class ServletUtils {
return true;
}
return false;
}
}
/**
* 初始化一些个性化配置
* @author ThinkGem
*/
private static void initWebViewConfig() {
if (favorPathExtension == null || favorParameter == null || favorHeader == null || jsonp == null) {
PropertiesUtils props = PropertiesUtils.getInstance();
favorPathExtension = ObjectUtils.toBoolean(props.getProperty("web.view.favorPathExtension", "false"));
favorParameter = ObjectUtils.toBoolean(props.getProperty("web.view.favorParameter", "true"));
favorHeader = ObjectUtils.toBoolean(props.getProperty("web.view.favorHeader", "true"));
jsonp = ObjectUtils.toBoolean(props.getProperty("web.jsonp.enabled", "false"));
}
}
/**
* 是否是Ajax异步请求
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request){
String accept = request.getHeader("accept");
if (StringUtils.contains(accept, MediaType.APPLICATION_JSON_VALUE)){
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (StringUtils.contains(xRequestedWith, "XMLHttpRequest")){
return true;
}
initWebViewConfig();
if (favorPathExtension) {
String uri = request.getRequestURI();
if (StringUtils.endsWithIgnoreCase(uri, ".json")
|| StringUtils.endsWithIgnoreCase(uri, ".xml")){
return true;
}
}
if (favorParameter) {
String ajaxParameter = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajaxParameter, "json", "xml")){
return true;
}
}
if (favorHeader) {
String ajaxHeader = request.getHeader("__ajax");
if (StringUtils.inStringIgnoreCase(ajaxHeader, "json", "xml")){
return true;
}
}
return false;
}
/**
* 返回结果JSON字符串支持JsonP请求参数加__callback=回调函数名)
@@ -222,9 +248,9 @@ public class ServletUtils {
HttpServletResponse response = getResponse();
HttpServletRequest request = getRequest();
if (request != null){
String uri = request.getRequestURI();
if (StringUtils.endsWithIgnoreCase(uri, ".xml") || StringUtils
.equalsIgnoreCase(request.getParameter("__ajax"), "xml")){
String uri = request.getRequestURI(); initWebViewConfig();
if ((favorPathExtension && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (favorParameter && StringUtils.equalsIgnoreCase(request.getParameter("__ajax"), "xml"))){
if (response != null){
response.setContentType(MediaType.APPLICATION_XML_VALUE);
}
@@ -234,7 +260,7 @@ public class ServletUtils {
return XmlMapper.toXml(resultMap);
}
}
if (ObjectUtils.toBoolean(PropertiesUtils.getInstance().getProperty("web.jsonp.enabled"))) {
if (jsonp) {
String functionName = request.getParameter("__callback");
if (StringUtils.isNotBlank(functionName)){
object = new JSONPObject(functionName, resultMap);
@@ -311,12 +337,12 @@ public class ServletUtils {
*/
public static String renderObject(HttpServletResponse response, Object object, Class<?> jsonView) {
HttpServletRequest request = getRequest();
String uri = request.getRequestURI();
if (StringUtils.endsWithIgnoreCase(uri, ".xml") || StringUtils
.equalsIgnoreCase(request.getParameter("__ajax"), "xml")){
String uri = request.getRequestURI(); initWebViewConfig();
if ((favorPathExtension && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (favorParameter && StringUtils.equalsIgnoreCase(request.getParameter("__ajax"), "xml"))){
return renderString(response, XmlMapper.toXml(object));
}
if (ObjectUtils.toBoolean(PropertiesUtils.getInstance().getProperty("web.jsonp.enabled"))) {
if (jsonp) {
String functionName = request.getParameter("__callback");
if (StringUtils.isNotBlank(functionName)){
object = new JSONPObject(functionName, object);
@@ -362,7 +388,9 @@ public class ServletUtils {
type = MediaType.TEXT_PLAIN_VALUE;
}
}
response.setContentType(type);
if (type != null) {
response.setContentType(type);
}
response.getWriter().print(string);
} catch (IOException e) {
e.printStackTrace();

View File

@@ -45,7 +45,7 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
}
}
.main-header .logo {
background-color: #1890ff;
background-color: transparent;
color: #ffffff;
border-bottom: 0 solid transparent;
}

View File

@@ -5,7 +5,12 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
color:#1e5edb;
}
.main-header .navbar {
background-color: #1951be;
background: #1951be;
background: -webkit-gradient(linear, left bottom, right top, color-stop(0, #1951be), color-stop(1, #2780ec));
background: -ms-linear-gradient(left, #1951be, #2780ec);
background: -moz-linear-gradient(left top, #1951be 0%, #2780ec 100%);
background: -o-linear-gradient(#2780ec, #1951be);
filter: progid:DXImageTransform.Microsoft.gradient(GradientType = 1,startColorstr='#2780ec', endColorstr='#1951be');
}
.main-header .navbar .nav > li > a {
color: #ffffff;
@@ -45,7 +50,7 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
}
}
.main-header .logo {
background-color: #1951be;
background-color: transparent;
color: #ffffff;
border-bottom: 0 solid transparent;
}

View File

@@ -1647,8 +1647,8 @@
} else {
if(lay(btn).hasClass(DISABLED)) return that.hint('不在有效日期或时间范围内');
}
that.done();
that.setValue(that.parse()).remove()
that.done();
}
};
active[type] && active[type]();

View File

@@ -307,7 +307,7 @@ Class.pt.creat = function(){
// + config.content[0] + '"></iframe>';
// 2017-5-13 ThinkGem 支持post方式提交iframe
config.content = '<iframe scrolling="'+ (config.content[1]||'auto') +'" allowtransparency="true" id="'
+ doms[4] +''+ times +'" name="'+ doms[4] +''+ times
+ doms[4] + times +'" name="'+ doms[4] +''+ times
+ '" onload="this.className=\'\';" class="layui-layer-load" frameborder="0"></iframe><form id="'
+ doms[4] + '-form' + times+'" action="' + config.content[0] + '" method="post" target="'
+ doms[4] + '' + times +'"></form>';
@@ -357,7 +357,12 @@ Class.pt.creat = function(){
// 2017-5-13 ThinkGem 支持post方式提交iframe
if (config.type == 2){
if (config.method == 'GET' || config.method == 'get'){
that.layero.find('iframe').attr('src', content[0]);
var iframeSrc = content[0] || '', formData = config.contentFormData;
for(var key in formData || {}){
iframeSrc += iframeSrc.indexOf('?') == -1 ? '?' : '&';
iframeSrc += key + '=' + formData[key];
}
that.layero.find('#' + doms[4] + times).attr('src', iframeSrc);
}else{
var form = that.layero.find('#' + doms[4] + '-form' + times), formData = config.contentFormData;
for(var key in formData || {}){

View File

@@ -0,0 +1,15 @@
#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 部署工程版本到Nexus服务器。"
echo ""
cd ..
mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin

View File

@@ -1,18 +0,0 @@
@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD><EBB9A4>Javadoc<6F><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>jar<61><72><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Pjavadoc
cd bin
pause

View File

@@ -0,0 +1,15 @@
#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程生成war/jar包文件。"
echo ""
cd ..
mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-parent</artifactId>
<version>4.2.0-SNAPSHOT</version>
<version>4.2.2-SNAPSHOT</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>

View File

@@ -3,44 +3,34 @@
*/
package com.jeesite.common.shiro.filter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import com.jeesite.common.lang.ExceptionUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.shiro.realm.CasAuthorizingRealm;
import com.jeesite.common.shiro.realm.LoginInfo;
/**
* CAS过滤器
* @author ThinkGem
* @version 2018-7-11
* @version 2020-9-19
*/
@SuppressWarnings("deprecation")
public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
private CasAuthorizingRealm authorizingRealm; // 安全认证类
/**
* 登录成功调用事件
*/
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
// 登录成功后初始化授权信息并处理登录后的操作
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest)request);
// AJAX不支持Redirect改用Forward
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
return false;
return FormAuthenticationFilter.onLoginSuccess((HttpServletRequest)request, (HttpServletResponse)response);
}
/**
@@ -59,15 +49,15 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
return false;
} else {
try {
if (ae != null && StringUtils.startsWith(ae.getMessage(), "msg:")){
String message = ExceptionUtils.getExceptionMessage(ae);
if (StringUtils.isNotBlank(message)){
request.setAttribute("exception", ae);
request.setAttribute("message", message);
request.getRequestDispatcher("/error/403").forward(request, response);
}else{
WebUtils.issueRedirect(request, response, getLoginUrl());
}
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
return false;
@@ -75,7 +65,7 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
}
public void setAuthorizingRealm(CasAuthorizingRealm authorizingRealm) {
this.authorizingRealm = authorizingRealm;
}
}

View File

@@ -34,7 +34,6 @@ import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.network.IpUtils;
import com.jeesite.common.shiro.authc.FormToken;
import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
import com.jeesite.common.shiro.realm.LoginInfo;
import com.jeesite.common.web.CookieUtils;
import com.jeesite.common.web.http.ServletUtils;
import com.jeesite.modules.sys.entity.Log;
@@ -45,20 +44,20 @@ import com.jeesite.modules.sys.utils.UserUtils;
/**
* 表单验证(包含验证码)过滤类
* @author ThinkGem
* @version 2020-4-13
* @version 2020-9-19
*/
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
public static final String CAPTCHA_PARAM = "validCode"; // 验证码
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
public static final String CAPTCHA_PARAM = "validCode"; // 验证码
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
private static final Logger logger = LoggerFactory.getLogger(FormAuthenticationFilter.class);
private BaseAuthorizingRealm authorizingRealm; // 安全认证类
private static FormAuthenticationFilter instance;
private Cookie rememberUserCodeCookie; // 记住用户名Cookie
private BaseAuthorizingRealm authorizingRealm;
private Cookie rememberUserCodeCookie; // 记住用户名Cookie
/**
* 构造方法
@@ -68,8 +67,16 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
rememberUserCodeCookie = new SimpleCookie(REMEMBER_USERCODE_PARAM);
rememberUserCodeCookie.setHttpOnly(true);
rememberUserCodeCookie.setMaxAge(Cookie.ONE_YEAR);
instance = this;
}
/**
* 创建登录授权令牌
*/
public static FormToken newToken(HttpServletRequest request, HttpServletResponse response) {
return (FormToken)instance.createToken(request, response);
}
/**
* 创建登录授权令牌
*/
@@ -94,13 +101,13 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
}
// 登录用户名解密(解决登录用户名明文传输安全问题)
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(secretKey)){
username = DesUtils.decode(username, secretKey);
if (StringUtils.isBlank(username)){
logger.info("登录账号为空或解码错误.");
}
}
// 登录成功后,判断是否需要记住用户名
// 登录判断是否需要记住用户名
if (WebUtils.isTrue(request, REMEMBER_USERCODE_PARAM)) {
rememberUserCodeCookie.setValue(EncodeUtils.encodeUrl(EncodeUtils.xssFilter(username)));
rememberUserCodeCookie.saveTo((HttpServletRequest)request, (HttpServletResponse)response);
@@ -121,7 +128,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
}
// 登录密码解密(解决登录密码明文传输安全问题)
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
if (StringUtils.isNotBlank(password) && StringUtils.isNotBlank(secretKey)){
password = DesUtils.decode(password, secretKey);
if (StringUtils.isBlank(password)){
logger.info("登录密码为空或解码错误.");
@@ -160,7 +167,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
}
// 登录用户名解密(解决登录用户名明文传输安全问题)
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
if (StringUtils.isNotBlank(captcha) && StringUtils.isNotBlank(secretKey)){
captcha = DesUtils.decode(captcha, secretKey);
}
return captcha;
@@ -241,30 +248,51 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
return super.executeLogin(request, response);
}
/**
* 登录成功调用事件(静态方便其他位置调用)
*/
public static boolean onLoginSuccess(HttpServletRequest request, HttpServletResponse response) {
try {
return instance.onLoginSuccess(null, null, request, response);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 登录成功调用事件
*/
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
// 登录成功后初始化授权信息并处理登录后的操作
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest) request);
authorizingRealm.onLoginSuccess(UserUtils.getLoginInfo(), (HttpServletRequest)request);
// AJAX不支持Redirect改用Forward
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
try {
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 登录失败调用事件(静态方便其他位置调用)
*/
public static boolean onLoginFailure(AuthenticationException e, HttpServletRequest request, HttpServletResponse response) {
return instance.onLoginFailure(null, e, request, response);
}
/**
* 登录失败调用事件
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
String message = StringUtils.EMPTY;
if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) {
message = Global.getText("sys.login.failure");
} else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
message = StringUtils.replace(e.getMessage(), "msg:", "");
} else if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) {
message = Global.getText("sys.login.failure");
} else {
message = Global.getText("sys.login.error");
logger.error(message, e); // 输出到日志文件
@@ -272,20 +300,20 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
request.setAttribute(EXCEPTION_ATTRIBUTE_NAME, e);
request.setAttribute(MESSAGE_PARAM, message);
// 登录操作如果是Ajax操作直接返回登录信息字符串。
if (ServletUtils.isAjaxRequest(((HttpServletRequest) request))){
Map<String, Object> data = getLoginFailureData(((HttpServletRequest) request), ((HttpServletResponse) response));
ServletUtils.renderResult(((HttpServletResponse) response), Global.TRUE, message, data);
return false;
// AJAX不支持Redirect改用Forward
try {
String loginFailureUrl = Global.getProperty("adminPath")+"/loginFailure";
request.getRequestDispatcher(loginFailureUrl).forward(request, response);
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
this.authorizingRealm = authorizingRealm;
return false;
}
/**
* 获取登录页面数据
* @author ThinkGem
*/
public static Map<String, Object> getLoginData(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> data = MapUtils.newHashMap();
@@ -294,7 +322,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
for (Entry<String, Object> entry : paramMap.entrySet()){
data.put(ServletUtils.EXT_PARAMS_PREFIX + entry.getKey(), entry.getValue());
}
// 如果已登录,再次访问主页,则退出原账号。
if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){
CookieUtils.setCookie(response, "LOGINED", "false");
@@ -316,6 +344,10 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
return data;
}
/**
* 获取登录失败数据
* @author ThinkGem
*/
public static Map<String, Object> getLoginFailureData(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> data = MapUtils.newHashMap();
@@ -362,4 +394,9 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
data.put("result", Global.FALSE);
return data;
}
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
this.authorizingRealm = authorizingRealm;
}
}

View File

@@ -38,16 +38,17 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
try {
Object principal = subject.getPrincipal();
if (principal != null){
// // 记录用户退出日志(@Deprecated v4.0.5支持setAuthorizingRealm之后版本可删除此if子句
// if (authorizingRealm == null){
// LogUtils.saveLog(UserUtils.getUser(), ServletUtils.getRequest(),
// "系统退出", Log.TYPE_LOGIN_LOGOUT);
// }
// else{
// 退出成功之前初始化授权信息并处理登录后的操作
authorizingRealm.onLogoutSuccess((LoginInfo)subject.getPrincipal(),
(HttpServletRequest)request);
// }
LoginInfo loginInfo = (LoginInfo)principal;
// 退出成功之前调用退出事件,方便记录日志等相关销毁工作
authorizingRealm.onLogoutSuccess(loginInfo, (HttpServletRequest)request);
// 设定了用户类型的登录页面,则退出到对应用户类型的登录页面
String userType = loginInfo.getParam("userType");
if(StringUtils.isNotBlank(userType)){
redirectUrl += StringUtils.contains(redirectUrl, "?") ? "&" : "?";
redirectUrl += "param_userType=" + userType;
}
}
// 退出登录
subject.logout();

View File

@@ -38,7 +38,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
/**
* 系统安全认证实现类
* @author ThinkGem
* @version 2018-7-11
* @version 2020-9-19
*/
@SuppressWarnings("deprecation")
public class CasAuthorizingRealm extends BaseAuthorizingRealm {
@@ -92,7 +92,7 @@ public class CasAuthorizingRealm extends BaseAuthorizingRealm {
casToken.setUserId(casPrincipal.getName());
// 生成登录信息对象
FormToken token = new FormToken();
FormToken token = new FormToken(request);
token.setUsername(casPrincipal.getName());
Map<String, Object> params = MapUtils.newHashMap();
params.putAll(casPrincipal.getAttributes());

View File

@@ -11,9 +11,10 @@ import com.jeesite.modules.sys.entity.Employee;
* 员工管理DAO接口
* @author ThinkGem
* @version 2017-03-25
* 通过 UserUtils.loadRefObj() 加载引用类型对象时需要给MyBatisDao指定引用entity类型。
* 通过 user.getRefObj() 获取引用对象时,需要给 \@MyBatisDao 指定引用 entity 类型。
* 但是,在 4.2.0+ 版本中,新增了 userTypeMap 指定 service所以无需设置 entity 类型。
*/
@MyBatisDao(entity=Employee.class)
@MyBatisDao(entity = Employee.class)
public interface EmployeeDao extends CrudDao<Employee> {
}

View File

@@ -36,7 +36,7 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@Column(name="emp_no", attrName="empNo", label="员工工号"),
@Column(name="emp_name", attrName="empName", label="员工姓名", queryType=QueryType.LIKE),
@Column(name="emp_name_en", attrName="empNameEn", label="英文名", queryType=QueryType.LIKE),
}),
}),
@JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
on="o.office_code=e.office_code", attrName="employee.office",
columns={
@@ -52,7 +52,7 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@Column(name="address", label="联系地址"),
@Column(name="zip_code", label="邮政编码"),
@Column(name="email", label="邮箱"),
}),
}),
@JoinTable(type=Type.LEFT_JOIN, entity=Company.class, alias="c",
on="c.company_code=e.company_code", attrName="employee.company",
columns={
@@ -62,7 +62,7 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@Column(name="view_code", label="公司代码"),
@Column(name="company_name", label="公司名称", isQuery=false),
@Column(name="full_name", label="公司全称"),
}),
}),
@JoinTable(type=Type.LEFT_JOIN, entity=Area.class, alias="ar",
on="ar.area_code = c.area_code", attrName="employee.company.area",
columns={
@@ -70,6 +70,10 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@Column(name="area_name", label="区域名称", isQuery=false),
@Column(name="area_type", label="区域类型"),
}),
// @JoinTable(type=Type.LEFT_JOIN, entity=User.class, attrName="this", alias="u",
// on="u.user_code = a.create_by", columns={
// @Column(name="user_name", attrName="createByName", label="用户名称", isQuery=false),
// }),
},
// extFromKeys="dsfOfficeFrom, dsfCompanyFrom",
// extWhereKeys="dsfOfficeWhere, dsfCompanyWhere",
@@ -107,7 +111,7 @@ public class EmpUser extends User {
@ExcelField(title="最后登录", attrName="lastLoginDate", align=Align.CENTER, words=20, sort=900, type=ExcelField.Type.EXPORT),
})
public Employee getEmployee(){
Employee employee = (Employee)super.getRefObj();
Employee employee = super.getRefObj();
if (employee == null){
employee = new Employee(getRefCode());
super.setRefObj(employee);

View File

@@ -54,7 +54,7 @@ public class EmpUtils {
*/
public static Employee get(User user){
if (user != null && User.USER_TYPE_EMPLOYEE.equals(user.getUserType())){
return (Employee)user.getRefObj();
return user.getRefObj();
}
return null;
}

View File

@@ -1,13 +1,15 @@
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.modules.sys.web.user;
package com.jeesite.modules.sys.web;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Controller;
@@ -17,12 +19,15 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jeesite.common.codec.DesUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.msg.EmailUtils;
import com.jeesite.common.msg.SmsUtils;
import com.jeesite.common.service.ServiceException;
import com.jeesite.common.shiro.authc.FormToken;
import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
import com.jeesite.common.web.BaseController;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.UserService;
@@ -38,28 +43,77 @@ import io.swagger.annotations.ApiOperation;
/**
* 账号自助服务Controller
* @author ThinkGem
* @version 2017-12-7
* @version 2020-9-20
*/
@Controller
@RequestMapping(value = "/account")
@ConditionalOnProperty(name="web.core.enabled", havingValue="true", matchIfMissing=true)
@Api(tags = "Account / 账号自助服务、找回密码、账号注册")
@Api(tags = "Account / 账号服务:验证码登录、找回密码、账号注册")
public class AccountController extends BaseController{
@Autowired
private UserService userService;
/**
* 获取登录短信或邮件验证码
* @param validCode 图片验证码防止重复机器人
* @param validType 验证方式mobileemail
* @author ThinkGem
*/
@PostMapping(value = "getLoginValidCode")
@ResponseBody
@ApiOperation(value = "获取登录的短信或邮件验证码")
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "登录账号", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "validCode", value = "图片验证码,防止重复机器人", required = true),
@ApiImplicitParam(name = "validType", value = "验证方式mobile、email", required = true),
})
public String getLoginValidCode(String username, String validCode, String validType, HttpServletRequest request) {
return getValidCode("login", username, validCode, validType, request, "登录验证码");
}
/**
* 根据短信或邮件验证码登录系统
* @author ThinkGem
*/
@PostMapping(value = "loginByValidCode")
@ResponseBody
@ApiOperation(value = "根据短信或邮件验证码登录系统")
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "登录账号", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "loginValidCode", value = "手机或邮箱接受的验证码", required = true),
})
public String loginByValidCode(String username, String loginValidCode, HttpServletRequest request, HttpServletResponse response) {
if (!Global.getConfigToBoolean("user.loginByValidCode", "true")) {
return renderResult(Global.FALSE, "验证码登录未开启请设置user.loginByValidCode=true");
}
FormToken formToken = FormAuthenticationFilter.newToken(request, response);
String s = validValidCode("login", formToken.getUsername(), loginValidCode, request);
if (s != null) {
return s;
}
// 登录系统
try {
formToken.setInnerLogin(true); // 因为手机验证码已验证所以无需再进行验证密码
UserUtils.getSubject().login(formToken);
FormAuthenticationFilter.onLoginSuccess(request, response);
} catch (AuthenticationException e) {
FormAuthenticationFilter.onLoginFailure(e, request, response);
}
return null;
}
/**
* 忘记密码页面
*/
@GetMapping(value = "forgetPwd")
@ApiOperation(value = "忘记密码页面")
public String forgetPwd(Model model) {
return "modules/sys/account/forgetPwd";
return "modules/sys/forgetPwd";
}
/**
* 获取找回密码短信邮件验证码
* 获取找回密码短信邮件验证码
* @param validCode 图片验证码防止重复机器人
* @param validType 验证方式mobileemail
*/
@@ -72,41 +126,7 @@ public class AccountController extends BaseController{
@ApiImplicitParam(name = "validType", value = "验证方式mobile、email", required = true),
})
public String getFpValidCode(User user, String validCode, String validType, HttpServletRequest request) {
// 校验图片验证码防止重复机器人
if (!ValidCodeUtils.validate(request, validCode)){
return renderResult(Global.FALSE, text("图片验证码不正确或已失效,请点击图片刷新!"));
}
if (!"mobile".equals(validType) && !"email".equals(validType)){
return renderResult(Global.FALSE, text("非法操作。"));
}
User u = UserUtils.getByLoginCode(user.getLoginCode());
if(u == null){
return renderResult(Global.FALSE, text("登录账号不正确!"));
}
if("mobile".equals(validType) && StringUtils.isBlank(u.getMobile())){
return renderResult(Global.FALSE, text("该账号未设置手机号码!"));
}else if("email".equals(validType) && StringUtils.isBlank(u.getEmail())){
return renderResult(Global.FALSE, text("该账号未设置邮件地址!"));
}
// 操作是否频繁验证 如果离上次获取验证码小于20秒则提示操作频繁
Date date = (Date)UserUtils.getCache("fpLastDate");
if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){
return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!"));
}else{
UserUtils.putCache("fpLastDate", new Date());
}
// 生成验证码并缓存
String fpValidCode = StringUtils.getRandomNum(6);
UserUtils.putCache("fpUserCode", u.getUserCode());
UserUtils.putCache("fpLoginCode", u.getLoginCode());
UserUtils.putCache("fpValidCode", fpValidCode);
// 发送邮箱或短信验证码
if("mobile".equals(validType)){
return sendSmsValidCode(u, fpValidCode, text("找回密码"));
}else if("email".equals(validType)){
return sendEmailValidCode(u, fpValidCode, text("找回密码"));
}
return null;
return getValidCode("fp", user.getLoginCode(), validCode, validType, request, "找回密码");
}
/**
@@ -121,39 +141,98 @@ public class AccountController extends BaseController{
@ApiImplicitParam(name = "password", value = "新密码", required = true, paramType="query", type="String"),
})
public String savePwdByValidCode(User user, String fpValidCode, HttpServletRequest request) {
String userCode = (String)UserUtils.getCache("fpUserCode");
String loginCode = (String)UserUtils.getCache("fpLoginCode");
String validCode = (String)UserUtils.getCache("fpValidCode");
Date date = (Date)UserUtils.getCache("fpLastDate");
String userCode = UserUtils.getCache("fp" + "UserCode");
String s = validValidCode("fp", user.getLoginCode(), fpValidCode, request);
if (s != null) {
return s;
}
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
user.setPassword(DesUtils.decode(user.getPassword(), secretKey));
}
// 更新为新密码
try{
userService.updatePassword(userCode, user.getPassword());
}catch(ServiceException se){
return renderResult(Global.FALSE, se.getMessage());
}
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码找回成功!", user.getLoginCode()));
}
/**
* 获取验证码
* @author ThinkGem
*/
private String getValidCode(String type, String loginCode, String validCode, String validType, HttpServletRequest request, String msgTitle) {
// 校验图片验证码防止重复机器人
if (!ValidCodeUtils.validate(request, validCode)){
return renderResult(Global.FALSE, text("图片验证码不正确或已失效,请点击图片刷新!"));
}
if (!"mobile".equals(validType) && !"email".equals(validType)){
return renderResult(Global.FALSE, text("非法操作。"));
}
User u = UserUtils.getByLoginCode(loginCode);
if(u == null){
return renderResult(Global.FALSE, text("登录账号不正确!"));
}
if("mobile".equals(validType) && StringUtils.isBlank(u.getMobile())){
return renderResult(Global.FALSE, text("该账号未设置手机号码!"));
}else if("email".equals(validType) && StringUtils.isBlank(u.getEmail())){
return renderResult(Global.FALSE, text("该账号未设置邮件地址!"));
}
// 操作是否频繁验证 如果离上次获取验证码小于20秒则提示操作频繁
Date date = (Date)UserUtils.getCache(type + "LastDate");
if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){
return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!"));
}else{
UserUtils.putCache(type + "LastDate", new Date());
}
// 生成验证码并缓存
String loginValidCode = StringUtils.getRandomNum(6);
UserUtils.putCache(type + "UserCode", u.getUserCode());
UserUtils.putCache(type + "LoginCode", u.getLoginCode());
UserUtils.putCache(type + "ValidCode", loginValidCode);
// 发送邮箱或短信验证码
if("mobile".equals(validType)){
return sendSmsValidCode(u, loginValidCode, text(msgTitle));
}else if("email".equals(validType)){
return sendEmailValidCode(u, loginValidCode, text(msgTitle));
}
return null;
}
/**
* 验证验证码
* @author ThinkGem
*/
private String validValidCode(String type, String loginCode, String loginValidCode, HttpServletRequest request) {
String userCode = UserUtils.getCache(type + "UserCode");
String loginCode2 = UserUtils.getCache(type + "LoginCode");
String validCode = UserUtils.getCache(type + "ValidCode");
Date date = (Date)UserUtils.getCache(type + "LastDate");
// 一同验证保存的用户名和验证码是否正确如果只校验验证码不验证用户名则会有获取验证码后修改用户名的漏洞
if (!(userCode != null && loginCode != null && loginCode.equals(user.getLoginCode()))){
if (!(userCode != null && loginCode != null && loginCode.equals(loginCode2))){
return renderResult(Global.FALSE, text("请重新获取验证码!"));
}
// 清理验证码验证码只允许使用一次
UserUtils.removeCache("fpUserCode");
UserUtils.removeCache("fpLoginCode");
UserUtils.removeCache("fpValidCode");
UserUtils.removeCache("fpLastDate");
// 验证码是否超时
boolean isTimeout = true;
String validTime = Global.getConfig("sys.account.validCodeTimeout", "10"); //验证码有效时间单位分钟0表示不限制默认值10
if("0".equals(validTime) || (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 60*Long.parseLong(validTime))){
isTimeout = false;
}
if (!(validCode != null && validCode.equals(fpValidCode) && !isTimeout)){
if (!(validCode != null && validCode.equals(loginValidCode) && !isTimeout)){
return renderResult(Global.FALSE, text("验证码不正确或已失效,请重新获取验证码!"));
}
// 更新为新密码
try{
userService.updatePassword(userCode, user.getPassword());
}catch(ServiceException se){
return renderResult(Global.FALSE, se.getMessage());
}
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码修改成功!", loginCode));
// 验证成功后清理缓存
UserUtils.removeCache(type + "UserCode");
UserUtils.removeCache(type + "LoginCode");
UserUtils.removeCache(type + "ValidCode");
UserUtils.removeCache(type + "LastDate");
return null;
}
/**
@@ -217,17 +296,21 @@ public class AccountController extends BaseController{
@ApiImplicitParam(name = "password", value = "新密码", required = true, paramType="query", type="String"),
})
public String savePwdByPwdQuestion(User user, HttpServletRequest request) {
String userCode = (String)UserUtils.getCache("fpUserCode");
String loginCode = (String)UserUtils.getCache("fpLoginCode");
String userCode = UserUtils.getCache("fpUserCode");
String loginCode = UserUtils.getCache("fpLoginCode");
// 一同验证保存的用户名和验证码是否正确如果只校验验证码不验证用户名则会有获取验证码后修改用户名的漏洞
if (!(userCode != null && loginCode != null && loginCode.equals(user.getLoginCode()))){
return renderResult(Global.FALSE, text("请重新获取保密问题!"));
}
// 清理保密问题每次获取只允许使用一次
UserUtils.removeCache("fpUserCode");
UserUtils.removeCache("fpLoginCode");
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
user.setPwdQuestionAnswer(DesUtils.decode(user.getPwdQuestionAnswer(), secretKey));
user.setPwdQuestionAnswer2(DesUtils.decode(user.getPwdQuestionAnswer2(), secretKey));
user.setPwdQuestionAnswer3(DesUtils.decode(user.getPwdQuestionAnswer3(), secretKey));
user.setPassword(DesUtils.decode(user.getPassword(), secretKey));
}
// 验证三个密保问题是否正确
User u = UserUtils.getByLoginCode(user.getLoginCode());
@@ -244,7 +327,12 @@ public class AccountController extends BaseController{
}catch(ServiceException se){
return renderResult(Global.FALSE, se.getMessage());
}
return renderResult(Global.TRUE, text("验证通过"));
// 更新密码后清理缓存
UserUtils.removeCache("fpUserCode");
UserUtils.removeCache("fpLoginCode");
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码找回成功!", user.getLoginCode()));
}
/**
@@ -254,7 +342,7 @@ public class AccountController extends BaseController{
@GetMapping(value = "registerUser")
@ApiOperation(value = "用户注册页面")
public String registerUser(User user, HttpServletRequest request) {
return "modules/sys/account/registerUser";
return "modules/sys/registerUser";
}
/**
@@ -352,14 +440,14 @@ public class AccountController extends BaseController{
if (!"true".equals(Global.getConfig("sys.account.registerUser"))){
return renderResult(Global.FALSE, text("当前系统没有开启注册功能!"));
}
String corpCode = (String)UserUtils.getCache("regCorpCode");
String corpName = (String)UserUtils.getCache("regCorpName");
String userType = (String)UserUtils.getCache("regUserType");
String loginCode = (String)UserUtils.getCache("regLoginCode");
String userName = (String)UserUtils.getCache("regUserName");
String email = (String)UserUtils.getCache("regEmail");
String mobile = (String)UserUtils.getCache("regMobile");
String validCode = (String)UserUtils.getCache("regValidCode");
String corpCode = UserUtils.getCache("regCorpCode");
String corpName = UserUtils.getCache("regCorpName");
String userType = UserUtils.getCache("regUserType");
String loginCode = UserUtils.getCache("regLoginCode");
String userName = UserUtils.getCache("regUserName");
String email = UserUtils.getCache("regEmail");
String mobile = UserUtils.getCache("regMobile");
String validCode = UserUtils.getCache("regValidCode");
Date date = (Date)UserUtils.getCache("regLastDate");
// 一同验证保存的用户名和验证码是否正确如果只校验验证码不验证用户名则会有获取验证码后修改用户名的漏洞
@@ -391,6 +479,10 @@ public class AccountController extends BaseController{
}
u.setLoginCode(loginCode);
u.setUserName(userName);
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
if (StringUtils.isNotBlank(secretKey)){
user.setPassword(DesUtils.decode(user.getPassword(), secretKey));
}
u.setPassword(user.getPassword());
u.setEmail(email);
u.setMobile(mobile);
@@ -399,7 +491,7 @@ public class AccountController extends BaseController{
u.setStatus(User.STATUS_AUDIT); // 待审核状态
userService.save(u);
// 验证成功后清理验证码验证码只允许使用一次
// 注册用户后清理缓存
UserUtils.removeCache("regCorpCode");
UserUtils.removeCache("regCorpName");
UserUtils.removeCache("regUserType");
@@ -408,7 +500,7 @@ public class AccountController extends BaseController{
UserUtils.removeCache("regValidCode");
UserUtils.removeCache("regLastDate");
return renderResult(Global.TRUE, text("恭喜你,您的账号 "+u.getLoginCode()+" 注册成功!"));
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 注册成功!", u.getLoginCode()));
}
/**

View File

@@ -18,7 +18,6 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.annotation.JsonView;
@@ -37,16 +36,16 @@ import com.jeesite.modules.sys.utils.UserUtils;
/**
* 登录Controller
* @author ThinkGem
* @version 2020-4-13
* @version 2020-9-19
*/
@Controller
@RequestMapping(value = "${adminPath}")
public class LoginController extends BaseController{
/**
* 管理登录
* 登录页面
*/
@RequestMapping(value = "login", method = RequestMethod.GET)
@RequestMapping(value = "login")
public String login(HttpServletRequest request, HttpServletResponse response, Model model) {
// 地址中如果包含JSESSIONID则跳转一次去掉JSESSIONID信息。
if (StringUtils.containsIgnoreCase(request.getRequestURI(), ";JSESSIONID=")){
@@ -94,9 +93,9 @@ public class LoginController extends BaseController{
}
/**
* 登录失败,真正登录的POST请求由Filter完成
* 登录失败,返回错误信息
*/
@RequestMapping(value = "login", method = RequestMethod.POST)
@RequestMapping(value = "loginFailure")
public String loginFailure(HttpServletRequest request, HttpServletResponse response, Model model) {
LoginInfo loginInfo = UserUtils.getLoginInfo();
@@ -190,7 +189,7 @@ public class LoginController extends BaseController{
// 设置共享SessionId的Cookie值第三方系统使用
String cookieName = Global.getProperty("session.shareSessionIdCookieName");
if (StringUtils.isNotBlank(cookieName)){
CookieUtils.setCookie((HttpServletResponse)response, cookieName, (String)session.getId());
CookieUtils.setCookie(response, cookieName, (String)session.getId(), "/");
}
// 如果登录设置了语言,则切换语言
if (loginInfo.getParam("lang") != null){
@@ -200,6 +199,9 @@ public class LoginController extends BaseController{
// 获取登录成功后跳转的页面
String successUrl = request.getParameter("__url");
if (StringUtils.isBlank(successUrl)){
successUrl = (String)request.getAttribute("__url");
}
if (StringUtils.isBlank(successUrl)){
successUrl = Global.getProperty("shiro.successUrl");
}
@@ -272,16 +274,16 @@ public class LoginController extends BaseController{
}
/**
* 获取侧边栏菜单数据
* 侧边栏菜单数据
*/
@RequiresPermissions("user")
@RequestMapping(value = "index/menuTree")
public String indexMenuTree(String parentCode) {
return "modules/sys/sysIndex/menuTree";
return "modules/sys/menuTree";
}
/**
* 获取当前用户权限字符串数据(移动端用)
* 当前用户权限字符串数据(移动端用)
*/
@RequiresPermissions("user")
@RequestMapping(value = "authInfo")
@@ -291,7 +293,7 @@ public class LoginController extends BaseController{
}
/**
* 获取当前用户菜单数据(移动端用)
* 当前用户菜单数据(移动端用)
*/
@RequiresPermissions("user")
@RequestMapping(value = "menuTree")
@@ -334,7 +336,7 @@ public class LoginController extends BaseController{
}
/**
* 切换主题
* 切换主题风格
*/
@RequiresPermissions("user")
@RequestMapping(value = "switchSkin/{skinName}")

View File

@@ -18,6 +18,7 @@ import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.shiro.authc.FormToken;
import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
import com.jeesite.common.web.BaseController;
import com.jeesite.common.web.http.ServletUtils;
import com.jeesite.modules.sys.entity.User;
@@ -26,7 +27,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
/**
* 单点登录Controller
* @author ThinkGem
* @version 2017-03-25
* @version 2020-9-19
*/
@Controller
public class SsoController extends BaseController{
@@ -63,24 +64,20 @@ public class SsoController extends BaseController{
// 通过令牌登录系统
if (token != null){
try {
FormToken upToken = new FormToken();
upToken.setUsername(username); // 登录用户名
upToken.setSsoToken(token); // 单点登录令牌
upToken.setParams(ServletUtils.getExtParams(request)); // 登录附加参数
UserUtils.getSubject().login(upToken);
if (ServletUtils.isAjaxRequest(request)){
return ServletUtils.renderResult(response, Global.TRUE, text("账号登录成功"));
}else{
return REDIRECT + EncodeUtils.decodeUrl2(url);
}
// FormToken 构造方法的三个参数:登录名、单点登录的令牌秘钥、请求对象
UserUtils.getSubject().login(new FormToken(username, token, request));
request.setAttribute("__url", EncodeUtils.decodeUrl2(url));
FormAuthenticationFilter.onLoginSuccess(request, response);
} catch (AuthenticationException e) {
if (!e.getMessage().startsWith("msg:")){
throw new AuthenticationException("msg:登录失败,请联系管理员。", e);
}
throw e;
FormAuthenticationFilter.onLoginFailure(e, request, response);
}
return null;
}
return "error/403";
}
// public static void main(String[] args) {
// System.out.println(UserUtils.getSsoToken("system"));
// }
}

View File

@@ -268,6 +268,7 @@ public class CorpAdminController extends BaseController {
if (UserUtils.getUser().isSuperAdmin()){
User where = new User();
where.setCorpCode_(corpCode);
where.setPage(new Page<>(1, 1, -1));
List<User> list = userService.findCorpList(where);
if (list.size() > 0){
User user = list.get(0);

View File

@@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONValidator;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.collect.MapUtils;
@@ -31,7 +33,6 @@ import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.DateUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.shiro.realm.AuthorizingRealm;
import com.jeesite.common.utils.excel.ExcelExport;
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
@@ -73,10 +74,7 @@ public class EmpUserController extends BaseController {
@ModelAttribute
public EmpUser get(String userCode, boolean isNewRecord) {
EmpUser empUser = new EmpUser();
empUser.setUserCode(userCode);
empUser.setIsNewRecord(isNewRecord);
return empUserService.getAndValid(empUser);
return empUserService.get(userCode, isNewRecord);
}
@RequiresPermissions("sys:empUser:view")
@@ -172,12 +170,11 @@ public class EmpUserController extends BaseController {
if (!Global.TRUE.equals(checkEmpNo(old != null ? old.getEmployee().getEmpNo() : "", empUser.getEmployee().getEmpNo()))) {
return renderResult(Global.FALSE, text("保存用户失败,员工工号''{0}''已存在", empUser.getEmployee().getEmpNo()));
}
if (StringUtils.inString(op, Global.OP_ADD, Global.OP_EDIT)
&& UserUtils.getSubject().isPermitted("sys:empUser:edit")){
Subject subject = UserUtils.getSubject();
if (StringUtils.inString(op, Global.OP_ADD, Global.OP_EDIT) && subject.isPermitted("sys:empUser:edit")){
empUserService.save(empUser);
}
if (StringUtils.inString(op, Global.OP_ADD, Global.OP_AUTH)
&& UserUtils.getSubject().isPermitted("sys:empUser:authRole")){
if (StringUtils.inString(op, Global.OP_ADD, Global.OP_AUTH) && subject.isPermitted("sys:empUser:authRole")){
userService.saveAuth(empUser);
}
return renderResult(Global.TRUE, text("保存用户''{0}''成功", empUser.getUserName()));
@@ -427,7 +424,7 @@ public class EmpUserController extends BaseController {
@RequestMapping(value = "empUserSelect")
public String empUserSelect(EmpUser empUser, String selectData, Model model) {
String selectDataJson = EncodeUtils.decodeUrl(selectData);
if (JsonMapper.fromJson(selectDataJson, Map.class) != null){
if (selectDataJson != null && JSONValidator.from(selectDataJson).validate()){
model.addAttribute("selectData", selectDataJson);
}
model.addAttribute("empUser", empUser);

View File

@@ -3,8 +3,6 @@
*/
package com.jeesite.modules.sys.web.user;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -17,12 +15,12 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONValidator;
import com.jeesite.common.codec.DesUtils;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.service.ServiceException;
import com.jeesite.common.web.BaseController;
import com.jeesite.modules.sys.entity.User;
@@ -84,7 +82,7 @@ public class UserController extends BaseController {
op = "base";
}
model.addAttribute("op", op);
model.addAttribute("user", user.getCurrentUser());
model.addAttribute("user", UserUtils.getUser());
return "modules/sys/user/userInfo";
}
@@ -202,7 +200,7 @@ public class UserController extends BaseController {
@RequestMapping(value = "userSelect")
public String userSelect(User user, String selectData, Model model) {
String selectDataJson = EncodeUtils.decodeUrl(selectData);
if (JsonMapper.fromJson(selectDataJson, Map.class) != null){
if (selectDataJson != null && JSONValidator.from(selectDataJson).validate()){
model.addAttribute("selectData", selectDataJson);
}
model.addAttribute("user", user);

View File

@@ -131,6 +131,9 @@ user:
# 登录账号是否租户内唯一,否则全局唯一
loginCodeCorpUnique: false
# 是否启用验证码登录(手机、邮箱)
loginByValidCode: true
# 用户类型配置信息employee员工member会员btype往来单位persion个人expert专家...JSON 格式说明如下:
# {"用户类型":{"beanName":"Service或Dao的Bean名称","loginView":"登录页面视图","indexView":"主框架页面视图,支持 redirect: 前缀"}}
@@ -335,10 +338,11 @@ shiro:
# 登录提交信息加密(如果不需要加密,设置为空即可)
loginSubmit:
# 登录提交信息安全Key加密用户名、密码、验证码后再提交key设置为3个用逗号分隔加密方式DES
# v4.2.0+ 支持 Base64 加密方式,方便移动端及第三方系统处理认证,可直接设置 Key 为 Base64
# 加密用户名、密码、验证码后再提交key设置为3个用逗号分隔加密方式DES4.1.9及之前版本默认设置)
# v4.2.0+ 开始支持 Base64 加密方式,方便移动端及第三方系统处理认证,可直接设置 Key 为 Base644.2.0+默认设置)
#secretKey: thinkgem,jeesite,com
secretKey: Base64
#secretKey: ~
# 记住我密钥设置,你可以通过 com.jeesite.test.RememberMeKeyGen 类快速生成一个秘钥。
# 若不设置,则每次启动系统后自动生成一个新秘钥,这样会导致每次重启后,客户端记录的用户信息将失效。
@@ -367,7 +371,7 @@ shiro:
# accessControlAllowOrigin: http://demo.jeesite.com
# accessControlAllowOrigin: '*'
# 允许跨域访问时 CORS可以使用的方法和响应
# 允许跨域访问时 CORS可以使用的方法和
# accessControlAllowMethods: GET, POST, OPTIONS
# accessControlAllowHeaders: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With
@@ -396,6 +400,7 @@ shiro:
# ${adminPath}/cms/article/* = anon
# ${adminPath}/cms/link/* = anon
# ${adminPath}/sys/corpAdmin/treeData = anon
# ${adminPath}/${spring.application.name}/swagger/** = anon
# ${adminPath}/** = user
filterChainDefinitions: |
${adminPath}/sys/corpAdmin/treeData = anon
@@ -429,8 +434,11 @@ session:
# 注意如果超时超过30m你还需要同步修改当前配置文件的属性j2cache.caffeine.region.sessionCache 超时时间,大于这个值。
sessionTimeout: 1800000
# PC设备会话超时参数设置登录请求参数加 param_deviceType=pc 时有效
#pcSessionTimeout: 1800000
# 手机APP设备会话超时参数设置登录请求参数加 param_deviceType=mobileApp 时有效
mobileAppSessionTimeout: 43200000
#mobileAppSessionTimeout: 43200000
# 定时清理失效会话,清理用户直接关闭浏览器造成的孤立会话
sessionTimeoutClean: 1200000
@@ -503,10 +511,12 @@ web:
# 使用智能参数接收器,同时支持 JSON 和 FormData 的参数接受
smartMethodArgumentResolver: true
# 使用 .json、.xml 后缀匹配视图(不推荐使用,推荐使用 favorParameter
# 使用 .json、.xml 后缀匹配返回视图数据Spring官方已不推荐使用
favorPathExtension: false
# 使用 __ajax=json、__ajax=xml 参数名匹配视图
# 使用 __ajax=json、__ajax=xml 后缀匹配返回视图数据
favorParameter: true
# 使用 __ajax=json、__ajax=xml 请求头匹配返回视图数据
favorHeader: true
# MVC 拦截器
interceptor:
@@ -623,6 +633,10 @@ video:
# 将mp4视频的元数据信息转到视频第一帧
qtFaststartFile: d:/tools/video/qt-faststart/qt-faststart.exe
# 文件管理是否启用租户模式
filemanager:
useCorpModel: false
#======================================#
#========== Message settings ==========#
#======================================#

View File

@@ -1,17 +1,5 @@
-- tables_db2_v95.sql
DROP TABLE ${_prefix}job_FIRED_TRIGGERS;
DROP TABLE ${_prefix}job_PAUSED_TRIGGER_GRPS;
DROP TABLE ${_prefix}job_SCHEDULER_STATE;
DROP TABLE ${_prefix}job_LOCKS;
DROP TABLE ${_prefix}job_SIMPLE_TRIGGERS;
DROP TABLE ${_prefix}job_SIMPROP_TRIGGERS;
DROP TABLE ${_prefix}job_CRON_TRIGGERS;
DROP TABLE ${_prefix}job_TRIGGERS;
DROP TABLE ${_prefix}job_JOB_DETAILS;
DROP TABLE ${_prefix}job_CALENDARS;
DROP TABLE ${_prefix}job_BLOB_TRIGGERS;
create table ${_prefix}job_job_details(
sched_name varchar(120) not null,
job_name varchar(80) not null,

View File

@@ -16,4 +16,5 @@
4.1.7
4.1.8
4.1.9
4.2.0
4.2.0
4.2.1

View File

@@ -20,6 +20,7 @@
操作=Actions
更多=More
更多操作=More action
设置=Setting
基本信息=Basic information
详细信息=Detail information

View File

@@ -20,6 +20,7 @@
操作=操作
更多=さらに多
更多操作=他の操作
设置=設置
基本信息=基本情報
详细信息=詳細情報

View File

@@ -69,6 +69,10 @@
登录=Login
欢迎回来=Welcome
账号登录=Login
手机登录=Mobile
没有账号=No account
点击注册=Register
请填写登录账号.=Please enter login account.
登录账号=Login account
@@ -77,6 +81,11 @@
请填写登录密码.=Please enter login password.
登录密码=Login password
登录租户=Login tenant
请填写手机验证码.=Please enter mobile valid code
手机验证码=Mobile valid code
获取手机验证码=Get valid code
公共场所慎用,下次不需要再填写帐号=Use caution in public places.
记住账号=Remember account
公共场所慎用,下次不需要再填写帐号和密码=Use caution in public places.

View File

@@ -70,6 +70,10 @@
登录=ログイン
欢迎回来=おかえり
账号登录=ログイン
手机登录=電話登録
没有账号=アカウントなし
点击注册=きにゅう
请填写登录账号.=ログインIDを入力してください.
登录账号=ログインアカウント
@@ -78,6 +82,11 @@
请填写登录密码.=パスワードを入力してください.
登录密码=パスワード
登录租户=テナント登録
请填写手机验证码.=携帯電話の検証コード
手机验证码=電話の検証コード
获取手机验证码=コードを取得
公共场所慎用,下次不需要再填写帐号=次回からログインIDの入力が不要にします.
记住账号=ログインID記憶
公共场所慎用,下次不需要再填写帐号和密码=次回からパスワードの入力が不要にします.
@@ -90,6 +99,9 @@
注册账号=アカウント作成
忘记密码=パスワードを忘れた
注册账号=アカウントを登録する
忘记密码=パスワードを忘れる
# =========== 主框架页 ===========
仪表盘=計器盤

View File

@@ -18,7 +18,21 @@
AND ur.role_code = #{roleCode}
</if>
<if test="employee.postCode != null and employee.postCode != ''">
AND ep.post_code = #{employee.postCode}
AND (
ep.post_code = #{employee.postCode}
OR EXISTS (
SELECT 1 FROM ${_prefix}sys_employee_office
WHERE emp_code = e.emp_code
AND post_code = #{employee.postCode}
)
)
</if>
<if test="employee.office.officeCode != null and employee.office.officeCode != ''">
OR EXISTS (
SELECT 1 FROM ${_prefix}sys_employee_office
WHERE emp_code = e.emp_code
AND office_code = #{employee.office.officeCode}
)
</if>
</where>
ORDER BY ${sqlMap.order.toSql()}

View File

@@ -0,0 +1,111 @@
/*!
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*
* @author ThinkGem
* @version 2019-1-6
*/
$(function(){
$('#fp_validType').change(function(){
var val = $(this).val(), action = '';
$('.fp-element').addClass('hide').removeClass('block');
$('.fp-'+val).addClass('block').removeClass('hide');
setTimeout(function(){
$('#fp_loginCode').focus();
}, 100);
if (val == 'mobile' || val == 'email'){
var txt = (val == 'mobile' ? '手机' : '邮箱')
$('#fpValidCode').attr('placeholder', txt+'验证码')
.attr('data-msg-required', '请填写'+txt+'验证码.');
$('#sendFpValidCode').val('获取'+txt+'验证码');
action = ctxPath + '/account/savePwdByValidCode';
}else if(val == 'question'){
action = ctxPath + '/account/savePwdByPwdQuestion';
}
$('#forgetForm').attr('action', action);
}).change();
var waitTime = 60;
function sendTime(o) {
if (waitTime == 0) {
o.removeAttribute("disabled");
o.value = "获取验证码";
waitTime = 60;
} else {
o.setAttribute("disabled", true);
o.value = "重新发送(" + waitTime + ")";
waitTime--;
setTimeout(function() {
sendTime(o)
}, 1000);
}
}
$('#sendFpValidCode').click(function() {
var $this = this;
js.ajaxSubmit(ctxPath + '/account/getFpValidCode', {
validType: $('#fp_validType').val(),
loginCode : $('#fp_loginCode').val(),
validCode : $('#fp_validCode').val()
}, function(data){
js.showMessage(data.message);
if (data.result == 'true'){
sendTime($this);
$('#fpValidCode').focus();
}else{
$('#fp_validCodeImg').click();
}
});
});
$('#fp_getQuestion').click(function() {
js.ajaxSubmit(ctxPath + '/account/getPwdQuestion', {
loginCode : $('#fp_loginCode').val(),
validCode : $('#fp_validCode').val()
}, function(data){
js.showMessage(data.message);
if (data.result == 'true'){
$('#fp_q1').text(data.pwdQuestion);
$('#fp_q2').text(data.pwdQuestion2);
$('#fp_q3').text(data.pwdQuestion3);
}
});
});
$('#forgetForm').validate({
ignore: ":hidden",
submitHandler: function(form) {
var $form = $(form),
action = $form.attr('action'),
data = $form.serializeArray(),
key = window.secretKey||$('#loginKey').data('key');
if (key != ''){
for (var i=0, l=data.length; i<l; i++){
if (data[i].name == 'pwdQuestionAnswer'){
data[i].value = DesUtils.encode($('#fp_pwdQuestionAnswer').val(), key);
}else if (data[i].name == 'pwdQuestionAnswer2'){
data[i].value = DesUtils.encode($('#fp_pwdQuestionAnswer2').val(), key);
}else if (data[i].name == 'pwdQuestionAnswer3'){
data[i].value = DesUtils.encode($('#fp_pwdQuestionAnswer3').val(), key);
}else if (data[i].name == 'password'){
data[i].value = DesUtils.encode($('#fp_password').val(), key);
}
}
}
js.ajaxSubmit(action, data, function(data, status, xhr){
if (data.result == "true"){
alert(data.message);
location = ctx + '/login';
}else{
js.showMessage(data.message);
}
});
}
});
$('#btnReset').click(function(){
location = ctx + '/login';
});
});

View File

@@ -0,0 +1,97 @@
/*!
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*
* @author ThinkGem
* @version 2019-1-6
*/
$(function(){
$('#reg_validType').change(function(){
var val = $(this).val(), action = '';
$('.reg-element').addClass('hide').removeClass('block');
$('.reg-'+val).addClass('block').removeClass('hide');
setTimeout(function(){
$('#reg_loginCode').focus();
}, 100);
if (val == 'mobile' || val == 'email'){
var txt = (val == 'mobile' ? '手机' : '邮箱')
$('#regValidCode').attr('placeholder', txt+'验证码')
.attr('data-msg-required', '请填写'+txt+'验证码.');
$('#sendRegValidCode').val('获取'+txt+'验证码');
action = ctxPath + '/account/saveRegByValidCode';
}else if(val == 'question'){
action = ctxPath + '/account/savePwdByPwdQuestion';
}
$('#registerForm').attr('action', action);
}).change();
var waitTime = 60;
function sendTime(o) {
if (waitTime == 0) {
o.removeAttribute("disabled");
o.value = "获取验证码";
waitTime = 60;
} else {
o.setAttribute("disabled", true);
o.value = "重新发送(" + waitTime + ")";
waitTime--;
setTimeout(function() {
sendTime(o)
}, 1000);
}
}
$('#sendRegValidCode').click(function() {
var $this = this;
js.ajaxSubmit(ctxPath + '/account/getRegValidCode', {
validType: $('#reg_validType').val(),
corpCode_ : $('#reg_corpCode').val(),
corpName_ : $('#reg_corpName').val(),
loginCode : $('#reg_loginCode').val(),
userName : $('#reg_userName').val(),
email : $('#reg_email').val(),
mobile : $('#reg_mobile').val(),
userType: $('#reg_userType').val(),
validCode : $('#reg_validCode').val()
}, function(data){
js.showMessage(data.message);
if (data.result == 'true'){
sendTime($this);
$('#regValidCode').focus();
}else{
$('#reg_validCodeImg').click();
}
});
});
$('#registerForm').validate({
ignore: ":hidden",
submitHandler: function(form) {
var $form = $(form),
action = $form.attr('action'),
data = $form.serializeArray(),
key = window.secretKey||$('#loginKey').data('key');
if (key != ''){
for (var i=0, l=data.length; i<l; i++){
if (data[i].name == 'password'){
data[i].value = DesUtils.encode($('#reg_password').val(), key);
}
}
}
js.ajaxSubmit(action, data, function(data, status, xhr){
if (data.result == "true"){
alert(data.message);
location = ctx + '/login';
}else{
js.showMessage(data.message);
}
});
}
});
$('#btnReset').click(function(){
location = ctx + '/login';
});
});

View File

@@ -7131,7 +7131,7 @@ var fillCharReg = new RegExp(domUtils.fillChar, 'g');
this.iframe.parentNode.style.height = height + 'px';
}
!notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);
this.body.style.height = height + 'px';
//this.body.style.height = height + 'px'; // 设置高的时候会出现多余的垂直滚动条
!notSetHeight && this.trigger('setHeight')
},
@@ -24454,6 +24454,7 @@ UE.plugin.register('simpleupload', function (){
var w = containerBtn.offsetWidth || 20,
h = containerBtn.offsetHeight || 20,
btnIframe = document.createElement('iframe'),
btnIframe2 = document.createElement('iframe'), // ThinkGem
btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;';
domUtils.on(btnIframe, 'load', function(){
@@ -24471,9 +24472,13 @@ UE.plugin.register('simpleupload', function (){
'style="' + btnStyle + '">' +
'<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '" ' +
'style="' + btnStyle + '">' +
'</form>' +
'<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';
'</form>';// +
//'<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';
// 解决因 iframe 嵌套问题 session 丢失 ThinkGem
btnIframe2.id = 'edui_iframe_' + timestrap;
btnIframe2.name = 'edui_iframe_' + timestrap;
wrapper.className = 'edui-' + me.options.theme;
wrapper.id = me.ui.id + '_iframeupload';
btnIframeBody.style.cssText = btnStyle;
@@ -24488,7 +24493,7 @@ UE.plugin.register('simpleupload', function (){
var form = btnIframeDoc.getElementById('edui_form_' + timestrap);
var input = btnIframeDoc.getElementById('edui_input_' + timestrap);
var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);
var iframe = btnIframe2;//btnIframeDoc.getElementById('edui_iframe_' + timestrap);
domUtils.on(input, 'change', function(){
if(!input.value) return;
@@ -24573,6 +24578,10 @@ UE.plugin.register('simpleupload', function (){
btnIframe.style.cssText = btnStyle;
containerBtn.appendChild(btnIframe);
// 解决因 iframe 嵌套问题 session 丢失 ThinkGem
btnIframe2.style.cssText = 'display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;';
containerBtn.appendChild(btnIframe2);
}
return {

View File

@@ -34,6 +34,7 @@ $.fn.webuploader.defaults.i18n = {
'向右旋转': 'Rotate right',
'向左旋转': 'Rotate left',
'不能上传空文件': 'Empty file error',
'文件类型不对': 'File type error',
'文件大小超出': 'File size exceeded',
'文件传输中断': 'File transfer interrupt',

View File

@@ -33,7 +33,8 @@ $.fn.webuploader.defaults.i18n = {
'删除': '削除',
'向右旋转': '右にまがる',
'向左旋转': '左に回る',
'不能上传空文件': '空のファイルはアップロードできません',
'文件类型不对': '書類のタイプが違う',
'文件大小超出': '書類のサイズがはみ出る',
'文件传输中断': 'ファイル転送を中断する。',

View File

@@ -14,19 +14,45 @@
<template>category-ref:dao</template>
</childTable>
</category>
<category value="crud_select" label="单表/主子表 (增删改查,含 listselect 选择页面)">
<template>category-ref:crud</template>
<template>crud/viewSelect.xml</template>
<childTable>
<template>category-ref:dao</template>
</childTable>
</category>
<category value="crud_cloud" label="单表/主子表 (增删改查 Cloud生成 Api/Client">
<template>crud/mapper.xml</template>
<template>crud_cloud/entity.xml</template>
<template>crud/dao.xml</template>
<template>crud_cloud/api.xml</template>
<template>crud_cloud/client.xml</template>
<template>crud_cloud/service.xml</template>
<template>crud/controller.xml</template>
<template>crud/viewList.xml</template>
<template>crud/viewForm.xml</template>
<childTable>
<template>crud/mapper.xml</template>
<template>crud_cloud/entity.xml</template>
<template>crud/dao.xml</template>
</childTable>
</category>
<category value="treeGrid" label="树表/树结构表(增删改查)">
<template>category-ref:crud</template>
</category>
<category value="service" label="业务层和持久层(不含控制器和视图">
<category value="treeGrid_cloud" label="树表/树结构表(增删改查 Cloud生成 Api/Client">
<template>category-ref:crud</template>
</category>
<category value="service" label="业务层和持久层dao/service不含控制器和视图">
<template>category-ref:dao</template>
<template>crud/service.xml</template>
</category>
<category value="dao" label="仅持久层dao/mapper/entity">
<category value="dao" label="关系表/仅持久层dao/mapper/entity">
<template>crud/mapper.xml</template>
<template>crud/entity.xml</template>
<template>crud/dao.xml</template>
</category>
<category value="query" label="仅查询功能(不含增删改)">
<category value="query" label="仅查询功能(不含增删改,仅数据展现">
<template>crud/mapper.xml</template>
<template>crud/entity.xml</template>
<template>query/dao.xml</template>
@@ -110,4 +136,42 @@
<dict value="4/4/8" label="4/4/8 三列"/>
<dict value="3/4/8" label="3/4/8 四列"/>
</gridRowCol>
<!-- 模块生成模板分类 -->
<moduleTplCategory>
<category value="module" label="生成模块代码">
<template>module/bin/deploy.bat.xml</template>
<template>module/bin/deploy.sh.xml</template>
<template>module/bin/package.bat.xml</template>
<template>module/bin/package.sh.xml</template>
<template>module/db/erm.xml</template>
<template>module/src/main/java/package.xml</template>
<template>module/src/main/resources/config/jeesite.xml</template>
<template>module/src/main/resources/db/versions.xml</template>
<template>module/src/main/resources/static/static.xml</template>
<template>module/pom.xml</template>
</category>
<category value="module_cloud" label="生成微服务模块代码Cloud">
<template>module_cloud/client/bin/deploy.bat.xml</template>
<template>module_cloud/client/bin/deploy.sh.xml</template>
<template>module_cloud/client/bin/package.bat.xml</template>
<template>module_cloud/client/bin/package.sh.xml</template>
<template>module_cloud/client/src/main/java/package.xml</template>
<template>module_cloud/client/pom.xml</template>
<template>module_cloud/web/bin/docker-bulid.bat.xml</template>
<template>module_cloud/web/bin/docker-bulid.sh.xml</template>
<template>module_cloud/web/bin/package.bat.xml</template>
<template>module_cloud/web/bin/package.sh.xml</template>
<template>module_cloud/web/bin/run-tomcat.bat.xml</template>
<template>module_cloud/web/bin/run-tomcat.sh.xml</template>
<template>module_cloud/web/bin/run-web.bat.xml</template>
<template>module_cloud/web/bin/run-web.sh.xml</template>
<template>module_cloud/web/db/erm.xml</template>
<template>module_cloud/web/src/main/java/package.xml</template>
<template>module_cloud/web/src/main/java/startClass.xml</template>
<template>module_cloud/web/src/main/resources/config/bootstrap.xml</template>
<template>module_cloud/web/src/main/resources/config/logback-spring.xml</template>
<template>module_cloud/web/src/main/resources/static/static.xml</template>
<template>module_cloud/web/pom.xml</template>
</category>
</moduleTplCategory>
</config>

View File

@@ -39,6 +39,10 @@ import com.jeesite.modules.sys.utils.UserUtils;
<% }else{ %>
import com.jeesite.common.entity.Page;
<% } %>
<% if (table.tplCategory == 'crud_select'){ %>
import com.alibaba.fastjson.JSONValidator;
import com.jeesite.common.codec.EncodeUtils;
<% } %>
import com.jeesite.common.web.BaseController;
import ${packageName}.${moduleName}.entity${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName};
import ${packageName}.${moduleName}.service${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName}Service;
@@ -238,10 +242,12 @@ public class ${ClassName}Controller extends BaseController {
List<${ClassName}> list = ${className}Service.findList(new ${ClassName}());
for (int i=0; i<list.size(); i++){
${ClassName} e = list.get(i);
<% if (table.statusExists){ %>
// 过滤非正常的数据
if (!${ClassName}.STATUS_NORMAL.equals(e.getStatus())){
continue;
}
<% } %>
// 过滤被排除的编码(包括所有子级)
if (StringUtils.isNotBlank(excludeCode)){
if (e.getId().equals(excludeCode)){
@@ -274,6 +280,22 @@ public class ${ClassName}Controller extends BaseController {
return renderResult(Global.TRUE, "数据修复成功");
}
<% } %>
<% if (table.tplCategory == 'crud_select'){ %>
/**
* 列表选择对话框
*/
@RequiresPermissions("${permissionPrefix}:view")
@RequestMapping(value = "${className}Select")
public String empUserSelect(${ClassName} ${className}, String selectData, Model model) {
String selectDataJson = EncodeUtils.decodeUrl(selectData);
if (selectDataJson != null && JSONValidator.from(selectDataJson).validate()){
model.addAttribute("selectData", selectDataJson);
}
model.addAttribute("${ClassName}", ${className});
return "${lastPackageName}/${viewPrefix}Select";
}
<% } %>
}]]>
</content>

View File

@@ -21,6 +21,13 @@ import com.jeesite.common.entity.TreeEntity;
import com.jeesite.common.mybatis.annotation.Column;
import com.jeesite.common.mybatis.annotation.Table;
import com.jeesite.common.mybatis.mapper.query.QueryType;
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
<% if(table.isTreeEntity){ %>
import com.jeesite.modules.bpm.entity.BpmTreeEntity;
<% }else{ %>
import com.jeesite.modules.bpm.entity.BpmEntity;
<% } %>
<% } %>
/**
* ${functionName}Entity
@@ -136,9 +143,9 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
}
}
if (isNotBlank(joinTables)){
print('joinTable={\n');
print('joinTable={');
print(joinTables);
print('\t}, ');
print('}, ');
}
// ◆ 生成排序字段
%>orderBy="<% if (isTree){
@@ -156,7 +163,7 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
}
} %>"
)
public class ${ClassName} extends ${table.isTreeEntity?'Tree':'Data'}Entity<${ClassName}> {
public class ${ClassName} extends ${toBoolean(table.optionMap['isBpmForm'])?(table.isTreeEntity?'BpmTree':'Bpm'):table.isTreeEntity?'Tree':'Data'}Entity<${ClassName}> {
private static final long serialVersionUID = 1L;
<%

View File

@@ -22,6 +22,13 @@ import com.jeesite.common.entity.Page;
import com.jeesite.common.service.${table.isTreeEntity?'Tree':'Crud'}Service;
import ${packageName}.${moduleName}.entity${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName};
import ${packageName}.${moduleName}.dao${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName}Dao;
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
import java.util.Map;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.service.ServiceException;
import com.jeesite.modules.bpm.utils.BpmUtils;
<% } %>
<% if(toBoolean(table.optionMap['isImageUpload']) || toBoolean(table.optionMap['isFileUpload'])){ %>
import com.jeesite.modules.file.utils.FileUploadUtils;
<% } %>
@@ -97,7 +104,43 @@ public class ${ClassName}Service extends ${table.isTreeEntity?'Tree':'Crud'}Serv
@Override
@Transactional(readOnly=false)
public void save(${ClassName} ${className}) {
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
// 如果未设置状态,则指定状态为审核状态,以提交审核流程
if (StringUtils.isBlank(${className}.getStatus())){
${className}.setStatus(${ClassName}.STATUS_AUDIT);
}
// 如果状态为正常,则代表不正常操作,可能前端进行了数据参数修改
if (${ClassName}.STATUS_NORMAL.equals(${className}.getStatus())){
throw new ServiceException(text("非法操作,前端数据被劫持!"));
}
// 如果状态为草稿或审核状态,才可以保存业务数据
if (${ClassName}.STATUS_DRAFT.equals(${className}.getStatus())
|| ${ClassName}.STATUS_AUDIT.equals(${className}.getStatus())){
super.save(${className});
}
// 如果为审核状态,则进行审批流操作
if (${ClassName}.STATUS_AUDIT.equals(${className}.getStatus())){
// 指定流程变量,作为流程条件,决定流转方向
Map<String, Object> variables = MapUtils.newHashMap();
//variables.put("leaveDays", ${className}.getLeaveDays());
// 如果流程实例为空,任务编号也为空,则:启动流程
if (StringUtils.isBlank(${className}.getBpm().getProcInsId())
&& StringUtils.isBlank(${className}.getBpm().getTaskId())){
BpmUtils.start(${className}, "${table.optionMap['bpmFormKey']}", variables, null);
}
// 如果有任务信息,则:提交任务
else{
BpmUtils.complete(${className}, variables, null);
}
}
<% }else{ %>
super.save(${className});
<% } %>
<% if(toBoolean(table.optionMap['isImageUpload'])){ %>
// 保存上传图片
FileUploadUtils.saveFileUpload(${className}.getId(), "${className}_image");

View File

@@ -45,13 +45,38 @@
<% } %>
<% include('/templates/modules/gen/include/formControl.html'){} %>
<% include('/templates/modules/gen/include/formChildTable.html'){} %>
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
\<% if(isNotBlank(${className}.bpm.taskId)){ %>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label col-xs-2">${text('审批意见')}</label>
<div class="col-xs-10">
<${'#'}bpm:comment bpmEntity="\${${className}}" />
</div>
</div>
</div>
</div>
\<% } %>
<${'#'}bpm:nextTaskInfo bpmEntity="\${${className}}" />
<% } %>
</div>
<div class="box-footer">
<div class="row">
<div class="col-sm-offset-2 col-sm-10">
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
\<% if (hasPermi('${permissionPrefix}:edit')){ %>
<${'#'}form:hidden path="status"/>
\<% if (${className}.isNewRecord || ${className}.status == '9'){ %>
<button type="submit" class="btn btn-sm btn-info" id="btnDraft"><i class="fa fa-save"></i> ${text('暂 存')}</button>&nbsp;
\<% } %>
<${'#'}bpm:button bpmEntity="\${${className}}" formKey="${table.optionMap['bpmFormKey']}" completeText="${text('提 交')}"/>
\<% } %>
<% }else{ %>
\<% if (hasPermi('${permissionPrefix}:edit')){ %>
<button type="submit" class="btn btn-sm btn-primary" id="btnSubmit"><i class="fa fa-check"></i> \${text('保 存')}</button>&nbsp;
\<% } %>
<% } %>
<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="js.closeCurrentTabPage()"><i class="fa fa-reply-all"></i> \${text('关 闭')}</button>
</div>
</div>
@@ -62,6 +87,19 @@
\<% } %>
<% include('/templates/modules/gen/include/formChildTableScript.html'){} %>
<script>
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
// 业务实现草稿按钮
$('#btnDraft').click(function(){
$('#status').val(Global.STATUS_DRAFT);
});
// 流程按钮操作事件
BpmButton = window.BpmButton || {};
BpmButton.init = function(task){ }
BpmButton.complete = function($this, task){
$('#status').val(Global.STATUS_AUDIT);
};
// 表单验证提交事件
<% } %>
$("#inputForm").validate({
submitHandler: function(form){
js.ajaxSubmitForm($(form), function(data){

View File

@@ -22,6 +22,7 @@
\<% if(hasPermi('${permissionPrefix}:edit')){ %>
<a href="\${ctx}/${urlPrefix}/form" class="btn btn-default btnTool" title="\${text('新增${functionNameSimple}')}"><i class="fa fa-plus"></i> \${text('新增')}</a>
\<% } %>
<a href="#" class="btn btn-default" id="btnSetting" title="\${text('设置')}"><i class="fa fa-navicon"></i></a>
</div>
</div>
<div class="box-body">

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>viewSelect</name>
<filePath>src/main/resources/views/${lastPackageName}/${moduleName}/${subModuleName}</filePath>
<fileName>${className}Select.html</fileName>
<content><![CDATA[
\<% layout('/layouts/default.html', {title: '${functionNameSimple}管理', libs: ['dataGrid']}){ %>
<div class="main-content">
<div class="box box-main">
<div class="box-body">
<% include('/templates/modules/gen/include/searchForm.html'){} %>
<div class="row">
<div class="col-xs-10 pr10">
<table id="dataGrid"></table>
<% if(!table.isTreeEntity){ %>
<div id="dataGridPage"></div>
<% } %>
</div>
<div class="col-xs-2 pl0">
<div id="selectData" class="tags-input"></div>
</div>
</div>
</div>
</div>
</div>
\<% } %>
<% include('/templates/modules/gen/include/dataGridSelectScript.html'){} %>]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>controller</name>
<filePath>${moduleName}-client/src/main/java/${packageName}/${moduleName}/api/${subModuleName}</filePath>
<fileName>${ClassName}ServiceApi.java</fileName>
<content><![CDATA[
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package ${packageName}.${moduleName}.api${isNotEmpty(subModuleName)?'.'+subModuleName:''};
import org.springframework.web.bind.annotation.RequestMapping;
import com.jeesite.common.service.rest.CrudServiceRest;
import ${packageName}.${moduleName}.entity${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName};
/**
* ${functionName}API
* @author ${functionAuthor}
* @version ${functionVersion}
*/
@RequestMapping(value = "/inner/api/${urlPrefix}")
public interface ${ClassName}ServiceApi extends ${table.isTreeEntity?'Tree':'Crud'}ServiceRest<${ClassName}> {
}]]>
</content>
</template>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>client</name>
<filePath>${moduleName}-client/src/main/java/${packageName}/${moduleName}/client/${subModuleName}</filePath>
<fileName>${ClassName}ServiceClient.java</fileName>
<content><![CDATA[
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package ${packageName}.${moduleName}.client${isNotEmpty(subModuleName)?'.'+subModuleName:''};
import org.springframework.cloud.openfeign.FeignClient;
import com.jeesite.modules.cloud.feign.condition.ConditionalOnNotCurrentApplication;
import ${packageName}.${moduleName}.api${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName}ServiceApi;
/**
* ${functionName}API
* @author ${functionAuthor}
* @version ${functionVersion}
*/
@FeignClient(name="\${service.${moduleName}.name}", path="\${service.${moduleName}.path}")
@ConditionalOnNotCurrentApplication(name="\${service.${moduleName}.name}")
public interface ${ClassName}ServiceClient extends ${ClassName}ServiceApi {
}]]>
</content>
</template>

View File

@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>entity</name>
<filePath>${moduleName}-client/src/main/java/${packageName}/${moduleName}/entity/${subModuleName}</filePath>
<fileName>${ClassName}.java</fileName>
<content><![CDATA[
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package ${packageName}.${moduleName}.entity${isNotBlank(subModuleName)?'.'+subModuleName:''};
<% for(i in table.importList){ %>
import ${i};
<% } %>
import com.jeesite.common.entity.DataEntity;
<% if(table.isTreeEntity){ %>
import com.jeesite.common.entity.TreeEntity;
<% } %>
import com.jeesite.common.mybatis.annotation.Column;
import com.jeesite.common.mybatis.annotation.Table;
import com.jeesite.common.mybatis.mapper.query.QueryType;
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
<% if(table.isTreeEntity){ %>
import com.jeesite.modules.bpm.entity.BpmTreeEntity;
<% }else{ %>
import com.jeesite.modules.bpm.entity.BpmEntity;
<% } %>
<% } %>
/**
* ${functionName}Entity
* @author ${functionAuthor}
* @version ${functionVersion}
*/
@Table(name="${table.genTableName}", alias="a", columns={
<%
var isBase = false, isData = false,
isTree = false, isExtend = false;
// ◆ 生成字段属性
for(c in table.columnList){
// ● 如果是BaseEntity类属性
if(table.isBaseEntity && c.isBaseEntityColumn){
if(!isBase){
isBase = true;
%>
@Column(includeEntity=BaseEntity.class),
<%
}
// ● 如果是DataEntity类属性
}else if(table.isDataEntity && c.isDataEntityColumn){
if(!isData){
isData = true;
%>
@Column(includeEntity=DataEntity.class),
<%
}
// ● 如果是TreeEntity类属性
}else if(table.isTreeEntity && c.isTreeEntityColumn){
if(!isTree){
isTree = true;
%>
@Column(includeEntity=TreeEntity.class),
<%
}
// ● 如果是Extend类属性
}else if(table.isExtendEntity && c.isExtendColumn){
if(!isExtend){
isExtend = true;
%>
@Column(includeEntity=Extend.class, attrName="extend"),
<%
}
// ● 其它情况下
}else{
// 容错,如果没有设置父表的主键属性,则设置
if(!@StringUtils.contains(c.attrName, ".")){
if (table.parentExists && table.parentTableFkName == c.columnName){
for (pk in table.parent.pkList){
c.fullAttrName = c.fullAttrName + '.' + pk.attrName;
break;
}
}
}
%>
@Column(name="${c.columnName}", attrName="${c.attrName}", label="${c.columnLabel}"<%
if (c.comments != c.columnLabel){
print(', comment="'+c.comments+'"');
}
if (c.isPk == @Global.YES){
print(', isPK=true');
}else{
if (c.isInsert != @Global.YES){
print(', isInsert=false');
}
if (c.isUpdate != @Global.YES){
print(', isUpdate=false');
}
if (c.isQuery == @Global.YES && @StringUtils.inString(c.queryType,
'NE', 'GT', 'GTE', 'LT', 'LTE', 'LIKE', 'LEFT_LIKE', 'RIGHT_LIKE')){
print(', queryType=QueryType.'+c.queryType);
}
if (c.isQuery != @Global.YES){
print(', isQuery=false');
}
if (c.attrName == table.treeViewNameAttrName){
print(', isTreeName=true');
}
}
%>),
<%
}
}
%>
}, <%
// ◆ 生成关联表
var joinTables = '';
for(c in table.columnList){
if (c.attrType == 'com.jeesite.modules.sys.entity.User'){
var joinTable = {
%>
@JoinTable(type=Type.LEFT_JOIN, entity=User.class, attrName="${c.simpleAttrName}", alias="u${cLP.index}",
on="u${cLP.index}.user_code = a.${c.columnName}", columns={
@Column(name="user_code", label="用户编码", isPK=true),
@Column(name="user_name", label="用户名称", isQuery=false),
}),
<%
};
joinTables = joinTables + joinTable;
}
else if (c.attrType == 'com.jeesite.modules.sys.entity.Office'){
var joinTable = {
%>
@JoinTable(type=Type.LEFT_JOIN, entity=Office.class, attrName="${c.simpleAttrName}", alias="u${cLP.index}",
on="u${cLP.index}.office_code = a.${c.columnName}", columns={
@Column(name="office_code", label="机构编码", isPK=true),
@Column(name="office_name", label="机构名称", isQuery=false),
}),
<%
};
joinTables = joinTables + joinTable;
}
}
if (isNotBlank(joinTables)){
print('joinTable={');
print(joinTables);
print('}, ');
}
// ◆ 生成排序字段
%>orderBy="<% if (isTree){
%>a.tree_sorts<%
for(pk in table.pkList){
%>, a.${pk.columnName}<%
}
}else if(table.parentExists && table.createDateExists){
%>a.create_date ASC<%
}else if(table.updateDateExists){
%>a.update_date DESC<%
}else{
for(pk in table.pkList){
%>${pkLP.index!=1?', ':''}a.${pk.columnName} ${table.parentExists?'ASC':'DESC'}<%
}
} %>"
)
public class ${ClassName} extends ${toBoolean(table.optionMap['isBpmForm'])?(table.isTreeEntity?'BpmTree':'Bpm'):table.isTreeEntity?'Tree':'Data'}Entity<${ClassName}> {
private static final long serialVersionUID = 1L;
<%
isExtend = false;
// 生成字段属性
for(c in table.columnList){
// 如果是Extend类属性
if(table.isExtendEntity && c.isExtendColumn){
if(!isExtend){
isExtend = true;
%>
private Extend extend; // 扩展字段
<%
}
}
// 如果不是基类属性
else if(!@StringUtils.equalsIgnoreCase(c.columnName, 'id') && !c.isSuperColumn){
// 父类对象
if(table.parentExists && table.parentTableFkName == c.columnName){
%>
private ${@StringUtils.cap(table.parent.className)} ${c.simpleAttrName}; <% if (isNotBlank(c.comments)){ %>// ${c.comments} 父类<% } %>
<%
// 其它字段
}else{
%>
private ${c.simpleAttrType} ${c.simpleAttrName}; <%if(isNotBlank(c.comments)){%>// ${c.comments}<%}%>
<%
}
}
}
// 生成子表列表字段
for(child in table.childList){
%>
private List<${@StringUtils.cap(child.className)}> ${@StringUtils.uncap(child.className)}List = ListUtils.newArrayList(); // 子表列表
<%
}
// 生成构造方法
%>
public ${ClassName}() {
this(<% for(pk in table.pkList){ %>${pkLP.index!=1?', ':''}null<% } %>);
}
<%
// 生成带主键参数的构造
if (!table.parentExists){
if (table.pkList.~size == 1){ %>
public ${ClassName}(String id){
super(id);
}
<% }else{ %>
public ${ClassName}(<% for(pk in table.pkList){ %>${pkLP.index!=1?', ':''}${pk.simpleAttrType} ${pk.simpleAttrName}<% } %>){
<% for(pk in table.pkList){ %>
this.${pk.simpleAttrName} = ${pk.simpleAttrName};
<% } %>
}
<%
}
}
// 生成父表参数的构造
else{
for(c in table.columnList){
if(table.parentExists && table.parentTableFkName == c.columnName){
%>
public ${ClassName}(${@StringUtils.cap(table.parent.className)} ${c.simpleAttrName}){
this.${c.simpleAttrName} = ${c.simpleAttrName};
}
<%
}
}
}
// 如果是树实体,则输出相应方法
if (table.isTreeEntity){
%>
@Override
public ${ClassName} getParent() {
return parent;
}
@Override
public void setParent(${ClassName} parent) {
this.parent = parent;
}
<%
}
// 生成属性的get和set方法
isExtend = false;
for(c in table.columnList){
// 如果是Extend类属性
if(c.isExtendColumn){
if(!isExtend){
isExtend = true;
%>
public Extend getExtend() {
return extend;
}
public void setExtend(Extend extend) {
this.extend = extend;
}
<%
}
// 如果不是基类属性
}else if(!@StringUtils.equalsIgnoreCase(c.columnName, 'id') && !c.isSuperColumn){
%>
<%
for(a in c.simpleAnnotationList){
%>
@${a}
<%
}
// 父类对象
if(table.parentExists && table.parentTableFkName == c.columnName){
%>
public ${@StringUtils.cap(table.parent.className)} get${@StringUtils.cap(c.simpleAttrName)}() {
return ${c.simpleAttrName};
}
public void set${@StringUtils.cap(c.simpleAttrName)}(${@StringUtils.cap(table.parent.className)} ${c.simpleAttrName}) {
this.${c.simpleAttrName} = ${c.simpleAttrName};
}
<%
// 其它字段
}else{
%>
public ${c.simpleAttrType} get${@StringUtils.cap(c.simpleAttrName)}() {
return ${c.simpleAttrName};
}
public void set${@StringUtils.cap(c.simpleAttrName)}(${c.simpleAttrType} ${c.simpleAttrName}) {
this.${c.simpleAttrName} = ${c.simpleAttrName};
}
<%
}
}
}
// 生成条件字段get和set方法范围类型
for(c in table.columnList){
if(c.isQuery == "1" && c.queryType == "BETWEEN"){
%>
public ${c.simpleAttrType} get${@StringUtils.cap(c.simpleAttrName)}_gte() {
return sqlMap.getWhere().getValue("${c.columnName}", QueryType.GTE);
}
public void set${@StringUtils.cap(c.simpleAttrName)}_gte(${c.simpleAttrType} ${c.simpleAttrName}) {
sqlMap.getWhere().and("${c.columnName}", QueryType.GTE, ${c.simpleAttrName});
}
public ${c.simpleAttrType} get${@StringUtils.cap(c.simpleAttrName)}_lte() {
return sqlMap.getWhere().getValue("${c.columnName}", QueryType.LTE);
}
public void set${@StringUtils.cap(c.simpleAttrName)}_lte(${c.simpleAttrType} ${c.simpleAttrName}) {
sqlMap.getWhere().and("${c.columnName}", QueryType.LTE, ${c.simpleAttrName});
}
<%
}
}
// 生成子表列表get和set方法
for(child in table.childList){
%>
public List<${@StringUtils.cap(child.className)}> get${@StringUtils.cap(child.className)}List() {
return ${@StringUtils.uncap(child.className)}List;
}
public void set${@StringUtils.cap(child.className)}List(List<${@StringUtils.cap(child.className)}> ${@StringUtils.uncap(child.className)}List) {
this.${@StringUtils.uncap(child.className)}List = ${@StringUtils.uncap(child.className)}List;
}
<% } %>
}]]>
</content>
</template>

View File

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>service</name>
<filePath>src/main/java/${packageName}/${moduleName}/service/${subModuleName}</filePath>
<fileName>${ClassName}Service.java</fileName>
<content><![CDATA[
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package ${packageName}.${moduleName}.service${isNotEmpty(subModuleName)?'.'+subModuleName:''};
import java.util.List;
<% if (table.childList.~size > 0){ %>
import org.springframework.beans.factory.annotation.Autowired;
<% } %>
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;
import com.jeesite.common.entity.Page;
import com.jeesite.common.service.${table.isTreeEntity?'Tree':'Crud'}Service;
import ${packageName}.${moduleName}.entity${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName};
import ${packageName}.${moduleName}.dao${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName}Dao;
import ${packageName}.${moduleName}.api${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${ClassName}ServiceApi;
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
import java.util.Map;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.service.ServiceException;
import com.jeesite.modules.bpm.utils.client.BpmUtils;
<% } %>
<% if(toBoolean(table.optionMap['isImageUpload']) || toBoolean(table.optionMap['isFileUpload'])){ %>
import com.jeesite.modules.file.utils.FileUploadUtils;
<% } %>
<% for (child in table.childList){ %>
import ${packageName}.${moduleName}.entity${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${@StringUtils.cap(child.className)};
import ${packageName}.${moduleName}.dao${isNotEmpty(subModuleName)?'.'+subModuleName:''}.${@StringUtils.cap(child.className)}Dao;
<% } %>
/**
* ${functionName}Service
* @author ${functionAuthor}
* @version ${functionVersion}
*/
@Service
@RestController
@Transactional(readOnly=true)
public class ${ClassName}Service extends ${table.isTreeEntity?'Tree':'Crud'}Service<${ClassName}Dao, ${ClassName}>
implements ${ClassName}ServiceApi {
<% for (child in table.childList){ %>
@Autowired
private ${@StringUtils.cap(child.className)}Dao ${@StringUtils.uncap(child.className)}Dao;
<% } %>
/**
* 获取单条数据
* @param ${className}
* @return
*/
@Override
public ${ClassName} get(${ClassName} ${className}) {
<% if (table.childList.~size > 0){ %>
${ClassName} entity = super.get(${className});
if (entity != null){
<% for (child in table.childList){ %>
${@StringUtils.cap(child.className)} ${@StringUtils.uncap(child.className)} = new ${@StringUtils.cap(child.className)}(entity);
${@StringUtils.uncap(child.className)}.setStatus(${@StringUtils.cap(child.className)}.STATUS_NORMAL);
entity.set${@StringUtils.cap(child.className)}List(${@StringUtils.uncap(child.className)}Dao.findList(${@StringUtils.uncap(child.className)}));
<% } %>
}
return entity;
<% }else{ %>
return super.get(${className});
<% } %>
}
<% if(!table.isTreeEntity){ %>
/**
* 查询分页数据
* @param ${className} 查询条件
* @param ${className}.page 分页对象
* @return
*/
@Override
public Page<${ClassName}> findPage(${ClassName} ${className}) {
return super.findPage(${className});
}
<% }else{ %>
/**
* 查询列表数据
* @param ${className}
* @return
*/
@Override
public List<${ClassName}> findList(${ClassName} ${className}) {
return super.findList(${className});
}
<% } %>
/**
* 保存数据(插入或更新)
* @param ${className}
*/
@Override
@Transactional(readOnly=false)
public void save(${ClassName} ${className}) {
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
// 如果未设置状态,则指定状态为审核状态,以提交审核流程
if (StringUtils.isBlank(${className}.getStatus())){
${className}.setStatus(${ClassName}.STATUS_AUDIT);
}
// 如果状态为正常,则代表不正常操作,可能前端进行了数据参数修改
if (${ClassName}.STATUS_NORMAL.equals(${className}.getStatus())){
throw new ServiceException(text("非法操作,前端数据被劫持!"));
}
// 如果状态为草稿或审核状态,才可以保存业务数据
if (${ClassName}.STATUS_DRAFT.equals(${className}.getStatus())
|| ${ClassName}.STATUS_AUDIT.equals(${className}.getStatus())){
super.save(${className});
}
// 如果为审核状态,则进行审批流操作
if (${ClassName}.STATUS_AUDIT.equals(${className}.getStatus())){
// 指定流程变量,作为流程条件,决定流转方向
Map<String, Object> variables = MapUtils.newHashMap();
//variables.put("leaveDays", ${className}.getLeaveDays());
// 如果流程实例为空,任务编号也为空,则:启动流程
if (StringUtils.isBlank(${className}.getBpm().getProcInsId())
&& StringUtils.isBlank(${className}.getBpm().getTaskId())){
BpmUtils.start(${className}, "${table.optionMap['bpmFormKey']}", variables, null);
}
// 如果有任务信息,则:提交任务
else{
BpmUtils.complete(${className}, variables, null);
}
}
<% }else{ %>
super.save(${className});
<% } %>
<% if(toBoolean(table.optionMap['isImageUpload'])){ %>
// 保存上传图片
FileUploadUtils.saveFileUpload(${className}.getId(), "${className}_image");
<% } %>
<% if(toBoolean(table.optionMap['isFileUpload'])){ %>
// 保存上传附件
FileUploadUtils.saveFileUpload(${className}.getId(), "${className}_file");
<% } %>
<% for (child in table.childList) { %>
// 保存 ${ClassName}子表
for (${@StringUtils.cap(child.className)} ${@StringUtils.uncap(child.className)} : ${className}.get${@StringUtils.cap(child.className)}List()){
if (!${@StringUtils.cap(child.className)}.STATUS_DELETE.equals(${@StringUtils.uncap(child.className)}.getStatus())){
<%
for(c in child.columnList){
if (child.parentExists && child.parentTableFkName == c.columnName){
%>
${@StringUtils.uncap(child.className)}.set${@StringUtils.cap(c.simpleAttrName)}(${className});
<%
}
}
%>
if (${@StringUtils.uncap(child.className)}.getIsNewRecord()){
${@StringUtils.uncap(child.className)}Dao.insert(${@StringUtils.uncap(child.className)});
}else{
${@StringUtils.uncap(child.className)}Dao.update(${@StringUtils.uncap(child.className)});
}
}else{
${@StringUtils.uncap(child.className)}Dao.delete(${@StringUtils.uncap(child.className)});
}
}
<% } %>
}
/**
* 更新状态
* @param ${className}
*/
@Override
@Transactional(readOnly=false)
public void updateStatus(${ClassName} ${className}) {
super.updateStatus(${className});
}
/**
* 删除数据
* @param ${className}
*/
@Override
@Transactional(readOnly=false)
public void delete(${ClassName} ${className}) {
super.delete(${className});
<% for (child in table.childList) { %>
${@StringUtils.cap(child.className)} ${@StringUtils.uncap(child.className)} = new ${@StringUtils.cap(child.className)}();
<%
for(c in child.columnList){
if (child.parentExists && child.parentTableFkName == c.columnName){
%>
${@StringUtils.uncap(child.className)}.set${@StringUtils.cap(c.simpleAttrName)}(${className});
<%
}
}
%>
${@StringUtils.uncap(child.className)}Dao.deleteByEntity(${@StringUtils.uncap(child.className)});
<% } %>
}
}]]>
</content>
</template>

View File

@@ -91,6 +91,11 @@ $('#dataGrid').dataGrid({
actions.push('<a href="\${ctx}/${urlPrefix}/form?parentCode='+row.id+'" class="btnList" title="\${text("新增下级${functionNameSimple}")}"><i class="fa fa-plus-square"></i></a>&nbsp;');
<% } %>
\<% } %>
<% if(toBoolean(table.optionMap['isBpmForm'])){ %>
if (row.status != Global.STATUS_DRAFT){
actions.push('<a href="\${ctx}/bpm/bpmRuntime/trace?formKey=${table.optionMap['bpmFormKey']}&bizKey='+row.id+'" class="btnList" title="\${text("流程追踪")}" data-layer="true"><i class="fa fa-file-picture-o"></i></a>&nbsp;');
}
<% } %>
<% } %>
return actions.join('');
}}

View File

@@ -0,0 +1,149 @@
<script>
var selectData = \${isNotBlank(selectData!) ? selectData! : "{\}"},
selectNum = 0, dataGrid = $('#dataGrid').dataGrid({
searchForm: $("#searchForm"),
columnModel: [
<%
// 是否是第一列
var firstColumn = true;
var firstColumnName = "";
// 生成树表的节点列
if(table.isTreeEntity){
for(c in table.columnList){
if(c.attrName == table.treeViewNameAttrName){
%>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:250, align:"left", frozen:true, formatter: function(val, obj, row, act){
return '( '+row.${table.treeViewCodeAttrName}+' ) '+(val||row.id);
}},
<%
firstColumn = false;
firstColumnName = c.attrName;
break;
}
}
}
%>
<%
for(c in table.columnList){
if(c.isList == "1"){
// 如果是树结构的字段,则自动忽略
if(table.isTreeEntity && @StringUtils.inString(c.columnName, 'parent_code',
'parent_codes', 'tree_sorts', 'tree_leaf', 'tree_level', 'tree_names')
&& c.attrName != table.treeViewCodeAttrName
&& c.attrName != table.treeViewNameAttrName){
}
// 如果是首列,则输出带链接的列
else if(firstColumn){
firstColumn = false;
firstColumnName = c.attrName;
%>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
return (val||row.id);
}},
<% }else if(c.showType == 'select' || c.showType == 'select_multiple' || c.showType == 'checkbox' || c.showType == 'radio'){ %>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:150, align:"center", formatter: function(val, obj, row, act){
return js.getDictLabel(\${@DictUtils.getDictListJson('${c.optionMap['dictType']}')}, val, '\${text("未知")}', true);
}},
<% }else if(c.showType == "userselect" || c.showType == "officeselect" || c.showType == "areaselect"){ %>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName2}', index:'a.${c.columnName}', width:150, align:"center"},
<% }else{
if (@StringUtils.inString(c.attrType, 'java.util.Date', 'Integer', 'Long')){
%>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:150, align:"center"},
<%
}else if (@StringUtils.inString(c.attrType, 'Float', 'Double')){
%>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:150, align:"right", formatter: function(val, obj, row, act){
return js.formatNumber(val, 2, false, ''); // 数值类型格式化 (原始数值, 小数位数, 是否千分位, 默认值金额情况下设置0.00);
}},
<%
}else {
%>
{header:'\${text("${c.columnLabel}")}', name:'${c.attrName}', index:'a.${c.columnName}', width:150, align:"left"},
<%
}
}
}
}
%>
{header:'行数据', name:'rowData', hidden:true, formatter: function(val, obj, row, act){
return JSON.stringify(row);
}}
],
<% if(table.isTreeEntity){ %>
treeGrid: true, // 启用树结构表格
defaultExpandLevel: 0, // 默认展开的层次
expandNodeClearPostData: '<%
for(c in table.columnList){
if(c.isQuery == "1" && !c.isTreeEntityColumn && c.attrName != 'status'){
print(c.attrName + ',');
}
} %>', // 展开节点清理请求参数数据(一般设置查询条件的字段属性,否则在查询后,不能展开子节点数据)
<% } %>
autoGridHeight: function(){
var height = $(window).height() - $('#searchForm').height() - $('#dataGridPage').height() - 74;
$('.tags-input').height($('.ui-jqgrid').height() - 10);
return height;
},
showCheckbox: '\${parameter.checkbox}' == 'true',
multiboxonly: false, // 单击复选框时再多选
ajaxSuccess: function(data){
$.each(selectData, function(key, value){
dataGrid.dataGrid('setSelectRow', key);
});
initSelectTag();
},
onSelectRow: function(id, isSelect, event){
if ('\${parameter.checkbox}' == 'true'){
if(isSelect){
selectData[id] = JSON.parse(dataGrid.dataGrid('getRowData', id).rowData);
}else{
delete selectData[id];
}
}else{
selectData = {};
selectData[id] = JSON.parse(dataGrid.dataGrid('getRowData', id).rowData);
}
initSelectTag();
},
onSelectAll: function(ids, isSelect){
if ('\${parameter.checkbox}' == 'true'){
for (var i=0; i<ids.length; i++){
if(isSelect){
selectData[ids[i]] = JSON.parse(dataGrid.dataGrid('getRowData', ids[i]).rowData);
}else{
delete selectData[ids[i]];
}
}
}
initSelectTag();
},
ondblClickRow: function(id, rownum, colnum, event){
if ('\${parameter.checkbox}' != 'true'){
js.layer.$('#' + window.name).closest('.layui-layer')
.find(".layui-layer-btn0").trigger("click");
}
initSelectTag();
}
});
function initSelectTag(){
selectNum = 0;
var html = [];
$.each(selectData, function(key, value){
selectNum ++;
html.push('<span class="tag" id="'+key+'_tags-input"><span>'+(value.${firstColumnName}||value.id)+' </span>'
+ '<a href="#" onclick="removeSelectTag(\''+key+'\');" title="\${text("取消选择")}">x</a></span>');
});
html.unshift('<div class="title">\${text("当前已选择 {0\} 项", "<span id=\"selectNum\">'+selectNum+'</span>")}</div>');
$('#selectData').empty().append(html.join(''));
}
function removeSelectTag(key){
delete selectData[key];
dataGrid.dataGrid('resetSelection', key);
$('#selectNum').html(--selectNum);
$('#'+key+'_tags-input').remove();
}
function getSelectData(){
return selectData;
}
</script>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>deploy</name>
<filePath>${module.moduleCode}/bin</filePath>
<fileName>deploy.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 部署工程版本到Nexus服务器。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin
cmd /c msg %username% /time:0 /w "部署完成..."
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>deploy</name>
<filePath>${module.moduleCode}/bin</filePath>
<fileName>deploy.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 部署工程版本到Nexus服务器。"
echo ""
cd ..
mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/bin</filePath>
<fileName>package.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包安装工程生成jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin
cmd /c msg %username% /time:0 /w "打包完成..."
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/bin</filePath>
<fileName>package.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程生成war/jar包文件。"
echo ""
cd ..
mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin]]>
</content>
</template>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>pom</name>
<filePath>${module.moduleCode}</filePath>
<fileName>pom.xml</fileName>
<charset></charset>
<content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-parent</artifactId>
<version>${jeesiteVersion}-SNAPSHOT</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<artifactId>jeesite-module-${module.moduleCode}</artifactId>
<packaging>jar</packaging>
<name>JeeSite Module ${module.moduleName}</name>
<url>http://jeesite.com</url>
<inceptionYear>2013-Now</inceptionYear>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-module-core</artifactId>
<version>\${project.parent.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
<pluginManagement>
<plugins>
</plugins>
</pluginManagement>
</build>
<developers>
<developer>
<id>thinkgem</id>
<name>WangZhen</name>
<email>thinkgem at 163.com</email>
<roles><role>Project lead</role></roles>
<timezone>+8</timezone>
</developer>
</developers>
<organization>
<name>JeeSite</name>
<url>http://jeesite.com</url>
</organization>
</project>
]]>
</content>
</template>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/src/main/java/com/jeesite/modules/${module.moduleCode}</filePath>
<fileName></fileName>
<content><![CDATA[
]]>
</content>
</template>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>jeesite</name>
<filePath>${module.moduleCode}/src/main/resources/config</filePath>
<fileName>jeesite-${module.moduleCode}.yml</fileName>
<content><![CDATA[
# 温馨提示不建议直接修改此文件为了平台升级方便建议将需要修改的参数值复制到application.yml里进行覆盖该参数值。
#${module.moduleCode}:
# enabled: true
]]>
</content>
</template>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>versions</name>
<filePath>${module.moduleCode}/src/main/resources/db/upgrade/${module.moduleCode}</filePath>
<fileName>versions</fileName>
<content><![CDATA[${module.currentVersion}]]>
</content>
</template>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>static</name>
<filePath>${module.moduleCode}/src/main/resources/static/modules/${module.moduleCode}</filePath>
<fileName></fileName>
<content><![CDATA[
]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>deploy</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client/bin</filePath>
<fileName>deploy.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 部署工程版本到Nexus服务器。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin
cmd /c msg %username% /time:0 /w "部署完成..."
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>deploy</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client/bin</filePath>
<fileName>deploy.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 部署工程版本到Nexus服务器。"
echo ""
cd ..
mvn clean deploy -Dmaven.test.skip=true -Pdeploy
cd bin]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client/bin</filePath>
<fileName>package.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包安装工程生成jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin
cmd /c msg %username% /time:0 /w "打包完成..."
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client/bin</filePath>
<fileName>package.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程生成war/jar包文件。"
echo ""
cd ..
mvn clean install -Dmaven.test.skip=true -Ppackage
cd bin]]>
</content>
</template>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>pom</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client</filePath>
<fileName>pom.xml</fileName>
<charset></charset>
<content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-cloud-parent</artifactId>
<version>${jeesiteVersion}-SNAPSHOT</version>
<relativePath>../../../parent/pom.xml</relativePath>
</parent>
<artifactId>jeesite-cloud-module-${module.moduleCode}-client</artifactId>
<packaging>jar</packaging>
<name>JeeSite Cloud Module ${module.moduleName} Client</name>
<url>http://jeesite.com</url>
<inceptionYear>2013-Now</inceptionYear>
<properties>
</properties>
<dependencies>
<!-- 云客户端 -->
<dependency>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-cloud-framework</artifactId>
<version>\${project.parent.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
<developers>
<developer>
<id>thinkgem</id>
<name>WangZhen</name>
<email>thinkgem at 163.com</email>
<roles><role>Project lead</role></roles>
<timezone>+8</timezone>
</developer>
</developers>
<organization>
<name>JeeSite</name>
<url>http://jeesite.com</url>
</organization>
</project>
]]>
</content>
</template>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}-client/src/main/java/com/jeesite/modules/${module.moduleCode}</filePath>
<fileName></fileName>
<content><![CDATA[
]]>
</content>
</template>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>docker-bulid</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>docker-bulid.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包Web工程导入到Docker服务。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package docker:stop docker:remove docker:build docker:run -Dmaven.test.skip=true -U
cd bin
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>docker-bulid</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>docker-bulid.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 使用 Spring Boot Docker 编译 Web 工程。"
echo ""
cd ..
mvn clean package docker:stop docker:remove docker:build docker:run -Dmaven.test.skip=true -U
cd bin]]>
</content>
</template>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>Dockerfile</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin/docker</filePath>
<fileName>Dockerfile</fileName>
<content><![CDATA[FROM frolvlad/alpine-java:jdk8-slim
MAINTAINER ThinkGem@163.com
ENV TZ "Asia/Shanghai"
ENV LANG C.UTF-8
VOLUME /tmp
WORKDIR /app
ADD ./maven/web.war ./app.war
RUN jar -xvf app.war
#RUN chmod -R 755 ./*
WORKDIR /app/WEB-INF
ADD ./app.yml ./classes/config/bootstrap-prod.yml
#ADD jeesite.lic ./
#ENV JAVA_OPTS "-Xms256m -Xmx1024m"
ENV JAVA_OPTS "$JAVA_OPTS -Dspring.profiles.active=prod"
ENTRYPOINT java $JAVA_OPTS -cp /app $JAVA_OPTS org.springframework.boot.loader.WarLauncher
EXPOSE 8983
#docker run -p 8983:8983 com.jeesite/jeesite-cloud-module-${module.moduleCode}:4.2
]]>
</content>
</template>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>app</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin/docker</filePath>
<fileName>app</fileName>
<content><![CDATA[
#======================================#
#========== Cloud settings ============#
#======================================#
# 服务注册
eureka:
# 实例设置
instance:
# 实例主机名称
hostname: 10.0.2.15
# 实例是否允许使用IP
preferIpAddress: false
# 客户端设置
client:
# 注册中心地址(集群时指定另外一个注册中心地址)
serviceUrl.defaultZone: http://10.0.2.15:8970/eureka/
#======================================#
#========== Spring settings ===========#
#======================================#
spring:
# 分布式配置中心
cloud:
config:
discovery:
enabled: true
serviceId: jeesite-cloud-config
# Consul 服务发现
consul:
host: 10.0.2.15
port: 8500
discovery:
hostname: 10.0.2.15
preferIpAddress: false
# 服务注册和配置
nacos:
discovery:
server-addr: 10.0.2.15:8848
config:
server-addr: 10.0.2.15:8848
file-extension: yml
group: jeesite-cloud-42
ext-config:
- data-id: application.yml
group: jeesite-cloud-42
]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>package.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包Web工程生成war/jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package spring-boot:repackage -Dmaven.test.skip=true -U
cd bin
cmd /c msg %username% /time:0 /w "打包完成..."
pause]]>
</content>
</template>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>package.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程生成war/jar包文件。"
echo ""
cd ..
mvn clean package spring-boot:repackage -Dmaven.test.skip=true -U
cd bin]]>
</content>
</template>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>run-tomcat</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>run-tomcat.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 使用 Spring Boot Tomcat 运行 Web 工程。
echo.
%~d0
cd %~dp0
cd ..
title %cd%
set "MAVEN_OPTS=%MAVEN_OPTS% -Xms512m -Xmx1024m"
call mvn clean spring-boot:run -Dmaven.test.skip=true
pause]]>
</content>
</template>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>run-tomcat</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>run-tomcat.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 使用 Spring Boot Tomcat 运行 Web 工程。"
echo ""
cd ..
MAVEN_OPTS="$MAVEN_OPTS -Xms512m -Xmx1024m"
mvn clean spring-boot:run -Dmaven.test.skip=true]]>
</content>
</template>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>run-web</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>run-web.bat</fileName>
<charset>GBK</charset>
<content><![CDATA[@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包Web工程并运行Web工程。
echo.
%~d0
cd %~dp0
rem 打包Web工程开始
cd ..
call mvn clean package spring-boot:repackage -Dmaven.test.skip=true -U
cd target
rem 打包Web工程结束
rem 根据情况修改 web.jar 为您的 jar 包名称
mkdir web
copy web.war web
cd web
jar -xvf web.war
cd WEB-INF
call startup.bat
pause]]>
</content>
</template>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>run-web</name>
<filePath>${module.moduleCode}/${module.moduleCode}/bin</filePath>
<fileName>run-web.sh</fileName>
<content><![CDATA[#!/bin/sh
# /**
# * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
# *
# * Author: ThinkGem@163.com
# *
# */
echo ""
echo "[信息] 打包Web工程并运行Web工程。"
echo ""
# 打包Web工程开始
cd ..
mvn clean package spring-boot:repackage -Dmaven.test.skip=true -U
cd target
# 打包Web工程结束
# 根据情况修改 web.jar 为您的 jar 包名称
mkdir web
cp web.war ./web
cd web
jar -xvf web.war
cd WEB-INF
exec ./startup.sh
]]>
</content>
</template>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>pom</name>
<filePath>${module.moduleCode}</filePath>
<fileName>pom.xml</fileName>
<charset></charset>
<content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-parent</artifactId>
<version>${jeesiteVersion}-SNAPSHOT</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<artifactId>jeesite-module-${module.moduleCode}</artifactId>
<packaging>jar</packaging>
<name>JeeSite Module ${module.moduleName}</name>
<url>http://jeesite.com</url>
<inceptionYear>2013-Now</inceptionYear>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-module-core</artifactId>
<version>\${project.parent.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
<pluginManagement>
<plugins>
</plugins>
</pluginManagement>
</build>
<developers>
<developer>
<id>thinkgem</id>
<name>WangZhen</name>
<email>thinkgem at 163.com</email>
<roles><role>Project lead</role></roles>
<timezone>+8</timezone>
</developer>
</developers>
<organization>
<name>JeeSite</name>
<url>http://jeesite.com</url>
</organization>
</project>
]]>
</content>
</template>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>package</name>
<filePath>${module.moduleCode}/${module.moduleCode}/src/main/java/com/jeesite/modules/${module.moduleCode}</filePath>
<fileName></fileName>
<content><![CDATA[
]]>
</content>
</template>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>start-class</name>
<filePath>${module.moduleCode}/${module.moduleCode}/src/main/java/com/jeesite/modules</filePath>
<fileName>${@StringUtils.cap(module.moduleCode)}Application.java</fileName>
<content><![CDATA[/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.modules;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* Application
* @author ThinkGem
* @version ${@DateUtils.getDate()}
*/
@SpringCloudApplication
@EnableFeignClients(basePackages={"com.jeesite.modules"})
public class ${@StringUtils.cap(module.moduleCode)}Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(${@StringUtils.cap(module.moduleCode)}Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
this.setRegisterErrorPageFilter(false); // 错误页面有容器来处理而不是SpringBoot
return builder.sources(${@StringUtils.cap(module.moduleCode)}Application.class);
}
}]]>
</content>
</template>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>bootstrap</name>
<filePath>${module.moduleCode}/${module.moduleCode}/src/main/resources/config</filePath>
<fileName>bootstrap.yml</fileName>
<content><![CDATA[
#======================================#
#========== Server settings ===========#
#======================================#
server:
port: 8989
#======================================#
#========== Cloud settings ============#
#======================================#
# 服务注册
eureka:
# 实例设置
instance:
# 实例主机名称
hostname: 127.0.0.1
# 实例是否允许使用IP
preferIpAddress: false
# 客户端设置
client:
# 注册中心地址(集群时指定另外一个注册中心地址)
serviceUrl.defaultZone: http://127.0.0.1:8970/eureka/
#======================================#
#========== Spring settings ===========#
#======================================#
spring:
# 应用程序名称
application:
name: jeesite-cloud-module-${module.moduleCode}
# 当前环境名称(注意:不可设置为 test 它是单元测试专用的名称)
profiles:
active: default
# 分布式配置中心
cloud:
config:
discovery:
enabled: true
serviceId: jeesite-cloud-config
# Consul 服务发现
consul:
host: 127.0.0.1
port: 8500
discovery:
hostname: 127.0.0.1
preferIpAddress: false
# 服务注册和配置
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml
group: jeesite-cloud-42
ext-config:
- data-id: application.yml
group: jeesite-cloud-42
# 打印横幅
main:
bannerMode: "off"
allow-bean-definition-overriding: true
# 日志配置
logging:
config: classpath:config/logback-spring.xml
]]>
</content>
</template>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>logback-spring</name>
<filePath>${module.moduleCode}/${module.moduleCode}/src/main/resources/config</filePath>
<fileName>logback-spring.yml</fileName>
<content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false">
<!-- Log file path -->
<property name="log.path" value="\${logPath:-\${java.io.tmpdir:-.}}/logs" />
<!-- Framework level setting -->
<include resource="config/logger-core.xml"/>
<!-- Project level setting -->
<!-- <logger name="your.package" level="DEBUG" /> -->
<logger name="org.springframework.context.annotation.AnnotationConfigApplicationContext" level="ERROR" />
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{MM-dd HH:mm:ss.SSS} %clr(%-5p) %clr([%-39logger{39}]){cyan} - %m%n%wEx</pattern>
</encoder>
</appender>
<!-- Log file debug output -->
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>\${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>\${log.path}/debug.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p \${PID:- } [%15.15t] [%-39logger{39}] - %m%n%wEx</pattern>
</encoder>
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>-->
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>\${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>\${log.path}/error.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p \${PID:- } [%15.15t] [%-39logger{39}] - %m%n%wEx</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="WARN">
<appender-ref ref="console" />
<appender-ref ref="debug" />
<appender-ref ref="error" />
</root>
</configuration>]]>
</content>
</template>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved. -->
<template>
<name>static</name>
<filePath>${module.moduleCode}/${module.moduleCode}/src/main/resources/static/modules/${module.moduleCode}</filePath>
<fileName></fileName>
<content><![CDATA[
]]>
</content>
</template>

View File

@@ -140,10 +140,12 @@ public class ${ClassName}Controller extends BaseController {
List<${ClassName}> list = ${className}Service.findList(new ${ClassName}());
for (int i=0; i<list.size(); i++){
${ClassName} e = list.get(i);
<% if (table.statusExists){ %>
// 过滤非正常的数据
if (!${ClassName}.STATUS_NORMAL.equals(e.getStatus())){
continue;
}
<% } %>
// 过滤被排除的编码(包括所有子级)
if (StringUtils.isNotBlank(excludeCode)){
if (e.getId().equals(excludeCode)){

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