Compare commits
211 Commits
v5.10.0.sp
...
v5.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6237f719b | ||
|
|
3cd5b2379d | ||
|
|
ad292502a9 | ||
|
|
1ac8085c8c | ||
|
|
df5e557f21 | ||
|
|
0484e1f64d | ||
|
|
6ac8a82718 | ||
|
|
163a387099 | ||
|
|
7b84892389 | ||
|
|
0d4701c8cc | ||
|
|
563571ae53 | ||
|
|
4575e6c211 | ||
|
|
49464e8bca | ||
|
|
9ccfd534d0 | ||
|
|
e68f96f3d6 | ||
|
|
07ba80ec4b | ||
|
|
3671148f56 | ||
|
|
6e56e515ae | ||
|
|
e6257a98c1 | ||
|
|
6a7817137a | ||
|
|
b32ffa3b6a | ||
|
|
95ec1770df | ||
|
|
9573da0309 | ||
|
|
aedd50c8c2 | ||
|
|
d8d8902e71 | ||
|
|
b4ffcf6f47 | ||
|
|
e3851a1066 | ||
|
|
47c88e5c6d | ||
|
|
05641a271e | ||
|
|
657f22da98 | ||
|
|
03ad0954e2 | ||
|
|
992e3c0cb7 | ||
|
|
c62f575d10 | ||
|
|
db5778a833 | ||
|
|
396e506936 | ||
|
|
2029cfc65a | ||
|
|
8de5edc40e | ||
|
|
37a74e7168 | ||
|
|
29345f8873 | ||
|
|
e9da7f1926 | ||
|
|
5cd3b507e4 | ||
|
|
533473b315 | ||
|
|
9eab7217cc | ||
|
|
553a0d652a | ||
|
|
4bc6d9e498 | ||
|
|
f1e7e5b8ee | ||
|
|
b99fcbad06 | ||
|
|
d9b626e925 | ||
|
|
0106d47779 | ||
|
|
30e4839da1 | ||
|
|
73d910ad13 | ||
|
|
a407593fc0 | ||
|
|
c3c377ba94 | ||
|
|
f130af6d7a | ||
|
|
ef4d06ff2e | ||
|
|
24d51e416e | ||
|
|
ed836c2f6a | ||
|
|
529d2b8192 | ||
|
|
9c0885b4c9 | ||
|
|
7ccbb05b7b | ||
|
|
53af15f85d | ||
|
|
21b15f16e3 | ||
|
|
8176853791 | ||
|
|
a56e29d8f7 | ||
|
|
081505f79c | ||
|
|
a6adfbc726 | ||
|
|
e883de354f | ||
|
|
f4909921ac | ||
|
|
0eb09a0dbb | ||
|
|
a58a2dcda2 | ||
|
|
1318ce840c | ||
|
|
0a771a7008 | ||
|
|
2ea481a417 | ||
|
|
07d3eef8ab | ||
|
|
f3c4a0dbe9 | ||
|
|
8f14549fee | ||
|
|
bccecc8b39 | ||
|
|
4a8bad7d35 | ||
|
|
8ef29563f5 | ||
|
|
87b8dc6ec4 | ||
|
|
b1f29a9d57 | ||
|
|
33eb95f120 | ||
|
|
4bfe7b2316 | ||
|
|
b0350b36d7 | ||
|
|
9f16332c09 | ||
|
|
419ed4f01b | ||
|
|
69cd032b7e | ||
|
|
c0aeef4881 | ||
|
|
e7c6e7e85b | ||
|
|
7f06df2bed | ||
|
|
250788a398 | ||
|
|
196cf4f10c | ||
|
|
3b587c661b | ||
|
|
7eb9484d7e | ||
|
|
c610af7c6b | ||
|
|
0c7cefb184 | ||
|
|
19d2399eb2 | ||
|
|
37b0a120c9 | ||
|
|
5fb6ab0ca6 | ||
|
|
2ba8b953d3 | ||
|
|
738fd5c552 | ||
|
|
745f6e88c0 | ||
|
|
3db837d6d6 | ||
|
|
14054a964f | ||
|
|
14581655d2 | ||
|
|
f162584d1e | ||
|
|
e57e8127b5 | ||
|
|
b7d4efa6a6 | ||
|
|
91a4db4eb8 | ||
|
|
7ed84e48cf | ||
|
|
f068bd9c90 | ||
|
|
4ae907a023 | ||
|
|
652a242c2b | ||
|
|
d242408de2 | ||
|
|
b8f51011ed | ||
|
|
84913ab783 | ||
|
|
b7bb765193 | ||
|
|
d1b06c45c8 | ||
|
|
19fe2023a6 | ||
|
|
590046d90c | ||
|
|
00c162ece1 | ||
|
|
d5deb38769 | ||
|
|
b71165f73c | ||
|
|
4260accf88 | ||
|
|
353131ab2c | ||
|
|
acb6baa226 | ||
|
|
5b7f7b0860 | ||
|
|
c57238e279 | ||
|
|
24ea4aaed0 | ||
|
|
0af1ae18c8 | ||
|
|
e054df919f | ||
|
|
a9ca557672 | ||
|
|
5bc76dd23d | ||
|
|
f337faeecc | ||
|
|
a6d84c59c9 | ||
|
|
b8279ffe64 | ||
|
|
af44331820 | ||
|
|
00ead34076 | ||
|
|
9b07e167f7 | ||
|
|
0fb15e31d6 | ||
|
|
3e769325f8 | ||
|
|
d555d508c3 | ||
|
|
11511c14bd | ||
|
|
2238ca062f | ||
|
|
3563f18335 | ||
|
|
983ad2faff | ||
|
|
f569da908d | ||
|
|
2e0718ba41 | ||
|
|
846bf82375 | ||
|
|
8cc6f25dd1 | ||
|
|
5ff9ca9815 | ||
|
|
31e6b01b4e | ||
|
|
bc8a6d2db7 | ||
|
|
9a13b33dd8 | ||
|
|
4bdba535bb | ||
|
|
09bf40feee | ||
|
|
5d74d2783f | ||
|
|
807b47dbc4 | ||
|
|
456cdaf883 | ||
|
|
d1b588b7d5 | ||
|
|
22a4b0fcf7 | ||
|
|
84407b5785 | ||
|
|
f5771c56a4 | ||
|
|
a3dee0f70a | ||
|
|
797abcdf87 | ||
|
|
0559c79687 | ||
|
|
f514b86bbc | ||
|
|
49992195df | ||
|
|
631225a108 | ||
|
|
5922951c16 | ||
|
|
5dc1b29a34 | ||
|
|
97252f7d82 | ||
|
|
efa8d7788a | ||
|
|
40c5759f59 | ||
|
|
13df22605b | ||
|
|
a2644570be | ||
|
|
da12b2d092 | ||
|
|
f5080cd8f5 | ||
|
|
729801bab5 | ||
|
|
0de77acca2 | ||
|
|
7128998483 | ||
|
|
1becabaea3 | ||
|
|
23b726e335 | ||
|
|
6909116d9a | ||
|
|
12132ab592 | ||
|
|
920a1a8916 | ||
|
|
eaa6646a74 | ||
|
|
696b7addb9 | ||
|
|
43fbbda930 | ||
|
|
727454d2a7 | ||
|
|
33d0693bb1 | ||
|
|
1eaff67ffd | ||
|
|
f54126bc07 | ||
|
|
fce22831ab | ||
|
|
ae17e2c2a4 | ||
|
|
db9ff3647a | ||
|
|
e5f5c4cd11 | ||
|
|
1098757b6a | ||
|
|
084bfaac92 | ||
|
|
e7ec4c52e8 | ||
|
|
02f0e1b300 | ||
|
|
e7e15fd15e | ||
|
|
a2d873fee5 | ||
|
|
48a93201e6 | ||
|
|
e3e222d7bb | ||
|
|
050aa6e4bf | ||
|
|
a0bfba3abb | ||
|
|
96838f50ad | ||
|
|
0a3c0e4bc8 | ||
|
|
0d24b71fe3 | ||
|
|
e658f9e6f6 |
129
README.md
129
README.md
@@ -2,110 +2,78 @@
|
||||
<p align="center">
|
||||
<img alt="JeeSite" src="https://jeesite.com/assets/images/logo.png" width="120" height="120" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
<h3 align="center" style="margin:30px 0 30px;font-weight:bold;font-size:30px;">快速开发平台 - Spring Boot 3</h3>
|
||||
<h3 align="center" style="margin:30px 0 30px;font-weight:bold;font-size:30px;">快速开发平台 - Spring Boot</h3>
|
||||
<p align="center">
|
||||
<a href="https://spring.io/projects/spring-boot" target="__blank"><img alt="SpringBoot-2.7/3.3" src="https://img.shields.io/badge/SpringBoot-V2.7/3.4-blue.svg"></a>
|
||||
<a href="https://v3.cn.vuejs.org/" target="__blank"><img alt="TypeScript-Vue3" src="https://img.shields.io/badge/TypeScript-Vue3-green.svg"></a>
|
||||
<a href="https://jeesite.com/docs/upgrade/" target="__blank"><img alt="JeeSite-5.9" src="https://img.shields.io/badge/JeeSite-V5.9-success.svg"></a>
|
||||
<a href="https://gitee.com/thinkgem/jeesite5" target="__blank"><img alt="star" src="https://gitee.com/thinkgem/jeesite5/badge/star.svg?theme=dark"></a>
|
||||
<a href="https://gitee.com/thinkgem/jeesite-vue" target="__blank"><img alt="star" src="https://gitee.com/thinkgem/jeesite-vue/badge/star.svg?theme=dark"></a>
|
||||
<a href="https://gitee.com/thinkgem/jeesite" target="__blank"><img alt="star" src="https://gitee.com/thinkgem/jeesite/badge/star.svg?theme=gvp"></a>
|
||||
<a href="https://gitcode.com/thinkgem/jeesite" target="__blank"><img alt="star" src="https://gitcode.com/thinkgem/jeesite/star/badge.svg"></a>
|
||||
<a href="https://jeesite.com/docs/upgrade/" target="__blank"><img alt="JeeSite-V5.7" src="https://img.shields.io/badge/JeeSite-V5.7-success.svg"></a>
|
||||
<a href="https://spring.io/projects/spring-boot#learn" target="__blank"><img alt="SpringBoot-2.7" src="https://img.shields.io/badge/SpringBoot-2.7-blue.svg"></a>
|
||||
<a href="https://gitee.com/thinkgem/jeesite5/stargazers" target="__blank"><img alt="star" src="https://gitee.com/thinkgem/jeesite5/badge/star.svg?theme=dark"></a>
|
||||
<a href="https://gitee.com/thinkgem/jeesite5/members" target="__blank"><img alt="fork" src="https://gitee.com/thinkgem/jeesite5/badge/fork.svg?theme=dark"></a>
|
||||
</p>
|
||||
|
||||
------
|
||||
|
||||
<div align="center">
|
||||
如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。
|
||||
</div>
|
||||
|
||||
------
|
||||
|
||||
## 技术交流
|
||||
|
||||
* 官方网站:<https://jeesite.com>
|
||||
* 使用文档:<https://jeesite.com/docs>
|
||||
* 交流 QQ 群(千人大群):`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)`
|
||||
* 码云Gitee:<https://gitee.com/thinkgem/jeesite5>
|
||||
* GitHub:<https://github.com/thinkgem/jeesite5>
|
||||
* 作者博客:<https://my.oschina.net/thinkgem>
|
||||
* **帮助文档:**<http://docs.jeesite.com>
|
||||
* 官方网站:<http://jeesite.com>
|
||||
* 问题反馈:<http://jeesite.net> [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR)
|
||||
* 需求收集:<https://gitee.com/thinkgem/jeesite5/issues/new>
|
||||
* 联系我们:<http://s.jeesite.com>
|
||||
* 关注微信公众号,了解最新动态:
|
||||
|
||||
<p style="padding-left:40px">
|
||||
<img alt="JeeSite微信公众号" src="https://jeesite.com/assets/images/mp.png" width="200">
|
||||
</p>
|
||||

|
||||
|
||||
* QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)`
|
||||
* 微信群:如果无法进入,可添加客服微信 jeesitex 邀请您进群
|
||||
|
||||
<p style="padding-left:40px">
|
||||
<img alt="JeeSite微信群" src="https://jeesite.com/assets/images/wxg_cur.png" width="200"/>
|
||||
</p>
|
||||
|
||||
* 源码仓库地址:
|
||||
[Gitee](https://gitee.com/thinkgem/jeesite5)、
|
||||
[GitCode](https://gitcode.com/thinkgem/jeesite5)、
|
||||
[GitHub](https://github.com/thinkgem/jeesite5)
|
||||
* 分离版源码仓库地址:
|
||||
[Gitee](https://gitee.com/thinkgem/jeesite-vue)、
|
||||
[GitCode](https://gitcode.com/thinkgem/jeesite-vue)、
|
||||
[GitHub](https://github.com/thinkgem/jeesite-vue)
|
||||
* 源码合集仓库地址:
|
||||
[GVP](https://gitee.com/thinkgem/jeesite/tree/v5.springboot3)、
|
||||
[G-Star](https://gitcode.com/thinkgem/jeesite/overview?ref=v5.springboot3)、
|
||||
[GitHub](https://github.com/thinkgem/jeesite/tree/v5.springboot3)
|
||||
* 源码仓库地址:<https://gitee.com/thinkgem/jeesite5>
|
||||
* 分离版前端源码仓库:<https://gitee.com/thinkgem/jeesite-vue>
|
||||
|
||||
## 平台介绍
|
||||
|
||||
* JeeSite 快速开发平台,不仅仅是一个后台开发框架,它是一个企业级快速开发解决方案,后端基于经典组合 Spring Boot、Shiro、MyBatis,前端采用 Beetl、Bootstrap、AdminLTE 经典开发模式,或者分离版 Vue3、Vite、Ant Design Vue、TypeScript、Vben Admin 最先进技术栈。
|
||||
JeeSite 快速开发平台,不仅仅是一个后台开发框架,它是一个企业级快速开发解决方案,后端基于经典组合 Spring Boot、Shiro、MyBatis,前端采用 Beetl、Bootstrap、AdminLTE 经典开发模式,或者分离版 Vue3、Vite、Ant Design Vue、TypeScript、Vben Admin 最先进技术栈。
|
||||
|
||||
* 提供在线数据源管理、数据表建模、代码生成等功能,可自动创建业务模块代码工程和微服务模块代码工程,自动生成前端代码和后端代码;包括核心功能模块如:组织机构、用户、角色、岗位、管理员、权限审计、菜单及按钮权限、数据权限、模块管理、系统参数、字典管理、系统监控、数据监控等;扩展功能如:工作流引擎、内容管理、消息推送、单点登录、第三方登录、在线作业调度、对象存储、可视化数据大屏、报表设计器、在线文件预览、国际化、全文检索、统一认证服务等。
|
||||
提供在线代码生成功能,可自动创建业务模块工程和微服务模块工程,自动生成前端代码和后端代码;包括功能模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。
|
||||
|
||||
* 本平台采用松耦合设计,微内核和插件架构,模块增减便捷,支持集群,支持 SaaS 架构,支持读写分离、分库分表、Spring Cloud 微服务架构;并内置了众多账号安全设置、密码策略、系统访问限制等安全解决方案,支持等保评测。
|
||||
采用松耦合设计,微内核和插件架构,模块增减便捷;界面细节到位,一键换肤;众多账号安全设置,密码策略;文件在线预览;消息推送;多元化第三方登录;在线定时任务配置;支持集群,支持SAAS;支持多数据源;支持读写分离、分库分表;支持微服务应用。
|
||||
|
||||
* 本平台专注于为初级研发人员提供强大的支持,使他们能够高效、快速地开发出复杂的业务功能,同时为中高级人员腾出宝贵的时间,专注于更具战略性和创新性的任务。我们致力于让开发者能够全心投入业务逻辑中,而将繁琐的技术细节交由平台来封装处理。这不仅降低了技术实现的难度,还确保了系统架构的稳定性和安全性,进而帮助企业节省人力成本、缩短项目周期,并提高整体软件的安全性和质量。
|
||||
主要目的是能够让初级的研发人员快速的开发出复杂的业务功能,中高级人员有时间做一些更有用的事情。让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
|
||||
|
||||
* 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中,拥有:精良架构、易于扩展、大众思维的设计模式,工匠精神,用心打磨每一个细节,深入开发者的内心,并荣获开源中国《最受欢迎中国开源软件》多次奖项,期间也帮助了不少刚毕业的大学生,教师作为入门教材,快速的去实践。
|
||||
JeeSite 自 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中,拥有:精良架构、易于扩展、大众思维的设计模式,工匠精神,用心打磨每一个细节,深入开发者的内心,并荣获开源中国《最受欢迎中国开源软件》多次奖项,期间也帮助了不少刚毕业的大学生,教师作为入门教材,快速的去实践。
|
||||
|
||||
* 2019 年换代升级,我们结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集等众多安全选项供您选择。努力为大中小微企业打造全方位企业级快速开发解决方案。
|
||||
2019 年换代升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集等众多安全选项供您选择。努力为大中小微企业打造全方位企业级快速开发解决方案。
|
||||
|
||||
* 2021 年终发布 Vue3 的前后分离版本,使得 JeeSite 拥有同一个后台服务 Web 来支撑分离版和全栈版两套前端技术栈。
|
||||
2021 年终发布 Vue3 的前后分离版本,使得 JeeSite 拥有同一个后台服务 Web 来支撑分离版和全栈版两套前端技术栈。
|
||||
|
||||
* 支持国产化软硬件环境,如国产芯片、操作系统、数据库、中间件、国密算法等。
|
||||
## 平台优势
|
||||
|
||||
## 核心优势
|
||||
JeeSite 非常易于二次开发,可控性高,整体架构清晰、技术稳定而先进、源代码书写规范、经典技术会的人多、易于维护、易于扩展、安全稳定。
|
||||
|
||||
* JeeSite 非常易于二次开发,可控性高,整体架构清晰、技术稳定而先进、源代码书写规范、经典技术会的人多、易于维护、易于扩展、安全稳定。
|
||||
JeeSite 功能全,知识点非常多,也非常少。因为她使用的都是一些通用的技术,通俗的设计风格,大多数基础知识点,多数人都能掌握,所以每一个 JeeSite 的功能点都非常容易掌握。只要您学会使用这些功能和组件的应用,就可以顺利的完成系统开发了。
|
||||
|
||||
* JeeSite 功能全,知识点非常多,也非常少。因为她使用的都是一些通用的技术,通俗的设计风格,大多数基础知识点,多数人都能掌握,所以每一个 JeeSite 的功能点都非常容易掌握。只要您学会使用这些功能和组件的应用,就可以顺利的完成系统开发了。
|
||||
JeeSite 是一个低代码开发平台,具有较高的封装度、扩展性,封装不是限制您去做一些事情,而是在便捷的同时,也具有较好的扩展性,在不具备一些功能的情况下,JeeSite 提供了扩展接口,提供了原生调用方法。
|
||||
|
||||
* JeeSite 是一个低代码开发平台,具有较高的封装度、扩展性,封装不是限制您去做一些事情,而是在便捷的同时,也具有较好的扩展性,在不具备一些功能的情况下,JeeSite 提供了扩展接口,提供了原生调用方法。
|
||||
大家都在用 Spring,也在学习 Spring 的优点,Spring 提供了较好的扩展性,可又有多少人去修改它的源代码呢,退一步说,大家去修改了 Spring 的源码,反而会对未来升级造成很大困扰,您说不是呢?这样的例子很多,所以不要纠结,我们非常注重这一点,JeeSite 也一样具备强大的扩展性。
|
||||
|
||||
* 大家都在用 Spring,也在学习 Spring 的优点,Spring 提供了较好的扩展性,可又有多少人去修改它的源代码呢,退一步说,大家去修改了 Spring 的源码,反而会对未来升级造成很大困扰,您说不是呢?这样的例子很多,所以不要纠结,我们非常注重这一点,JeeSite 也一样具备强大的扩展性。为你解决升级的困扰。
|
||||
为什么说 JeeSite 比较易于学习?JeeSite 很好的把握了设计的 “度”,避免过度设计的情况。过度设计是在产品设计过程中忽略了产品和用户的实际需求,反而带来了不必要的复杂性,而忽略了系统的学习、开发和维护成本。
|
||||
|
||||
* 为什么说 JeeSite 比较易于学习?JeeSite 很好的把握了设计的 “度”,避免过度设计的情况。过度设计是在产品设计过程中忽略了产品和用户的实际需求,反而带来了不必要的复杂性,而忽略了系统的学习、开发和维护成本。
|
||||
|
||||
------
|
||||
|
||||
* 至今 JeeSite 平台架构已经非常稳定,我们持续升级,并不失架构的先进性。
|
||||
* JeeSite 精益求精,用心打磨每一个细节,界面 UI 操作便捷,体验性好。
|
||||
* JeeSite 是一个专业的平台,是一个可以让您使用放心的平台。
|
||||
* 至今 JeeSite 平台架构已经非常稳定。
|
||||
* JeeSite 精益求精,用心打磨每一个细节。
|
||||
* JeeSite 是一个专业的平台,是一个让你使用放心的平台。
|
||||
* 社区版基于 Apache License 2.0 开源协议,永久免费使用。
|
||||
|
||||
### 架构特点及安全方面的优势:<https://jeesite.com/docs/feature/>
|
||||
|
||||
## 技术选型
|
||||
|
||||
* 主框架:Spring Boot 3.3、Spring Framework 6.1、Apache Shiro 2.0、J2Cache
|
||||
* 持久层:Apache MyBatis 3.5、Hibernate Validator 8.0、Alibaba Druid 1.2
|
||||
* 视图层:Spring MVC 6.1、Beetl 3.10(替换JSP)、Bootstrap 3.3、AdminLTE 2.4
|
||||
* 主框架:Spring Boot 2.7、Spring Framework 5.3、Apache Shiro 1.12、J2Cache
|
||||
* 持久层:Apache MyBatis 3.5、Hibernate Validator 6.2、Alibaba Druid 1.2
|
||||
* 视图层:Spring MVC 5.3、Beetl 3.10(替换JSP)、Bootstrap 3.3、AdminLTE 2.4
|
||||
* 前端组件:jQuery 3.7、jqGrid 4.7、layer 3.5、zTree 3.5、jQuery Validation
|
||||
* 分离前端版:Node.js、TypeScript、Vue3、Vite、Ant Design Vue、Vue Vben Admin
|
||||
* 工作流引擎:Flowable 7.1、符合 BPMN 规范、在线流程设计器、中国式流程、退回、撤回、自由流
|
||||
* Bootstrap 版 支持 IE10 及以上版本及其他所有现代浏览器,如:谷歌、火狐、国产浏览器 等
|
||||
* 工作流引擎:Flowable 6.6、符合 BPMN 规范、在线流程设计器、中国式流程、退回、撤回、自由流
|
||||
* Bootstrap 版 支持 IE9 及以上版本及其他所有现代浏览器,如:谷歌、火狐、国产浏览器 等
|
||||
* Vue3 版 支持现代浏览器,如:谷歌 Chrome 86+、火狐、国产浏览器 等
|
||||
* 技术选型(详细):<http://jeesite.com/docs/technology/>
|
||||
* JeeSite Vue 版本:<https://gitee.com/thinkgem/jeesite-vue>
|
||||
* Spring Boot 2.x 版本:<https://gitee.com/thinkgem/jeesite5/tree/v5.9>
|
||||
* Spring Boot 3.x 版本:<https://gitee.com/thinkgem/jeesite5/tree/v5.springboot3>
|
||||
|
||||
## 更多介绍
|
||||
|
||||
@@ -119,13 +87,13 @@
|
||||
|
||||
* 分布式微服务(Spring Cloud):<https://gitee.com/thinkgem/jeesite-cloud>
|
||||
* Flowable业务流程引擎(BPM):<http://jeesite.com/docs/bpm/>
|
||||
* JFlow工作流引擎:<https://gitee.com/thinkgem/jeesite-jflow>
|
||||
* 多站点内容管理模块(CMS):<https://jeesite.com/docs/cms/>
|
||||
* 手机端移动端:<https://gitee.com/thinkgem/jeesite-uniapp>
|
||||
* PC客户端程序:<https://gitee.com/thinkgem/jeesite-client>
|
||||
* Vue3分离版本:<https://gitee.com/thinkgem/jeesite-vue>
|
||||
* JeeSite统一认证:<https://jeesite.com/docs/oauth2-server>
|
||||
* JFlow工作流引擎:<https://gitee.com/thinkgem/jeesite-jflow>
|
||||
* Mybatis-Plus: <https://gitee.com/thinkgem/jeesite-mybatisplus>
|
||||
* MybatisPlus: <https://gitee.com/thinkgem/jeesite-mybatisplus>
|
||||
* Magic接口快速开发:<https://gitee.com/thinkgem/jeesite-magic-api>
|
||||
* 内外网中间件:<https://my.oschina.net/thinkgem/blog/4624519>
|
||||
|
||||
@@ -133,13 +101,13 @@
|
||||
|
||||
### 在线演示
|
||||
|
||||
1. 全栈版地址:<http://demo.jeesite.com>
|
||||
1. 全栈版地址:<http://vue.jeesite.com/js>
|
||||
2. Vue3分离版地址:<http://vue.jeesite.com>
|
||||
|
||||
### 本地运行
|
||||
|
||||
1. 环境准备:`JDK 17+`、`Maven 3.8+`、使用 `MySQL 5.7 or 8.x` 数据库、[其它数据库](https://jeesite.com/docs/technology/#_8、已支持数据库)
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite5/repository/archive/v5.springboot3.zip> 并解压
|
||||
1. 环境准备:`JDK 1.8 or 11、17`、`Maven 3.6+`、使用 `MySQL 5.7 or 8.0` 数据库、[其它数据库](https://jeesite.com/docs/technology/#_8、已支持数据库)
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite5/repository/archive/v5.7.zip> 并解压
|
||||
3. 打开文件:`/web/src/main/resources/config/application.yml` 配置JDBC连接
|
||||
4. 执行脚本:`/web/bin/init-data.bat` 初始化数据库
|
||||
5. 执行脚本:`/web/bin/run-tomcat.bat` 启动服务即可
|
||||
@@ -149,12 +117,12 @@
|
||||
|
||||
### 快速运行
|
||||
|
||||
1. 环境准备:`JDK 17+`、`Maven 3.8+`、无需准备数据库(使用内嵌 H2 DB、Vue资源包)
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite5/repository/archive/v5.springboot3.zip> 并解压
|
||||
1. 环境准备:`JDK 1.8 or 11、17`、`Maven 3.6+`、无需准备数据库(使用内嵌 H2 DB、Vue资源包)
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite5/repository/archive/v5.7.zip> 并解压
|
||||
3. 执行脚本:`/web-fast/bin/run-tomcat.bat` 启动服务即可(自动初始化库)
|
||||
4. Vue分离版本地址:<http://127.0.0.1:8980/vue/login>
|
||||
5. 全栈版本地址:<http://127.0.0.1:8980/a/login>
|
||||
6. 初始登录账号:超级管理员:system 密码:admin
|
||||
4. 全栈版本地址:<http://127.0.0.1:8980/a/login>
|
||||
5. Vue分离版本地址:<http://127.0.0.1:8980/vue/login>
|
||||
6. 默认超级管理员账号:system 密码 admin
|
||||
7. 部署常见问题:<https://jeesite.com/docs/faq/>
|
||||
|
||||
### 容器运行
|
||||
@@ -243,11 +211,10 @@ docker run --name jeesite-web -p 8980:8980 -d --restart unless-stopped \
|
||||
7. 本项目已申请软件著作权,请尊重开源,感谢阅读。
|
||||
8. 无用户数限制,无在线人数限制,放心使用。
|
||||
|
||||
## 技术支持与服务
|
||||
## 技术服务与支持
|
||||
|
||||
* 本软件免费,我们也提供了相应的收费服务,因为:
|
||||
* 没有资金的支撑就很难得到发展,特别是一个好的产品,如果 JeeSite 帮助了您,请为我们点赞。支持我们,您可以获得更多回馈,我们会把公益事业做的更好,开放更多资源,回报社区和社会。请给我们一些动力吧,在此非常感谢已支持我们的朋友!
|
||||
* **联系我们**:请访问技术支持与服务页面:<http://s.jeesite.com>
|
||||
* **联系我们**:请访问技术支持服务页面:<https://jeesite.com/docs/support/>
|
||||
|
||||
## 今后如何升级?
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>5.10.0.springboot3-SNAPSHOT</version>
|
||||
<version>5.7.1-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
<!-- Servlet Api -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>${commons-text.version}</version>
|
||||
<version>${commons-text.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
@@ -45,12 +45,12 @@
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Fury serialize -->
|
||||
|
||||
<!-- Java serialization -->
|
||||
<dependency>
|
||||
<groupId>org.apache.fury</groupId>
|
||||
<artifactId>fury-core</artifactId>
|
||||
<version>${fury.version}</version>
|
||||
<groupId>de.ruedigermoeller</groupId>
|
||||
<artifactId>fst</artifactId>
|
||||
<version>${fst.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson json -->
|
||||
@@ -91,7 +91,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Email -->
|
||||
@@ -119,7 +118,7 @@
|
||||
<artifactId>metadata-extractor</artifactId>
|
||||
<version>${metadata-extractor.version}</version>
|
||||
</dependency> -->
|
||||
<!-- 缩略图工具 -->
|
||||
<!-- 缩略图工具 -->
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
@@ -131,7 +130,7 @@
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<version>${twelvemonkeys.version}</version>
|
||||
</dependency>
|
||||
<!-- 图片验证码生成 -->
|
||||
<!-- 图片验证码生成 -->
|
||||
<dependency>
|
||||
<groupId>com.bladejava</groupId>
|
||||
<artifactId>blade-patchca</artifactId>
|
||||
@@ -162,7 +161,7 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 条形码、二维码生成 -->
|
||||
<!-- 条形码、二维码生成 -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
@@ -197,19 +196,12 @@
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Pinyin4j -->
|
||||
<!-- pinyin4j -->
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
<version>${pinyin4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- BC Provider -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>${bcprov.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging begin -->
|
||||
<dependency>
|
||||
@@ -264,13 +256,13 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
<developers>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>thinkgem</id>
|
||||
<name>WangZhen</name>
|
||||
<email>thinkgem at 163.com</email>
|
||||
<roles><role>Project lead</role></roles>
|
||||
<timezone>+8</timezone>
|
||||
<timezone>+8</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
|
||||
@@ -4,175 +4,176 @@
|
||||
*/
|
||||
package com.jeesite.common.codec;
|
||||
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
|
||||
/**
|
||||
* AES 加密解密工具类
|
||||
* AES加密解密工具类
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public class AesUtils {
|
||||
|
||||
private static final String AES = "AES";
|
||||
private static final String AES_CBC = "AES/CBC/PKCS5Padding";
|
||||
private static final int DEFAULT_KEY_SIZE = 128; // 生成AES密钥, 默认长度为128位(16字节).
|
||||
private static final int DEFAULT_IV_SIZE = 16; // 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
|
||||
private static final int DEFAULT_AES_KEYSIZE = 128; // 生成AES密钥, 默认长度为128位(16字节).
|
||||
private static final int DEFAULT_IVSIZE = 16; // 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
|
||||
private static final SecureRandom RANDOM = new SecureRandom(); // 用于 生成 generateIV随机数对象
|
||||
|
||||
private static final byte[] DEFAULT_KEY = EncodeUtils.decodeHex(PropertiesUtils.getInstance()
|
||||
.getProperty("encrypt.defaultKey", "9f58a20946b47e190003ec716c1c457d"));
|
||||
private static final boolean STORE_BASE64 = PropertiesUtils.getInstance()
|
||||
.getPropertyToBoolean("encrypt.storeBase64", "false");
|
||||
private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
|
||||
|
||||
/**
|
||||
* 生成 AES 密钥,返回字节数组, 默认长度为128位(16字节)
|
||||
*/
|
||||
public static byte[] genKey() {
|
||||
return genKey(DEFAULT_KEY_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 AES 密钥, 返回字节数组, 默认长度为128位(16字节)
|
||||
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
|
||||
*/
|
||||
public static String genKeyString() {
|
||||
return EncodeUtils.encodeHex(genKey());
|
||||
return EncodeUtils.encodeHex(genKey(DEFAULT_AES_KEYSIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
*/
|
||||
public static String encode(String input) {
|
||||
try {
|
||||
return EncodeUtils.encodeHex(encode(input.getBytes(EncodeUtils.UTF_8), DEFAULT_KEY));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static String encode(String input, String key) {
|
||||
try {
|
||||
return EncodeUtils.encodeHex(encode(input.getBytes(EncodeUtils.UTF_8), EncodeUtils.decodeHex(key)));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
*/
|
||||
public static String decode(String input) {
|
||||
try {
|
||||
return new String(decode(EncodeUtils.decodeHex(input), DEFAULT_KEY), EncodeUtils.UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static String decode(String input, String key) {
|
||||
try {
|
||||
return new String(decode(EncodeUtils.decodeHex(input), EncodeUtils.decodeHex(key)), EncodeUtils.UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 AES 密钥, 可选长度为128,192,256位
|
||||
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
|
||||
*/
|
||||
public static byte[] genKey(int keySize) {
|
||||
public static byte[] genKey() {
|
||||
return genKey(DEFAULT_AES_KEYSIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AES密钥,可选长度为128,192,256位.
|
||||
*/
|
||||
public static byte[] genKey(int keysize) {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
|
||||
keyGenerator.init(keySize);
|
||||
keyGenerator.init(keysize);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw ExceptionUtils.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
|
||||
* 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
|
||||
*/
|
||||
public static byte[] genIV() {
|
||||
byte[] bytes = new byte[DEFAULT_IV_SIZE];
|
||||
byte[] bytes = new byte[DEFAULT_IVSIZE];
|
||||
RANDOM.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密原始字符串
|
||||
* @param input 原始输入字符串
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String encode(String input) {
|
||||
if (STORE_BASE64) {
|
||||
return EncodeUtils.encodeBase64(encode(input.getBytes(StandardCharsets.UTF_8), DEFAULT_KEY));
|
||||
}
|
||||
return EncodeUtils.encodeHex(encode(input.getBytes(StandardCharsets.UTF_8), DEFAULT_KEY));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密原始字符串
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合要求的密钥
|
||||
* @author ThinkGem
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static byte[] encode(byte[] input, byte[] key) {
|
||||
return aes(input, key, Cipher.ENCRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密原始字符串
|
||||
* @param input 原始输入字符串
|
||||
* @param key 符合要求的密钥
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String encode(String input, String key) {
|
||||
if (STORE_BASE64) {
|
||||
return EncodeUtils.encodeBase64(encode(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(key)));
|
||||
}
|
||||
return EncodeUtils.encodeHex(encode(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密原始字符串
|
||||
* 使用AES加密原始字符串.
|
||||
*
|
||||
* @param input 原始输入字符数组
|
||||
* @param key 符合要求的密钥
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static byte[] encode(byte[] input, byte[] key, byte[] iv) {
|
||||
return aes(input, key, iv, Cipher.ENCRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 解密数据, 返回原始字符串
|
||||
* @param input Hex 或 Base64 编码的加密字符串
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String decode(String input) {
|
||||
if (STORE_BASE64) {
|
||||
return new String(decode(EncodeUtils.decodeBase64(input), DEFAULT_KEY), StandardCharsets.UTF_8);
|
||||
}
|
||||
return new String(decode(EncodeUtils.decodeHex(input), DEFAULT_KEY), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 解密数据, 返回原始字符串
|
||||
* @param input 加密输入字符数组
|
||||
* @param key 符合要求的密钥
|
||||
* @author ThinkGem
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
*/
|
||||
public static byte[] decode(byte[] input, byte[] key) {
|
||||
return aes(input, key, Cipher.DECRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 解密数据, 返回原始字符串
|
||||
* @param input Hex 或 Base64 编码的加密字符串
|
||||
* @param key 符合要求的密钥
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String decode(String input, String key) {
|
||||
if (STORE_BASE64) {
|
||||
return new String(decode(EncodeUtils.decodeBase64(input), EncodeUtils.decodeHex(key)), StandardCharsets.UTF_8);
|
||||
}
|
||||
return new String(decode(EncodeUtils.decodeHex(input), EncodeUtils.decodeHex(key)), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 解密数据, 返回原始字符串
|
||||
* 使用AES解密字符串, 返回原始字符串.
|
||||
*
|
||||
* @param input Hex编码的加密字符串
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static byte[] decode(byte[] input, byte[] key, byte[] iv) {
|
||||
return aes(input, key, iv, Cipher.DECRYPT_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密或解密无编码的原始字节数组, 返回无编码的字节数组结果
|
||||
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
|
||||
*
|
||||
* @param input 原始字节数组
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
|
||||
* @author ThinkGem
|
||||
*/
|
||||
private static byte[] aes(byte[] input, byte[] key, int mode) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(AES);
|
||||
SecretKey secretKey = new SecretKeySpec(key, AES);
|
||||
Cipher cipher = Cipher.getInstance(AES);
|
||||
cipher.init(mode, secretKey);
|
||||
return cipher.doFinal(input);
|
||||
} catch (GeneralSecurityException e) {
|
||||
@@ -181,18 +182,18 @@ public class AesUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 AES 加密或解密无编码的原始字节数组, 返回无编码的字节数组结果
|
||||
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
|
||||
*
|
||||
* @param input 原始字节数组
|
||||
* @param key 符合AES要求的密钥
|
||||
* @param iv 初始向量
|
||||
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
|
||||
* @author ThinkGem
|
||||
*/
|
||||
private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(AES_CBC);
|
||||
SecretKey secretKey = new SecretKeySpec(key, AES);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
Cipher cipher = Cipher.getInstance(AES_CBC);
|
||||
cipher.init(mode, secretKey, ivSpec);
|
||||
return cipher.doFinal(input);
|
||||
} catch (GeneralSecurityException e) {
|
||||
@@ -200,4 +201,18 @@ public class AesUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
//
|
||||
// String s = "hello word!";
|
||||
// System.out.println(s);
|
||||
//
|
||||
// String k = genKeyString();
|
||||
// System.out.println(k);
|
||||
// String ss = encode(s, k);
|
||||
// System.out.println(ss);
|
||||
// String sss = decode(ss, k);
|
||||
// System.out.println(sss);
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -4,13 +4,15 @@
|
||||
*/
|
||||
package com.jeesite.common.codec;
|
||||
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
|
||||
/**
|
||||
* 不可逆加密工具类
|
||||
@@ -18,15 +20,11 @@ import java.security.*;
|
||||
*/
|
||||
public class DigestUtils {
|
||||
|
||||
public static final String SHA1 = "SHA-1";
|
||||
public static final String MD5 = "MD5";
|
||||
public static final String SM3 = "SM3";
|
||||
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
|
||||
/**
|
||||
* 生成随机的 Byte[] 作为 salt 密钥.
|
||||
* @param numBytes byte 数组的大小
|
||||
* 生成随机的Byte[]作为salt密钥.
|
||||
* @param numBytes byte数组的大小
|
||||
*/
|
||||
public static byte[] genSalt(int numBytes) {
|
||||
Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
|
||||
@@ -34,41 +32,25 @@ public class DigestUtils {
|
||||
random.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机的 Byte[] 作为 salt 密钥,返回 HEX 值
|
||||
* @param numBytes byte 数组的大小
|
||||
*/
|
||||
public static String genSaltString(int numBytes) {
|
||||
return EncodeUtils.encodeHex(genSalt(numBytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 MessageDigest
|
||||
*/
|
||||
private static MessageDigest getMessageDigest(String algorithm) throws GeneralSecurityException {
|
||||
if (SM3.equals(algorithm)) {
|
||||
return MessageDigest.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME);
|
||||
} else {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串进行散列, 支持md5与sha1算法.
|
||||
* @param input 需要散列的字符串
|
||||
* @param algorithm 散列算法("SHA-1"、"MD5"、"SM3")
|
||||
* @param salt 可为空
|
||||
* @param algorithm 散列算法("SHA-1"、"MD5")
|
||||
* @param salt
|
||||
* @param iterations 迭代次数
|
||||
* @return
|
||||
*/
|
||||
public static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
|
||||
try {
|
||||
MessageDigest digest = getMessageDigest(algorithm);
|
||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||
|
||||
if (salt != null) {
|
||||
digest.update(salt);
|
||||
}
|
||||
|
||||
byte[] result = digest.digest(input);
|
||||
|
||||
for (int i = 1; i < iterations; i++) {
|
||||
digest.reset();
|
||||
result = digest.digest(result);
|
||||
@@ -82,18 +64,20 @@ public class DigestUtils {
|
||||
/**
|
||||
* 对文件进行sha1散列.
|
||||
* @param input 需要散列的流
|
||||
* @param algorithm 散列算法("SHA-1"、"MD5"、"SM3")
|
||||
* @param algorithm 散列算法("SHA-1"、"MD5")
|
||||
*/
|
||||
public static byte[] digest(InputStream input, String algorithm) throws IOException {
|
||||
try {
|
||||
MessageDigest messageDigest = getMessageDigest(algorithm);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
|
||||
int bufferLength = 8 * 1024;
|
||||
byte[] buffer = new byte[bufferLength];
|
||||
int read = input.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
messageDigest.update(buffer, 0, read);
|
||||
read = input.read(buffer, 0, bufferLength);
|
||||
}
|
||||
|
||||
return messageDigest.digest();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw ExceptionUtils.unchecked(e);
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
@@ -26,11 +26,11 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 封装各种格式的编码解码工具类.
|
||||
* 1. Commons-Codec 的 hex/base64 编码
|
||||
* 2. 自制的 base62 编码
|
||||
* 3. Commons-Lang 的 xml/html escape
|
||||
* 4. JDK 提供的 URLEncoder
|
||||
* 5. XSS、SQL、orderBy 过滤器
|
||||
* 1.Commons-Codec的 hex/base64 编码
|
||||
* 2.自制的base62 编码
|
||||
* 3.Commons-Lang的xml/html escape
|
||||
* 4.JDK提供的URLEncoder
|
||||
* 5、XSS、SQL、orderBy 过滤器
|
||||
* @author calvin、ThinkGem
|
||||
* @version 2022-2-17
|
||||
*/
|
||||
@@ -304,4 +304,38 @@ public class EncodeUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// xssFilter("1 你好 <script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("2 你好 <strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->3 你好 \"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->4 你好 <iframe src=\"abcdef\"></iframe><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->5 你好 <iframe src=\"abcdef\"/><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->6 你好 <iframe src=\"abcdef\"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->7 你好 <script type=\"text/javascript\">alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->8 你好 <script\n type=\"text/javascript\">\nalert(document.cookie)\n</script>我还在。");
|
||||
// xssFilter("<!--HTML-->9 你好 <script src='' onerror='alert(document.cookie)'></script>我还在。");
|
||||
// xssFilter("<!--HTML-->10 你好 <script type=text/javascript>alert()我还在。");
|
||||
// xssFilter("<!--HTML-->11 你好 <script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->12 你好 <script>window.location='url'我还在。");
|
||||
// xssFilter("<!--HTML-->13 你好 </script></iframe>我还在。");
|
||||
// xssFilter("<!--HTML-->14 你好 eval(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->15 你好 expression(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->16 你好 <img src='abc.jpg' onerror='location='';alert(document.cookie);'></img>我还在。");
|
||||
// xssFilter("<!--HTML-->17 你好 <img src='abc.jpg' onerror='alert(document.cookie);'/>我还在。");
|
||||
// xssFilter("<!--HTML-->18 你好 <img src='abc.jpg' onerror='alert(document.cookie);'>我还在。");
|
||||
// xssFilter("<!--HTML-->19 你好 <a onload='alert(\"abc\")'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->20 你好 <a href=\"/abc\">hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->21 你好 <a href='/abc'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->22 你好 <a href='vbscript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->23 你好 <a href='javascript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->24 你好 ?abc=def&hello=123&world={\"a\":1}我还在。");
|
||||
// xssFilter("<!--HTML-->25 你好 ?abc=def&hello=123&world={'a':1}我还在。");
|
||||
// sqlFilter("1 你好 select * from xxx where abc=def and 1=1我还在。");
|
||||
// sqlFilter("2 你好 insert into xxx values(1,2,3,4,5)我还在。");
|
||||
// sqlFilter("3 你好 delete from xxx我还在。");
|
||||
// sqlFilter("4 a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(111) end then 1 else 1/0 end", "orderBy");
|
||||
// sqlFilter("5 if(1=2,1,SLEEP(10)), if(mid(database(),{},1)=\\\"{}\\\",a.id,a.login_name)", "orderBy");
|
||||
// sqlFilter("6 a.audit_result asc, b.audit_result2 desc, b.AuditResult3 desc", "orderBy");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -4,25 +4,22 @@
|
||||
*/
|
||||
package com.jeesite.common.codec;
|
||||
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* MD5不可逆加密工具类
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public class Md5Utils {
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
* @param input 加密字符串
|
||||
*/
|
||||
public static byte[] md5(byte[] input) {
|
||||
return md5(input, 1);
|
||||
}
|
||||
|
||||
private static final String MD5 = "MD5";
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
* @param input 加密字符串
|
||||
@@ -36,24 +33,36 @@ public class Md5Utils {
|
||||
* @param input 加密字符串
|
||||
* @param iterations 迭代次数
|
||||
*/
|
||||
public static byte[] md5(byte[] input, int iterations) {
|
||||
return DigestUtils.digest(input, DigestUtils.MD5, null, iterations);
|
||||
public static String md5(String input, int iterations) {
|
||||
try {
|
||||
return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(EncodeUtils.UTF_8), MD5, null, iterations));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
* @param input 加密字符串
|
||||
*/
|
||||
public static byte[] md5(byte[] input) {
|
||||
return md5(input, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
* @param input 加密字符串
|
||||
* @param iterations 迭代次数
|
||||
*/
|
||||
public static String md5(String input, int iterations) {
|
||||
return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(StandardCharsets.UTF_8), DigestUtils.MD5, null, iterations));
|
||||
public static byte[] md5(byte[] input, int iterations) {
|
||||
return DigestUtils.digest(input, MD5, null, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行md5散列.
|
||||
*/
|
||||
public static byte[] md5(InputStream input) throws IOException {
|
||||
return DigestUtils.digest(input, DigestUtils.MD5);
|
||||
return DigestUtils.digest(input, MD5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,16 +6,17 @@ package com.jeesite.common.codec;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* SHA-1 加密工具类,散列加密,不可逆加密
|
||||
* SHA-1不可逆加密工具类
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public class Sha1Utils {
|
||||
|
||||
private static final String SHA1 = "SHA-1";
|
||||
|
||||
/**
|
||||
* 生成随机的 Byte[] 作为 salt 密钥.
|
||||
* 生成随机的Byte[]作为salt密钥.
|
||||
* @param numBytes byte数组的大小
|
||||
*/
|
||||
public static byte[] genSalt(int numBytes) {
|
||||
@@ -23,60 +24,31 @@ public class Sha1Utils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机的 Byte[] 作为 salt 密钥,返回 HEX 值
|
||||
* @param numBytes byte 数组的大小
|
||||
*/
|
||||
public static String genSaltString(int numBytes) {
|
||||
return DigestUtils.genSaltString(numBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
* 对输入字符串进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(byte[] input) {
|
||||
return DigestUtils.digest(input, DigestUtils.SHA1, null, 1);
|
||||
return DigestUtils.digest(input, SHA1, null, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
*/
|
||||
public static String sha1(String input) {
|
||||
return EncodeUtils.encodeHex(sha1(input.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
* 对输入字符串进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(byte[] input, byte[] salt) {
|
||||
return DigestUtils.digest(input, DigestUtils.SHA1, salt, 1);
|
||||
return DigestUtils.digest(input, SHA1, salt, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
*/
|
||||
public static String sha1(String data, String salt) {
|
||||
return EncodeUtils.encodeHex(sha1(data.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(salt)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
* 对输入字符串进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
|
||||
return DigestUtils.digest(input, DigestUtils.SHA1, salt, iterations);
|
||||
return DigestUtils.digest(input, SHA1, salt, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行 SHA-1 散列.
|
||||
*/
|
||||
public static String sha1(String input, String salt, int iterations) {
|
||||
return EncodeUtils.encodeHex(sha1(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(salt), iterations));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行 SHA-1 散列.
|
||||
* 对文件进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(InputStream input) throws IOException {
|
||||
return DigestUtils.digest(input, DigestUtils.SHA1);
|
||||
return DigestUtils.digest(input, SHA1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@ package com.jeesite.common.io;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.sf.jmimemagic.Magic;
|
||||
import net.sf.jmimemagic.MagicMatch;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -18,6 +15,9 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
@@ -710,11 +710,11 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
|
||||
end = Long.parseLong(values[1]);
|
||||
}
|
||||
}
|
||||
long requestSize = 0;
|
||||
int requestSize = 0;
|
||||
if (end != 0 && end > start) {
|
||||
requestSize = Long.valueOf(end - start + 1).intValue();
|
||||
} else {
|
||||
requestSize = Long.MAX_VALUE;
|
||||
requestSize = Integer.MAX_VALUE;
|
||||
}
|
||||
response.setContentType(FileUtils.getContentType(file.getName()));
|
||||
boolean isPreview = "preview".equalsIgnoreCase(request.getParameter("source"));
|
||||
@@ -748,12 +748,12 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
|
||||
}
|
||||
}
|
||||
randomFile.seek(start);
|
||||
long needSize = requestSize;
|
||||
int needSize = requestSize;
|
||||
while (needSize > 0) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len = randomFile.read(buffer);
|
||||
if (needSize < buffer.length) {
|
||||
out.write(buffer, 0, (int)needSize);
|
||||
out.write(buffer, 0, needSize);
|
||||
} else {
|
||||
out.write(buffer, 0, len);
|
||||
if (len < buffer.length) {
|
||||
|
||||
@@ -36,10 +36,12 @@ public class PropertiesUtils {
|
||||
// 默认加载的文件,可通过继承覆盖(若有相同Key,优先加载后面的)
|
||||
public static final String[] DEFAULT_CONFIG_FILE = new String[]{
|
||||
"classpath:application.yml", "classpath:config/application.yml",
|
||||
"classpath:bootstrap.yml", "classpath:config/bootstrap.yml",
|
||||
"file:application.yml", "file:config/application.yml",
|
||||
"file:bootstrap.yml", "file:config/bootstrap.yml",
|
||||
};
|
||||
|
||||
private static final Logger logger = PropertiesUtils.initLogger();
|
||||
private static Logger logger = PropertiesUtils.initLogger();
|
||||
private final Set<String> configSet = SetUtils.newLinkedHashSet();
|
||||
private final Properties properties = new Properties();
|
||||
private static Environment environment;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
package com.jeesite.common.lang;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@@ -28,8 +28,6 @@ public class ExceptionUtils {
|
||||
ex = (Throwable) request.getAttribute("exception");
|
||||
} else if (request.getAttribute(RequestDispatcher.ERROR_EXCEPTION) != null) {
|
||||
ex = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
|
||||
} else if (request.getAttribute("org.springframework.web.servlet.DispatcherServlet.EXCEPTION") != null) {
|
||||
ex = (Throwable) request.getAttribute("org.springframework.web.servlet.DispatcherServlet.EXCEPTION");
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
*/
|
||||
package com.jeesite.common.lang;
|
||||
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.fury.Fury;
|
||||
import org.apache.fury.ThreadSafeFury;
|
||||
import org.apache.fury.config.Language;
|
||||
import org.nustaq.serialization.FSTConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -26,25 +24,14 @@ import java.lang.reflect.InvocationTargetException;
|
||||
*/
|
||||
public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ObjectUtils.class);
|
||||
|
||||
/**
|
||||
* 当前类的实例持有者(静态内部类,延迟加载,懒汉式,线程安全的单例模式)
|
||||
*/
|
||||
private static final class Static {
|
||||
private static final Boolean isJavaSerialize;
|
||||
private static final ThreadSafeFury fury;
|
||||
static {
|
||||
isJavaSerialize = PropertiesUtils.getInstance()
|
||||
.getPropertyToBoolean("isJavaSerialize", "false");
|
||||
org.apache.fury.logging.LoggerFactory.useSlf4jLogging(true);
|
||||
fury = Fury.builder().withLanguage(Language.JAVA)
|
||||
.withRefTracking(true)
|
||||
.requireClassRegistration(false)
|
||||
.buildThreadSafeFury();
|
||||
}
|
||||
private static Logger logger = LoggerFactory.getLogger(ObjectUtils.class);
|
||||
private static final boolean isJavaSerialize;
|
||||
|
||||
static {
|
||||
String[] ver = StringUtils.split(System.getProperty("java.version"), StringUtils.DOT);
|
||||
isJavaSerialize = ver.length > 0 && Integer.parseInt(ver[0]) > 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为 Double 类型
|
||||
*/
|
||||
@@ -135,7 +122,7 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
*/
|
||||
public static String toStringIgnoreNull(final Object val, String defaultVal) {
|
||||
String str = ObjectUtils.toString(val);
|
||||
return !"".equals(str) && !"null".equalsIgnoreCase(str.trim()) ? str : defaultVal;
|
||||
return !"".equals(str) && !"null".equals(str.trim().toLowerCase()) ? str : defaultVal;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,7 +153,8 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = ObjectUtils.serialize(source);
|
||||
return ObjectUtils.unserialize(bytes);
|
||||
Object target = ObjectUtils.unserialize(bytes);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,10 +164,10 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
*/
|
||||
public static byte[] serialize(Object object) {
|
||||
try {
|
||||
if (Static.isJavaSerialize) {
|
||||
if (isJavaSerialize) {
|
||||
return ObjectUtils.serializeJava(object);
|
||||
} else {
|
||||
return ObjectUtils.serializeFury(object);
|
||||
}else {
|
||||
return ObjectUtils.serializeFst(object);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("serialize: {}", e.getMessage());
|
||||
@@ -194,10 +182,10 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
*/
|
||||
public static Object unserialize(byte[] bytes) {
|
||||
try {
|
||||
if (Static.isJavaSerialize) {
|
||||
if (isJavaSerialize) {
|
||||
return ObjectUtils.unserializeJava(bytes);
|
||||
} else {
|
||||
return ObjectUtils.unserializeFury(bytes);
|
||||
}else {
|
||||
return ObjectUtils.unserializeFst(bytes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("unserialize: {}", e.getMessage());
|
||||
@@ -255,88 +243,51 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
private static ThreadLocal<FSTConfiguration> fstConfiguration =
|
||||
new NamedThreadLocal<FSTConfiguration>("FSTConfiguration") {
|
||||
@Override
|
||||
public FSTConfiguration initialValue() {
|
||||
return FSTConfiguration.createDefaultConfiguration();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
* FST 序列化对象
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public static byte[] serializeFury(Object object) {
|
||||
public static byte[] serializeFst(Object object) {
|
||||
if (object == null){
|
||||
return null;
|
||||
}
|
||||
long beginTime = System.currentTimeMillis();
|
||||
byte[] bytes = Static.fury.serialize(object);
|
||||
byte[] bytes = fstConfiguration.get().asByteArray(object);
|
||||
long totalTime = System.currentTimeMillis() - beginTime;
|
||||
if (totalTime > 30000){
|
||||
logger.warn(object.getClass() + " serialize time: " + TimeUtils.formatTime(totalTime));
|
||||
logger.warn(object.getClass() + " fst serialize time: " + TimeUtils.formatTime(totalTime));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化对象
|
||||
* FST 反序列化对象
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static Object unserializeFury(byte[] bytes) {
|
||||
public static Object unserializeFst(byte[] bytes) {
|
||||
if (bytes == null){
|
||||
return null;
|
||||
}
|
||||
long beginTime = System.currentTimeMillis();
|
||||
Object object = Static.fury.deserialize(bytes);
|
||||
Object object = fstConfiguration.get().asObject(bytes);
|
||||
long totalTime = System.currentTimeMillis() - beginTime;
|
||||
if (totalTime > 30000 && object != null){
|
||||
logger.warn(object.getClass() + " unserialize time: " + TimeUtils.formatTime(totalTime));
|
||||
logger.warn(object.getClass() + " fst unserialize time: " + TimeUtils.formatTime(totalTime));
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
// private static ThreadLocal<FSTConfiguration> fstConfiguration =
|
||||
// new NamedThreadLocal<FSTConfiguration>("FSTConfiguration") {
|
||||
// @Override
|
||||
// public FSTConfiguration initialValue() {
|
||||
// return FSTConfiguration.createDefaultConfiguration();
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * FST 序列化对象
|
||||
// * @param object
|
||||
// * @return
|
||||
// */
|
||||
// public static byte[] serializeFst(Object object) {
|
||||
// if (object == null){
|
||||
// return null;
|
||||
// }
|
||||
// long beginTime = System.currentTimeMillis();
|
||||
// byte[] bytes = fstConfiguration.get().asByteArray(object);
|
||||
// long totalTime = System.currentTimeMillis() - beginTime;
|
||||
// if (totalTime > 30000){
|
||||
// logger.warn(object.getClass() + " fst serialize time: " + TimeUtils.formatTime(totalTime));
|
||||
// }
|
||||
// return bytes;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * FST 反序列化对象
|
||||
// * @param bytes
|
||||
// * @return
|
||||
// */
|
||||
// public static Object unserializeFst(byte[] bytes) {
|
||||
// if (bytes == null){
|
||||
// return null;
|
||||
// }
|
||||
// long beginTime = System.currentTimeMillis();
|
||||
// Object object = fstConfiguration.get().asObject(bytes);
|
||||
// long totalTime = System.currentTimeMillis() - beginTime;
|
||||
// if (totalTime > 30000 && object != null){
|
||||
// logger.warn(object.getClass() + " fst unserialize time: " + TimeUtils.formatTime(totalTime));
|
||||
// }
|
||||
// return object;
|
||||
// }
|
||||
|
||||
// private static Pool<Kryo> kryoPool = new Pool<Kryo>(true, false, 8) {
|
||||
// protected Kryo create() {
|
||||
// Kryo kryo = new Kryo();
|
||||
|
||||
@@ -26,7 +26,6 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
public static final String COLON = ":";
|
||||
public static final String TILDE = "~";
|
||||
public static final String UNDERLINE = "_";
|
||||
public static final String MINUS = "-";
|
||||
|
||||
/**
|
||||
* 分隔字符串(逗号分隔)
|
||||
@@ -285,7 +284,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == UNDERLINE.charAt(0) || c == MINUS.charAt(0)) {
|
||||
if (c == UNDERLINE.charAt(0)) {
|
||||
upperCase = i != 1; // 不允许第二个字符是大写
|
||||
} else if (upperCase) {
|
||||
sb.append(Character.toUpperCase(c));
|
||||
|
||||
@@ -50,7 +50,7 @@ public class JsonMapper extends ObjectMapper {
|
||||
private static final class JsonMapperHolder {
|
||||
private static final JsonMapper INSTANCE = new JsonMapper();
|
||||
}
|
||||
|
||||
|
||||
public JsonMapper() {
|
||||
// Spring ObjectMapper 初始化配置,支持 @JsonView
|
||||
new Jackson2ObjectMapperBuilder().configure(this);
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.jeesite.common.io.PropertiesUtils;
|
||||
*/
|
||||
public class EmailUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EmailUtils.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(EmailUtils.class);
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class SmsUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SmsUtils.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(SmsUtils.class);
|
||||
|
||||
/**
|
||||
* 模拟发送短信
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class IpUtils {
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ public class ReflectUtils {
|
||||
//Method method = getAccessibleMethodByName(object, methodName, 0);
|
||||
//if (method == null) { return; }
|
||||
//Class<?> returnType = method.getReturnType();
|
||||
System.out.println(object.getClass());
|
||||
MethodAccess ma = MethodAccess.get(object.getClass());
|
||||
Class<?> returnType = ma.getReturnTypes()[ma.getIndex(methodName)];
|
||||
childObj = returnType.getDeclaredConstructor().newInstance();
|
||||
|
||||
@@ -47,9 +47,6 @@ public abstract class MethodAccess {
|
||||
|
||||
/** Returns the index of the first method with the specified name. */
|
||||
public int getIndex (String methodName) {
|
||||
// 先查找无参数的方法,再查找有参数的方法,当未传递参数类型的时候,这是一个降级策略
|
||||
for (int i = 0, n = methodNames.length; i < n; i++)
|
||||
if (methodNames[i].equals(methodName) && parameterTypes[i].length == 0) return i;
|
||||
for (int i = 0, n = methodNames.length; i < n; i++)
|
||||
if (methodNames[i].equals(methodName)) return i;
|
||||
throw new IllegalArgumentException("Unable to find non-private method: " + methodName);
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -39,12 +39,12 @@ import java.util.*;
|
||||
*/
|
||||
public class ExcelExport implements Closeable{
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExcelExport.class);
|
||||
private static Logger log = LoggerFactory.getLogger(ExcelExport.class);
|
||||
|
||||
/**
|
||||
* 工作薄对象
|
||||
*/
|
||||
private final Workbook wb;
|
||||
private Workbook wb;
|
||||
|
||||
/**
|
||||
* 工作表对象
|
||||
@@ -59,7 +59,7 @@ public class ExcelExport implements Closeable{
|
||||
/**
|
||||
* 当前行号
|
||||
*/
|
||||
private int rowNum;
|
||||
private int rownum;
|
||||
|
||||
/**
|
||||
* 注解列表(Object[]{ ExcelField, Field/Method })
|
||||
@@ -69,7 +69,7 @@ public class ExcelExport implements Closeable{
|
||||
/**
|
||||
* 存储字段类型临时数据
|
||||
*/
|
||||
private final Map<Class<? extends FieldType>, FieldType> fieldTypes = MapUtils.newHashMap();
|
||||
private Map<Class<? extends FieldType>, FieldType> fieldTypes = MapUtils.newHashMap();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static Class dictUtilsClass = null;
|
||||
@@ -158,16 +158,6 @@ public class ExcelExport implements Closeable{
|
||||
}
|
||||
this.createSheet(sheetName, title, headerList, headerWidthList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public ExcelExport(ExcelImport excelImport) {
|
||||
this.wb = excelImport.getWorkbook();
|
||||
this.styles = createStyles(wb);
|
||||
this.sheet = excelImport.getSheet();
|
||||
this.rowNum = excelImport.getHeaderNum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个工作簿
|
||||
@@ -194,13 +184,6 @@ public class ExcelExport implements Closeable{
|
||||
*/
|
||||
public void createSheet(String sheetName, String title, Class<?> cls, Type type, String... groups){
|
||||
this.annotationList = ListUtils.newArrayList();
|
||||
// Get class annotation
|
||||
ExcelFields cfs = cls.getAnnotation(ExcelFields.class);
|
||||
if (cfs != null && cfs.value() != null){
|
||||
for (ExcelField ef : cfs.value()){
|
||||
addAnnotation(annotationList, ef, cfs, type, groups);
|
||||
}
|
||||
}
|
||||
// Get constructor annotation
|
||||
Constructor<?>[] cs = cls.getConstructors();
|
||||
for (Constructor<?> c : cs) {
|
||||
@@ -303,12 +286,12 @@ public class ExcelExport implements Closeable{
|
||||
* @param headerWidthList 表头字段宽度设置
|
||||
*/
|
||||
public void createSheet(String sheetName, String title, List<String> headerList, List<Integer> headerWidthList) {
|
||||
this.sheet = wb.createSheet(StringUtils.defaultIfBlank(sheetName, StringUtils.defaultIfBlank(title, "Sheet1")));
|
||||
this.sheet = wb.createSheet(StringUtils.defaultString(sheetName, StringUtils.defaultString(title, "Sheet1")));
|
||||
this.styles = createStyles(wb);
|
||||
this.rowNum = 0;
|
||||
this.rownum = 0;
|
||||
// Create title
|
||||
if (StringUtils.isNotBlank(title)){
|
||||
Row titleRow = sheet.createRow(rowNum++);
|
||||
Row titleRow = sheet.createRow(rownum++);
|
||||
titleRow.setHeightInPoints(30);
|
||||
Cell titleCell = titleRow.createCell(0);
|
||||
titleCell.setCellStyle(styles.get("title"));
|
||||
@@ -320,7 +303,7 @@ public class ExcelExport implements Closeable{
|
||||
if (headerList == null){
|
||||
throw new ExcelException("headerList not null!");
|
||||
}
|
||||
Row headerRow = sheet.createRow(rowNum++);
|
||||
Row headerRow = sheet.createRow(rownum++);
|
||||
headerRow.setHeightInPoints(16);
|
||||
for (int i = 0; i < headerList.size(); i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
@@ -429,7 +412,7 @@ public class ExcelExport implements Closeable{
|
||||
* @return 行对象
|
||||
*/
|
||||
public Row addRow(){
|
||||
return sheet.createRow(rowNum++);
|
||||
return sheet.createRow(rownum++);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -650,5 +633,54 @@ public class ExcelExport implements Closeable{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 导出测试
|
||||
// */
|
||||
// public static void main(String[] args) throws Throwable {
|
||||
//
|
||||
// // 初始化表头
|
||||
// List<String> headerList = ListUtils.newArrayList();
|
||||
// for (int i = 1; i <= 10; i++) {
|
||||
// headerList.add("表头"+i);
|
||||
// }
|
||||
//
|
||||
// // 初始化数据集
|
||||
// List<String> rowList = ListUtils.newArrayList();
|
||||
// for (int i = 1; i <= headerList.size(); i++) {
|
||||
// rowList.add("数据"+i);
|
||||
// }
|
||||
// List<List<String>> dataList = ListUtils.newArrayList();
|
||||
// for (int i = 1; i <=100; i++) {
|
||||
// dataList.add(rowList);
|
||||
// }
|
||||
//
|
||||
// // 创建一个Sheet表,并导入数据
|
||||
// try(ExcelExport ee = new ExcelExport("表格1", "表格标题1", headerList, null)){
|
||||
//
|
||||
// for (int i = 0; i < dataList.size(); i++) {
|
||||
// Row row = ee.addRow();
|
||||
// for (int j = 0; j < dataList.get(i).size(); j++) {
|
||||
// ee.addCell(row, j, dataList.get(i).get(j));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 再创建一个Sheet表,并导入数据
|
||||
// ee.createSheet("表格2", "表格标题2", headerList, null);
|
||||
// for (int i = 0; i < dataList.size(); i++) {
|
||||
// Row row = ee.addRow();
|
||||
// for (int j = 0; j < dataList.get(i).size(); j++) {
|
||||
// ee.addCell(row, j, dataList.get(i).get(j)+"2");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 输出到文件
|
||||
// ee.writeFile("target/export.xlsx");
|
||||
//
|
||||
// }
|
||||
//
|
||||
// log.debug("Export success.");
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ import java.util.*;
|
||||
*/
|
||||
public class ExcelImport implements Closeable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExcelImport.class);
|
||||
private static Logger log = LoggerFactory.getLogger(ExcelImport.class);
|
||||
|
||||
/**
|
||||
* 工作薄对象
|
||||
*/
|
||||
private final Workbook wb;
|
||||
private Workbook wb;
|
||||
|
||||
/**
|
||||
* 工作表对象
|
||||
@@ -61,39 +61,20 @@ public class ExcelImport implements Closeable {
|
||||
/**
|
||||
* 存储字段类型临时数据
|
||||
*/
|
||||
private final Map<Class<? extends FieldType>, FieldType> fieldTypes = MapUtils.newHashMap();
|
||||
private Map<Class<? extends FieldType>, FieldType> fieldTypes = MapUtils.newHashMap();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static Class dictUtilsClass = null;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param fileName 导入文件对象,读取第一个工作表
|
||||
* @throws InvalidFormatException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ExcelImport(String fileName) throws InvalidFormatException, IOException {
|
||||
this(new File(fileName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param file 导入文件对象,读取第一个工作表
|
||||
* @param path 导入文件对象,读取第一个工作表
|
||||
* @throws InvalidFormatException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ExcelImport(File file) throws InvalidFormatException, IOException {
|
||||
this(file, 0, 0);
|
||||
}
|
||||
/**
|
||||
* 构造函数
|
||||
* @param fileName 导入文件对象,读取第一个工作表
|
||||
* @throws InvalidFormatException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ExcelImport(String fileName, int headerNum) throws InvalidFormatException, IOException {
|
||||
this(new File(fileName), headerNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -107,19 +88,6 @@ public class ExcelImport implements Closeable {
|
||||
this(file, headerNum, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param fileName 导入文件对象
|
||||
* @param headerNum 标题行数,数据行号=标题行数+1
|
||||
* @param sheetIndexOrName 工作表编号或名称,从0开始
|
||||
* @throws InvalidFormatException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ExcelImport(String fileName, int headerNum, Object sheetIndexOrName)
|
||||
throws InvalidFormatException, IOException {
|
||||
this(new File(fileName), headerNum, sheetIndexOrName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param file 导入文件对象
|
||||
@@ -202,21 +170,7 @@ public class ExcelImport implements Closeable {
|
||||
public Workbook getWorkbook() {
|
||||
return wb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前工作表
|
||||
*/
|
||||
public Sheet getSheet() {
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前标题行数
|
||||
*/
|
||||
public int getHeaderNum() {
|
||||
return headerNum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置当前工作表和标题行数
|
||||
* @author ThinkGem
|
||||
@@ -385,13 +339,6 @@ public class ExcelImport implements Closeable {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E> List<E> getDataList(Class<E> cls, MethodCallback exceptionCallback, String... groups) throws Exception{
|
||||
List<Object[]> annotationList = ListUtils.newArrayList();
|
||||
// Get class annotation
|
||||
ExcelFields cfs = cls.getAnnotation(ExcelFields.class);
|
||||
if (cfs != null && cfs.value() != null){
|
||||
for (ExcelField ef : cfs.value()){
|
||||
addAnnotation(annotationList, ef, cls, Type.IMPORT, groups);
|
||||
}
|
||||
}
|
||||
// Get constructor annotation
|
||||
Constructor<?>[] cs = cls.getConstructors();
|
||||
for (Constructor<?> c : cs) {
|
||||
@@ -581,4 +528,25 @@ public class ExcelImport implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 导入测试
|
||||
// */
|
||||
// public static void main(String[] args) throws Throwable {
|
||||
//
|
||||
// ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
|
||||
//
|
||||
// for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
|
||||
// Row row = ei.getRow(i);
|
||||
// if (row == null){
|
||||
// continue;
|
||||
// }
|
||||
// for (int j = 0; j < ei.getLastCellNum(); j++) {
|
||||
// Object val = ei.getCellValue(row, j);
|
||||
// System.out.print(val+", ");
|
||||
// }
|
||||
// System.out.println();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.common.utils.excel.fieldtype;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
|
||||
/**
|
||||
* BigDecimal类型转换
|
||||
* @author ThinkGem
|
||||
* @version 2020-3-5
|
||||
* @example fieldType = BigDecimalType.class
|
||||
*/
|
||||
public class BigDecimalType implements FieldType {
|
||||
|
||||
/**
|
||||
* 获取对象值(导入)
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(String val) {
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象值(导出)
|
||||
*/
|
||||
@Override
|
||||
public String setValue(Object val) {
|
||||
return val == null ? StringUtils.EMPTY : val.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象值格式(导出)
|
||||
*/
|
||||
@Override
|
||||
public String getDataFormat() {
|
||||
return "0.00";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,9 +7,10 @@ package com.jeesite.common.web;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Cookie工具类
|
||||
@@ -95,8 +96,7 @@ public class CookieUtils {
|
||||
* @return 值
|
||||
*/
|
||||
public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) {
|
||||
String ctxPath = PropertiesUtils.getInstance().getProperty("ctxPath", request != null ? request.getContextPath() : StringUtils.EMPTY);
|
||||
return getCookie(request, response, name, ctxPath, isRemove);
|
||||
return getCookie(request, response, name, request != null ? request.getContextPath() : "", false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +116,6 @@ public class CookieUtils {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals(name)) {
|
||||
value = EncodeUtils.decodeUrl(cookie.getValue());
|
||||
value = EncodeUtils.xssFilter(value, request);
|
||||
if (isRemove && response != null) {
|
||||
cookie.setPath(path);
|
||||
cookie.setMaxAge(0);
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.common.web.http;
|
||||
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 统一包装结果输出类:{ code: 200, msg: "", data: {} | [] }
|
||||
* @author ThinkGem
|
||||
* @version 2024-07-24
|
||||
*/
|
||||
public class ResultUtils {
|
||||
|
||||
private static final boolean isDefaultResult = PropertiesUtils.getInstance()
|
||||
.getPropertyToBoolean("web.isDefaultResult", "false");
|
||||
private static final String resultParamName = PropertiesUtils.getInstance()
|
||||
.getProperty("web.resultParamName", "__data");
|
||||
private static final String headerParamName = PropertiesUtils.getInstance()
|
||||
.getProperty("web.headerParamName", "x-data");
|
||||
|
||||
/**
|
||||
* 设置 web.isResult 参数可强制全局使用统一结果输出,否则,传递 __data=true 参数,或 x-data 请求头为 true 时启用
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static Object result(Object data, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (request != null && response != null && (isDefaultResult || (
|
||||
"true".equals(request.getParameter(resultParamName))
|
||||
|| "true".equals(request.getHeader(headerParamName))))) {
|
||||
Object msg = request.getAttribute("message");
|
||||
return new Result(response.getStatus(), msg, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 结果对象
|
||||
* @author ThinkGem
|
||||
* @version 2024-07-24
|
||||
*/
|
||||
private static class Result {
|
||||
private int code;
|
||||
private String msg;
|
||||
private Object data;
|
||||
|
||||
public Result(int code, Object msg, Object data) {
|
||||
this.code = code;
|
||||
this.msg = msg != null ? msg.toString() : null;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,15 +12,14 @@ import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.mapper.JsonMapper;
|
||||
import com.jeesite.common.mapper.XmlMapper;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
@@ -57,12 +56,7 @@ public class ServletUtils {
|
||||
|
||||
// 是否打印错误信息参数到视图页面(生产环境关闭)
|
||||
private static final Boolean PRINT_ERROR_INFO = PROPS.getPropertyToBoolean("error.page.printErrorInfo", "true");
|
||||
|
||||
// 允许重定向的地址,不设置为全部允许,设置this只允许本项目内部跳转,多个用逗号隔开,例如:this,http://*.jeesite.com
|
||||
private static final String[] ALLOW_REDIRECTS = PROPS.getPropertyToArray("shiro.allowRedirects", "");
|
||||
private static final Boolean SCHEME_HTTPS = PROPS.getPropertyToBoolean("server.schemeHttps", "false");
|
||||
private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前请求对象
|
||||
* web.xml: <listener><listener-class>
|
||||
@@ -70,8 +64,13 @@ public class ServletUtils {
|
||||
* </listener-class></listener>
|
||||
*/
|
||||
public static HttpServletRequest getRequest(){
|
||||
HttpServletRequest request = null;
|
||||
try{
|
||||
return ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||
request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||
if (request == null){
|
||||
return null;
|
||||
}
|
||||
return request;
|
||||
}catch(Exception e){
|
||||
return null;
|
||||
}
|
||||
@@ -84,11 +83,16 @@ public class ServletUtils {
|
||||
* <filter-name>requestContextFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
|
||||
*/
|
||||
public static HttpServletResponse getResponse(){
|
||||
HttpServletResponse response = null;
|
||||
try{
|
||||
return ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getResponse();
|
||||
response = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getResponse();
|
||||
if (response == null){
|
||||
return null;
|
||||
}
|
||||
}catch(Exception e){
|
||||
return null;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,8 +106,7 @@ public class ServletUtils {
|
||||
if (StringUtils.contains(url, "://")){
|
||||
response.sendRedirect(url);
|
||||
}else{
|
||||
String ctxPath = PropertiesUtils.getInstance().getProperty("ctxPath", request.getContextPath());
|
||||
response.sendRedirect(ctxPath + url);
|
||||
response.sendRedirect(request.getContextPath() + url);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -118,8 +121,9 @@ public class ServletUtils {
|
||||
public static boolean isStaticFile(String uri){
|
||||
if (STATIC_FILE == null){
|
||||
try {
|
||||
throw new Exception("检测到“application.yml”中没有配置“web.staticFile”属性。配置示例:\n#静态文件后缀\nweb.staticFile=" +
|
||||
".css,.js,.map,.png,.jpg,.gif,.jpeg,.webp,.bmp,.ico,.swf,.psd,.htc,.crx,.xpi,.exe,.ipa,.apk,.otf,.eot,.svg,.ttf,.woff,.woff2");
|
||||
throw new Exception("检测到“application.yml”中没有配置“web.staticFile”属性。"
|
||||
+ "配置示例:\n#静态文件后缀\nweb.staticFile=.css,.js,.png,.jpg,.gif,"
|
||||
+ ".jpeg,.bmp,.ico,.swf,.psd,.htc,.crx,.xpi,.exe,.ipa,.apk");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -253,7 +257,6 @@ public class ServletUtils {
|
||||
if (object == null) {
|
||||
object = resultMap;
|
||||
}
|
||||
object = ResultUtils.result(object, request, response);
|
||||
if (jsonView != null) {
|
||||
return JsonMapper.toJson(object, jsonView);
|
||||
}else {
|
||||
@@ -327,7 +330,6 @@ public class ServletUtils {
|
||||
object = new JSONPObject(functionName, object);
|
||||
}
|
||||
}
|
||||
object = ResultUtils.result(object, request, response);
|
||||
if (jsonView != null) {
|
||||
return renderString(response, JsonMapper.toJson(object, jsonView));
|
||||
}else {
|
||||
@@ -355,7 +357,18 @@ public class ServletUtils {
|
||||
try {
|
||||
// response.reset(); // 注释掉,否则以前设置的Header会被清理掉,如ajax登录设置记住我的Cookie信息
|
||||
if (type == null && StringUtils.isBlank(response.getContentType())){
|
||||
type = getContentType(string);
|
||||
if ((StringUtils.startsWith(string, "{") && StringUtils.endsWith(string, "}"))
|
||||
|| (StringUtils.startsWith(string, "[") && StringUtils.endsWith(string, "]"))){
|
||||
type = MediaType.APPLICATION_JSON_VALUE;
|
||||
}else if (StringUtils.startsWith(string, "<") && StringUtils.endsWith(string, ">")){
|
||||
if (StringUtils.startsWith(string, "<!DOCTYPE")){
|
||||
type = MediaType.TEXT_HTML_VALUE;
|
||||
}else{
|
||||
type = MediaType.APPLICATION_XML_VALUE;
|
||||
}
|
||||
}else{
|
||||
type = MediaType.TEXT_PLAIN_VALUE;
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
response.setContentType(type);
|
||||
@@ -369,36 +382,10 @@ public class ServletUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据内容判断相应类型 MediaType
|
||||
* @return application/json、text/html、application/xml、text/plain
|
||||
* 获取请求的域名(含端口)
|
||||
*/
|
||||
public static String getContentType(String string) {
|
||||
String type;
|
||||
if ((StringUtils.startsWith(string, "{") && StringUtils.endsWith(string, "}"))
|
||||
|| (StringUtils.startsWith(string, "[") && StringUtils.endsWith(string, "]"))){
|
||||
type = MediaType.APPLICATION_JSON_VALUE;
|
||||
}else if (StringUtils.startsWith(string, "<") && StringUtils.endsWith(string, ">")){
|
||||
if (StringUtils.startsWith(string, "<!DOCTYPE")){
|
||||
type = MediaType.TEXT_HTML_VALUE;
|
||||
}else{
|
||||
type = MediaType.APPLICATION_XML_VALUE;
|
||||
}
|
||||
}else{
|
||||
type = MediaType.TEXT_PLAIN_VALUE;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前请求的域名(含端口)
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String getThisDomain(HttpServletRequest request) {
|
||||
String url = request.getRequestURL().toString();
|
||||
public static String getRequestDomain(String url) {
|
||||
String scheme = StringUtils.substringBefore(url, "://");
|
||||
if (SCHEME_HTTPS && StringUtils.equals(scheme, "http")) {
|
||||
scheme = "https";
|
||||
}
|
||||
String domain = StringUtils.substringAfter(url, "://");
|
||||
if (StringUtils.contains(domain, "/")) {
|
||||
domain = StringUtils.substringBefore(domain, "/");
|
||||
@@ -406,28 +393,6 @@ public class ServletUtils {
|
||||
return scheme + "://" + domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证地址是否允许重定向
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static boolean isAllowRedirects(HttpServletRequest request, String url) {
|
||||
if (ALLOW_REDIRECTS == null || ALLOW_REDIRECTS.length == 0) {
|
||||
return true;
|
||||
}
|
||||
boolean allow = false;
|
||||
for (String pattern : ALLOW_REDIRECTS) {
|
||||
String p = StringUtils.trim(pattern);
|
||||
if ("this".equals(p)) {
|
||||
p = getThisDomain(request);
|
||||
}
|
||||
if (PATH_MATCHER.match(p + "/**", url)){
|
||||
allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得请求参数值
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package com.jeesite.common.web.http;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import eu.bitwalker.useragentutils.Browser;
|
||||
import eu.bitwalker.useragentutils.DeviceType;
|
||||
|
||||
@@ -235,6 +235,3 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
|
||||
.ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:46px!important;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th div {padding:15px 0 15px 2px;}
|
||||
.ui-jqgrid tr.jqgrow td {height: 49px;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:36px!important;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-htable th div {padding:9px 0 8px 2px;}
|
||||
.table-form .ui-jqgrid tr.jqgrow td {height: 39px;}
|
||||
|
||||
@@ -235,6 +235,3 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
|
||||
.ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:46px!important;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th div {padding:15px 0 15px 2px;}
|
||||
.ui-jqgrid tr.jqgrow td {height: 49px;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:36px!important;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-htable th div {padding:9px 0 8px 2px;}
|
||||
.table-form .ui-jqgrid tr.jqgrow td {height: 39px;}
|
||||
|
||||
@@ -296,9 +296,6 @@ a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sor
|
||||
.ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:46px!important;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th div {padding:15px 0 15px 2px;}
|
||||
.ui-jqgrid tr.jqgrow td {height: 49px;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-frozen .ui-jqgrid-htable th div {height:36px!important;}
|
||||
.table-form .ui-jqgrid .ui-jqgrid-htable th div {padding:9px 0 8px 2px;}
|
||||
.table-form .ui-jqgrid tr.jqgrow td {height: 39px;}
|
||||
|
||||
.ui-jqgrid tr.jqgroup td, .ui-jqgrid tr.footrow td, .ui-jqgrid tr.jqfoot td {background:#323232;}
|
||||
.ui-jqgrid .actions .moreItems {background:#1a1a1a;border-color:#3c3c3c;box-shadow:none;}
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Default Layout Theme
|
||||
* Created for jquery.layout
|
||||
* Copyright (c) 2010
|
||||
* Fabrizio Balliano (http://www.fabrizioballiano.net)
|
||||
* Kevin Dalman (http://allpro.net)
|
||||
* Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
|
||||
* and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
|
||||
* Last Updated: 2010-02-10、2022-09-27 jeesite
|
||||
* NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
|
||||
*/
|
||||
.ui-draggable-handle{-ms-touch-action:none;touch-action:none}
|
||||
|
||||
/*
|
||||
* DEFAULT FONT
|
||||
* Just to make demo-pages look better - not actually relevant to Layout!
|
||||
*/
|
||||
/* body { */
|
||||
/* font-family: Geneva, Arial, Helvetica, sans-serif; */
|
||||
/* font-size: 100%; */
|
||||
/* *font-size: 80%; */
|
||||
/* } */
|
||||
|
||||
/*
|
||||
* PANES & CONTENT-DIVs
|
||||
*/
|
||||
.ui-layout-pane { /* all 'panes' */
|
||||
/* background: #fff; */
|
||||
/* border: 1px solid #eee; */
|
||||
/* padding: 10px; */
|
||||
overflow: auto;
|
||||
/* DO NOT add scrolling (or padding) to 'panes' that have a content-div,
|
||||
otherwise you may get double-scrollbars - on the pane AND on the content-div
|
||||
- use ui-layout-wrapper class if pane has a content-div
|
||||
- use ui-layout-container if pane has an inner-layout
|
||||
*/
|
||||
}
|
||||
/* (scrolling) content-div inside pane allows for fixed header(s) and/or footer(s) */
|
||||
.ui-layout-content {
|
||||
padding: 10px;
|
||||
position: relative; /* contain floated or positioned elements */
|
||||
overflow: auto; /* add scrolling to content-div */
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* UTILITY CLASSES
|
||||
* Must come AFTER pane-class above so will override
|
||||
* These classes are NOT auto-generated and are NOT used by Layout
|
||||
*/
|
||||
.layout-child-container,
|
||||
.layout-content-container {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.layout-child-container {
|
||||
border: 0; /* remove border because inner-layout-panes probably have borders */
|
||||
}
|
||||
.layout-scroll {
|
||||
overflow: auto;
|
||||
}
|
||||
.layout-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* RESIZER-BARS
|
||||
*/
|
||||
.ui-layout-resizer { /* all 'resizer-bars' */
|
||||
background: #fafafa;
|
||||
border: 1px solid #eee;
|
||||
border-width: 0;
|
||||
}
|
||||
.ui-layout-resizer-drag { /* REAL resizer while resize in progress */
|
||||
}
|
||||
.ui-layout-resizer-hover { /* affects both open and closed states */
|
||||
}
|
||||
/* NOTE: It looks best when 'hover' and 'dragging' are set to the same color,
|
||||
otherwise color shifts while dragging when bar can't keep up with mouse */
|
||||
.ui-layout-resizer-open-hover , /* hover-color to 'resize' */
|
||||
.ui-layout-resizer-dragging { /* resizer beging 'dragging' */
|
||||
background: #fafafa;
|
||||
}
|
||||
.ui-layout-resizer-dragging { /* CLONED resizer being dragged */
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
.ui-layout-resizer-north-dragging,
|
||||
.ui-layout-resizer-south-dragging {
|
||||
border-width: 1px 0;
|
||||
}
|
||||
.ui-layout-resizer-west-dragging,
|
||||
.ui-layout-resizer-east-dragging {
|
||||
border-width: 0 1px;
|
||||
}
|
||||
/* NOTE: Add a 'dragging-limit' color to provide visual feedback when resizer hits min/max size limits */
|
||||
.ui-layout-resizer-dragging-limit { /* CLONED resizer at min or max size-limit */
|
||||
background: #E1A4A4; /* red */
|
||||
}
|
||||
|
||||
.ui-layout-resizer-closed-hover { /* hover-color to 'slide open' */
|
||||
background: #EBD5AA;
|
||||
}
|
||||
.ui-layout-resizer-sliding { /* resizer when pane is 'slid open' */
|
||||
/* opacity: .10; show only a slight shadow */
|
||||
/* filter: alpha(opacity=10); */
|
||||
}
|
||||
.ui-layout-resizer-sliding-hover { /* sliding resizer - hover */
|
||||
/* opacity: 1.00; on-hover, show the resizer-bar normally */
|
||||
/* filter: alpha(opacity=100); */
|
||||
}
|
||||
/* sliding resizer - add 'outside-border' to resizer on-hover
|
||||
* this sample illustrates how to target specific panes and states */
|
||||
.ui-layout-resizer-north-sliding-hover { border-bottom-width: 1px; }
|
||||
.ui-layout-resizer-south-sliding-hover { border-top-width: 1px; }
|
||||
.ui-layout-resizer-west-sliding-hover { border-right-width: 1px; }
|
||||
.ui-layout-resizer-east-sliding-hover { border-left-width: 1px; }
|
||||
|
||||
/*
|
||||
* TOGGLER-BUTTONS
|
||||
*/
|
||||
.ui-layout-toggler {
|
||||
/* border: 1px solid #eee;
|
||||
background-color: #eee; */
|
||||
border-radius: 8px;
|
||||
}
|
||||
.ui-layout-resizer-hover .ui-layout-toggler {
|
||||
opacity: 1.00;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.ui-layout-toggler-hover , /* need when NOT resizable */
|
||||
.ui-layout-resizer-hover .ui-layout-toggler-hover { /* need specificity when IS resizable */
|
||||
background-color: #dfdfdf;
|
||||
opacity: 1.00;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.skin-dark .ui-layout-toggler-hover ,
|
||||
.skin-dark .ui-layout-resizer-hover .ui-layout-toggler-hover {
|
||||
background-color: #2e2e2e;
|
||||
}
|
||||
.ui-layout-toggler-north ,
|
||||
.ui-layout-toggler-south {
|
||||
border-width: 0 1px; /* left/right borders */
|
||||
}
|
||||
.ui-layout-toggler-west ,
|
||||
.ui-layout-toggler-east {
|
||||
border-width: 1px 0; /* top/bottom borders */
|
||||
}
|
||||
/* hide the toggler-button when the pane is 'slid open' */
|
||||
.ui-layout-resizer-sliding .ui-layout-toggler {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
* style the text we put INSIDE the togglers
|
||||
*/
|
||||
.ui-layout-toggler .ui-content {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 8px;
|
||||
width: 100%;
|
||||
padding-bottom: 0.35ex; /* to 'vertically center' text inside text-span */
|
||||
}
|
||||
.ui-layout-toggler .ui-content .fa{
|
||||
line-height: 8px;
|
||||
}
|
||||
|
||||
.ui-layout-toggler-north-closed .fa:before,
|
||||
.ui-layout-toggler-south-open .fa:before {
|
||||
content: "\f0d7";/* 下 */
|
||||
}
|
||||
.ui-layout-toggler-south-closed .fa:before,
|
||||
.ui-layout-toggler-north-open .fa:before {
|
||||
content: "\f0d8";/* 上 */
|
||||
}
|
||||
.ui-layout-toggler-west-closed .fa:before,
|
||||
.ui-layout-toggler-east-open .fa:before {
|
||||
content: "\f0da";/* 右 */
|
||||
}
|
||||
.ui-layout-toggler-east-closed .fa:before,
|
||||
.ui-layout-toggler-west-open .fa:before {
|
||||
content: "\f0d9";/* 左 */
|
||||
}
|
||||
|
||||
/*
|
||||
* PANE-MASKS
|
||||
* these styles are hard-coded on mask elems, but are also
|
||||
* included here as !important to ensure will overrides any generic styles
|
||||
*/
|
||||
.ui-layout-mask {
|
||||
border: none !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden !important;
|
||||
position: absolute !important;
|
||||
opacity: 0 !important;
|
||||
filter: Alpha(Opacity="0") !important;
|
||||
}
|
||||
.ui-layout-mask-inside-pane { /* masks always inside pane EXCEPT when pane is an iframe */
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
div.ui-layout-mask {} /* standard mask for iframes */
|
||||
iframe.ui-layout-mask {} /* extra mask for objects/applets */
|
||||
|
||||
/*
|
||||
* Default printing styles
|
||||
*/
|
||||
@media print {
|
||||
/*
|
||||
* Unless you want to print the layout as it appears onscreen,
|
||||
* these html/body styles are needed to allow the content to 'flow'
|
||||
*/
|
||||
html {
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
body.ui-layout-container {
|
||||
position: static !important;
|
||||
top: auto !important;
|
||||
bottom: auto !important;
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
/* only IE6 has container width & height set by Layout */
|
||||
_width: auto !important;
|
||||
_height: auto !important;
|
||||
}
|
||||
.ui-layout-resizer, .ui-layout-toggler {
|
||||
display: none !important;
|
||||
}
|
||||
/*
|
||||
* Default pane print styles disables positioning, borders and backgrounds.
|
||||
* You can modify these styles however it suit your needs.
|
||||
*/
|
||||
.ui-layout-pane {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
bottom: auto !important;
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
.strength {position:relative;}
|
||||
.strength .strength_input {position:absolute;left:0;top:0;height:30px;background:transparent;border:transparent;z-index:2;color:#333;}
|
||||
.strength .strength_input:focus {background:transparent;}
|
||||
.strength .strength_meter {position:absolute;left:0;top:0;width:100%;height:30px;z-index:1;border:1px solid #dedede;border-radius:4px;}
|
||||
.strength .strength_meter.veryweak {border-color:#F04040!important;}
|
||||
.strength .strength_meter.weak {border-color:#FF853C!important;}
|
||||
.strength .strength_meter.medium {border-color:#FC0!important;}
|
||||
.strength .strength_meter.strong {border-color:#8DFF1C!important;}
|
||||
.strength .strength_meter div {width:0%;height:28px;text-align:right;-webkit-transition:all .3s ease-in-out;border-radius:4px;}
|
||||
.strength .strength_meter div.veryweak {background-color:#FFA0A0;width:25%!important;}
|
||||
.strength .strength_meter div.weak {background-color:#FFB78C;width:50%!important;}
|
||||
.strength .strength_meter div.medium {background-color:#FFEC8B;width:75%!important;}
|
||||
.strength .strength_meter div.strong {background-color:#C3FF88;width:100%!important;}
|
||||
.strength .strength_meter div p {position:absolute;right:15px;font-size:13px;line-height:29px;font-weight:bold;color:#333}
|
||||
.strength .button_strength {text-decoration:none;display:block;padding-top:43px;color:#f59942;}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*!
|
||||
* strength.js
|
||||
* Original author: @aaronlumsden
|
||||
* Further changes, comments: jeesite
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
;(function ($, window, document, undefined) {
|
||||
|
||||
var pluginName = "strength";
|
||||
|
||||
function Plugin(element, options) {
|
||||
this.element = element;
|
||||
this.$elem = $(this.element);
|
||||
this.options = $.extend({}, $.fn.strength.defaults, options);
|
||||
this._defaults = $.fn.strength.defaults;
|
||||
this._name = pluginName;
|
||||
this.init();
|
||||
}
|
||||
|
||||
Plugin.prototype = {
|
||||
|
||||
init : function () {
|
||||
|
||||
var options = this.options;
|
||||
|
||||
var upperCaseExp = new RegExp("[A-Z]");
|
||||
var lowerCaseExp = new RegExp("[a-z]");
|
||||
var numberExp = new RegExp("[0-9]");
|
||||
var specialExp = new RegExp("[~!@#$%\\^&\\*()_+\\{\\}:\"\\|<>?`\\-=\\[\\];\\\'\\\\,\\./]");
|
||||
|
||||
function check_strength(thisval, thisid) {
|
||||
var charLength = thisval.length >= 8 ? 1 : 0;
|
||||
var upperCase = thisval.match(upperCaseExp) ? 1 : 0;
|
||||
var lowerCase = thisval.match(lowerCaseExp) ? 1 : 0;
|
||||
var number = thisval.match(numberExp) ? 1 : 0;
|
||||
var special = thisval.match(specialExp) ? 1 : 0;
|
||||
var total = charLength + upperCase + lowerCase + number + special;
|
||||
get_total(total, thisid);
|
||||
options.strengthCheck(thisval, total);
|
||||
}
|
||||
|
||||
function get_total(total, thisid) {
|
||||
var thismeter = $('div[data-meter="' + thisid + '"]').removeClass();
|
||||
thismeter.parent().removeClass().addClass(options.strengthMeterClass);
|
||||
if (total == 1) {
|
||||
thismeter.parent().addClass('veryweak');
|
||||
thismeter.addClass('veryweak').html('<p>'+options.veryweakText+'</p>');
|
||||
} else if (total == 2) {
|
||||
thismeter.parent().addClass('weak');
|
||||
thismeter.addClass('weak').html('<p>'+options.weakText+'</p>');
|
||||
} else if (total == 3 || total == 4) {
|
||||
thismeter.parent().addClass('medium');
|
||||
thismeter.addClass('medium').html('<p>'+options.mediumText+'</p>');
|
||||
} else if (total > 4) {
|
||||
thismeter.parent().addClass('strong');
|
||||
thismeter.addClass('strong').html('<p>'+options.strongText+'</p>');
|
||||
} else {
|
||||
thismeter.html('');
|
||||
}
|
||||
}
|
||||
|
||||
var isShown = false;
|
||||
var strengthButtonText = options.strengthTipText + ' ' + options.strengthButtonText;
|
||||
var strengthButtonTextToggle = options.strengthTipText + ' ' + options.strengthButtonTextToggle;
|
||||
|
||||
var thisid = this.$elem.attr('id');
|
||||
|
||||
this.$elem.parent().addClass(options.strengthClass);
|
||||
|
||||
this.$elem.addClass(options.strengthInputClass).attr('data-password', thisid)
|
||||
.after('<input style="display:none" class="' + this.$elem.attr('class') + '" data-password="'
|
||||
+ thisid + '" type="text" name="" value=""><a data-password-button="' + thisid
|
||||
+ '" href="javascript:" class="' + options.strengthButtonClass + '" tabindex="-1">'
|
||||
+ strengthButtonText + '</a><div class="' + options.strengthMeterClass
|
||||
+ '"><div data-meter="' + thisid + '"><p></p></div></div>');
|
||||
|
||||
this.$elem.bind('keyup keydown', function (event) {
|
||||
thisval = $('#' + thisid).val();
|
||||
var st = $('input[type="text"][data-password="' + thisid + '"]').val(thisval);
|
||||
try{st.resetValid();}catch(e){}; // 如果表单加了验证,则验证。
|
||||
check_strength(thisval, thisid);
|
||||
});
|
||||
|
||||
$('input[type="text"][data-password="' + thisid + '"]').bind('keyup keydown', function (event) {
|
||||
thisval = $('input[type="text"][data-password="' + thisid + '"]').val();
|
||||
$('input[type="password"][data-password="' + thisid + '"]').val(thisval);
|
||||
check_strength(thisval, thisid);
|
||||
});
|
||||
|
||||
$(document.body).on('click', '.' + options.strengthButtonClass, function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
thisclass = 'hide_' + $(this).attr('class');
|
||||
|
||||
if (isShown) {
|
||||
$('input[type="text"][data-password="' + thisid + '"]').hide();
|
||||
$('input[type="password"][data-password="' + thisid + '"]').show().focus();
|
||||
$('a[data-password-button="' + thisid + '"]').removeClass(thisclass).html(strengthButtonText);
|
||||
isShown = false;
|
||||
|
||||
} else {
|
||||
$('input[type="text"][data-password="' + thisid + '"]').show().focus();
|
||||
$('input[type="password"][data-password="' + thisid + '"]').hide();
|
||||
$('a[data-password-button="' + thisid + '"]').addClass(thisclass).html(strengthButtonTextToggle);
|
||||
isShown = true;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// A really lightweight plugin wrapper around the constructor,
|
||||
// preventing against multiple instantiations
|
||||
$.fn[pluginName] = function (options) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, "plugin_" + pluginName)) {
|
||||
$.data(this, "plugin_" + pluginName, new Plugin(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.fn[pluginName].defaults = {
|
||||
strengthClass : 'strength',
|
||||
strengthInputClass : 'strength_input',
|
||||
strengthMeterClass : 'strength_meter',
|
||||
strengthButtonClass : 'button_strength',
|
||||
strengthTipText: '建议:长度不小于8位,且包含,大写英文字母、小写英文字母、数字和符号。',
|
||||
strengthButtonText: '点击显示密码。',
|
||||
strengthButtonTextToggle: '点击隐藏密码。',
|
||||
veryweakText: '密码太弱啦!',
|
||||
weakText: '密码比较弱哦!',
|
||||
mediumText: '密码较安全!',
|
||||
strongText: '密码很强很安全!',
|
||||
// 验证后调用方法(当前值,安全级别)
|
||||
strengthCheck: function(thisval, thislevel){ }
|
||||
};
|
||||
|
||||
})(jQuery, window, document);
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.2 KiB |
@@ -1,42 +0,0 @@
|
||||
<!-- Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
No deletion without permission, or be held responsible to law. -->
|
||||
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" />
|
||||
<title>请升级您的浏览器</title><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" >
|
||||
<meta name="renderer" content="webkit"><base target="_blank" /><style type="text/css">
|
||||
a{text-decoration:none;color:#0072c6;}a:hover{text-decoration:none;color:#004d8c;}
|
||||
body{width:960px;margin:0 auto;padding:10px;font-size:14px;line-height:24px;color:#454545;font-family:'Microsoft YaHei UI','Microsoft YaHei',DengXian,SimSun,'Segoe UI',Tahoma,Helvetica,sans-serif;}
|
||||
h1{font-size:30px;line-height:80px;font-weight:100;margin-bottom:10px;}
|
||||
h2{font-size:20px;line-height:25px;font-weight:100;margin:10px 0;}
|
||||
p{margin-bottom:10px;font-size:16px;}
|
||||
hr{margin:20px 0;border:0;border-top:1px solid #dadada}
|
||||
img{width:34px;height:34px;border:0;float:left;margin-right:10px;}
|
||||
span{display:block;font-size:12px;line-height:12px;}
|
||||
.browser{padding:10px 0;}
|
||||
.browser li{width:180px;height:34px;line-height:22px;float:left;list-style:none;padding-left:25px}
|
||||
.clean{clear:both;}
|
||||
</style></head><body>
|
||||
<h1>浏览器版本过低,是时候升级您的浏览器了</h1>
|
||||
<p>本系统 <a href="http://jeesite.com">JeeSite</a> 支持 IE9 及以上版本及其他所有现代浏览器,如:谷歌浏览器、火狐浏览器、国产浏览器 等。</p>
|
||||
<p>您正在使用 Internet Explorer 的过期版本(IE6、IE7、IE8 内核的浏览器)。这意味着在升级浏览器前,您将无法继续访问。</p>
|
||||
<hr>
|
||||
<h2>为什么会出现这个页面?</h2>
|
||||
<p>如果您不知道升级浏览器是什么意思,请请教一些熟练电脑操作的朋友。如果您使用的不是Internet Explorer,而是360、QQ、搜狗等,双核浏览器,出现这个页面可能是您切换到了兼容模式,请<strong style="color:#f00;">切换到极速模式</strong>下,如果还不行请升级至最新版浏览器。</p>
|
||||
<hr>
|
||||
<h2>请注意:微软(Microsoft)对 Windows XP、Vista、7、8、8.1 及 Internet Explorer 的支持已经结束</h2>
|
||||
<p>微软(Microsoft)不再为已经结束的版本提供相应支持和更新。如果您继续使用这些,您将可能受到病毒、间谍软件和其他恶意软件的攻击,无法确保个人信息的安全。请参阅 <a href="http://windows.microsoft.com/zh-cn/windows/end-support-help">Windows XP 支持已经结束的说明</a> 。</p>
|
||||
<p>于 2022 年 6 月 15 日,微软对 Internet Explorer 11 的支持也已结束。请参阅 <a href="http://windows.microsoft.com/zh-cn/internet-explorer/download-ie"> Internet Explorer 浏览器下载</a>。</p>
|
||||
<hr>
|
||||
<h2>您可以选择更先进的浏览器</h2>
|
||||
<p>推荐使用以下浏览器的最新版本。如果您的电脑已有以下浏览器的最新版本则直接使用该浏览器访问 <b id="url"></b>即可。</p>
|
||||
<div class="browser"><ul>
|
||||
<li><img src="img/chrome360.jpg"><a href="http://chrome.360.cn/"> 360极速浏览器<span>360 Chrome</span></a></li>
|
||||
<li><img src="img/chrome.jpg"><a href="http://www.google.cn/intl/zh-CN/chrome/browser/desktop/index.html"> 谷歌浏览器<span>Google Chrome</span></a></li>
|
||||
<li><img src="img/firefox.jpg"><a href="http://www.firefox.com.cn/download/"> 火狐浏览器<span>Mozilla Firefox</span></a></li>
|
||||
<li><img src="img/edge.png"><a href="https://www.microsoft.com/zh-cn/edge"> Edge 浏览器<span>Microsoft Edge</span></a></li>
|
||||
</ul><div class="clean"></div></div>
|
||||
<hr><br/>
|
||||
<script>
|
||||
var url = location.href; url = url.substring(0, url.indexOf('/static/upbw'));
|
||||
document.getElementById("url").innerHTML = '<a href="' + url + '">' + url + '</a> ';
|
||||
</script>
|
||||
</body></html>
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.codec;
|
||||
|
||||
import com.jeesite.common.codec.AesUtils;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* AES 加密解密工具类
|
||||
* @author ThinkGem
|
||||
* @version 2024-07-22
|
||||
*/
|
||||
public class AesUtilsTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
String s = "Hello word! 你好,中文!";
|
||||
System.out.println(s);
|
||||
|
||||
String k = AesUtils.genKeyString();
|
||||
System.out.println(k);
|
||||
String s1 = AesUtils.encode(s, k);
|
||||
System.out.println(s1);
|
||||
String s2 = AesUtils.decode(s1, k);
|
||||
System.out.println(s2);
|
||||
|
||||
byte[] key = AesUtils.genKey();
|
||||
byte[] iv = AesUtils.genIV();
|
||||
byte[] data = AesUtils.encode(s.getBytes(StandardCharsets.UTF_8), key, iv);
|
||||
System.out.println(EncodeUtils.encodeHex(data));
|
||||
byte[] data2 = AesUtils.decode(data, key, iv);
|
||||
System.out.println(new String(data2, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.codec;
|
||||
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
|
||||
/**
|
||||
* 封装各种格式的编码解码工具测试类
|
||||
* @author ThinkGem
|
||||
* @version 2024-07-22
|
||||
*/
|
||||
public class EncodeUtilsTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
EncodeUtils.xssFilter("1 你好 <script>alert(document.cookie)</script>我还在。");
|
||||
EncodeUtils.xssFilter("2 你好 <strong>加粗文字</strong>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->3 你好 \"><strong>加粗文字</strong>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->4 你好 <iframe src=\"abcdef\"></iframe><strong>加粗文字</strong>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->5 你好 <iframe src=\"abcdef\"/><strong>加粗文字</strong>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->6 你好 <iframe src=\"abcdef\"><strong>加粗文字</strong>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->7 你好 <script type=\"text/javascript\">alert(document.cookie)</script>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->8 你好 <script\n type=\"text/javascript\">\nalert(document.cookie)\n</script>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->9 你好 <script src='' onerror='alert(document.cookie)'></script>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->10 你好 <script type=text/javascript>alert()我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->11 你好 <script>alert(document.cookie)</script>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->12 你好 <script>window.location='url'我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->13 你好 </script></iframe>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->14 你好 eval(abc)我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->15 你好 expression(abc)我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->16 你好 <img src='abc.jpg' onerror='location='';alert(document.cookie);'></img>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->17 你好 <img src='abc.jpg' onerror='alert(document.cookie);'/>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->18 你好 <img src='abc.jpg' onerror='alert(document.cookie);'>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->19 你好 <a onload='alert(\"abc\")'>hello</a>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->20 你好 <a href=\"/abc\">hello</a>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->21 你好 <a href='/abc'>hello</a>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->22 你好 <a href='vbscript:alert(\"abc\");'>hello</a>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->23 你好 <a href='javascript:alert(\"abc\");'>hello</a>我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->24 你好 ?abc=def&hello=123&world={\"a\":1}我还在。");
|
||||
EncodeUtils.xssFilter("<!--HTML-->25 你好 ?abc=def&hello=123&world={'a':1}我还在。");
|
||||
EncodeUtils.sqlFilter("1 你好 select * from xxx where abc=def and 1=1我还在。");
|
||||
EncodeUtils.sqlFilter("2 你好 insert into xxx values(1,2,3,4,5)我还在。");
|
||||
EncodeUtils.sqlFilter("3 你好 delete from xxx我还在。");
|
||||
EncodeUtils.sqlFilter("4 a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(111) end then 1 else 1/0 end", "orderBy");
|
||||
EncodeUtils.sqlFilter("5 if(1=2,1,SLEEP(10)), if(mid(database(),{},1)=\\\"{}\\\",a.id,a.login_name)", "orderBy");
|
||||
EncodeUtils.sqlFilter("6 a.audit_result asc, b.audit_result2 desc, b.AuditResult3 desc", "orderBy");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.codec;
|
||||
|
||||
import com.jeesite.common.codec.Sha1Utils;
|
||||
|
||||
/**
|
||||
* SHA-1 加密工具类,散列加密,不可逆加密
|
||||
* @author ThinkGem
|
||||
* @version 2024-07-22
|
||||
*/
|
||||
public class Sha1UtilsTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
String s = "Hello word! 你好,中文!";
|
||||
System.out.println(s);
|
||||
|
||||
String salt = Sha1Utils.genSaltString(8);
|
||||
System.out.println(salt);
|
||||
String data = Sha1Utils.sha1(s, salt);
|
||||
System.out.println(data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -230,7 +230,7 @@ public class ReflectUtilsTest {
|
||||
*/
|
||||
class ReflectUtils2 {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ReflectUtils2.class);
|
||||
private static Logger logger = LoggerFactory.getLogger(ReflectUtils2.class);
|
||||
private static final String SETTER_PREFIX = "set";
|
||||
private static final String GETTER_PREFIX = "get";
|
||||
private static Class baseEntityClass = null;
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.utils.excel;
|
||||
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.utils.excel.ExcelExport;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 导出Excel文件测试类
|
||||
* @author ThinkGem
|
||||
* @version 2020-3-5
|
||||
*/
|
||||
public class ExcelExportTest {
|
||||
|
||||
/**
|
||||
* 导出测试
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
File classPath = new File(ExcelExportTest.class.getResource("/").getFile());
|
||||
String fileName = classPath.getParentFile().getAbsoluteFile() + "/export.xlsx";
|
||||
|
||||
// 初始化表头
|
||||
List<String> headerList = ListUtils.newArrayList();
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
headerList.add("表头"+i);
|
||||
}
|
||||
|
||||
// 初始化数据集
|
||||
List<String> rowList = ListUtils.newArrayList();
|
||||
for (int i = 1; i <= headerList.size(); i++) {
|
||||
rowList.add("数据"+i);
|
||||
}
|
||||
List<List<String>> dataList = ListUtils.newArrayList();
|
||||
for (int i = 1; i <=100; i++) {
|
||||
dataList.add(rowList);
|
||||
}
|
||||
|
||||
// 创建一个Sheet表,并导入数据
|
||||
try(ExcelExport ee = new ExcelExport("表格1", "表格标题1", headerList, null)){
|
||||
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
Row row = ee.addRow();
|
||||
for (int j = 0; j < dataList.get(i).size(); j++) {
|
||||
ee.addCell(row, j, dataList.get(i).get(j));
|
||||
}
|
||||
}
|
||||
|
||||
// 再创建一个Sheet表,并导入数据
|
||||
ee.createSheet("表格2", "表格标题2", headerList, null);
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
Row row = ee.addRow();
|
||||
for (int j = 0; j < dataList.get(i).size(); j++) {
|
||||
ee.addCell(row, j, dataList.get(i).get(j)+"2");
|
||||
}
|
||||
}
|
||||
|
||||
// 输出到文件
|
||||
ee.writeFile(fileName);
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Export success.");
|
||||
|
||||
// 按模板导出,从第 3 行开始
|
||||
ExcelImport ei = new ExcelImport(fileName, 3);
|
||||
try(ExcelExport ee = new ExcelExport(ei)){
|
||||
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
Row row = ee.addRow();
|
||||
for (int j = 0; j < dataList.get(i).size(); j++) {
|
||||
ee.addCell(row, j, dataList.get(i).get(j) + "-plus");
|
||||
}
|
||||
}
|
||||
|
||||
// 输出到文件
|
||||
ee.writeFile(fileName);
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Export success by template.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.utils.excel;
|
||||
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 导入Excel文件测试类
|
||||
* @author ThinkGem
|
||||
* @version 2020-3-5
|
||||
*/
|
||||
public class ExcelImportTest {
|
||||
|
||||
/**
|
||||
* 导入测试
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
File classPath = new File(ExcelExportTest.class.getResource("/").getFile());
|
||||
String fileName = classPath.getParentFile().getAbsoluteFile() + "/export.xlsx";
|
||||
ExcelImport ei = new ExcelImport(fileName, 1);
|
||||
|
||||
for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
|
||||
Row row = ei.getRow(i);
|
||||
if (row == null){
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < ei.getLastCellNum(); j++) {
|
||||
Object val = ei.getCellValue(row, j);
|
||||
System.out.print(val+", ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("Import success.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
* No deletion without permission, or be held responsible to law.
|
||||
*/
|
||||
package com.jeesite.test.web.http;
|
||||
|
||||
import com.jeesite.common.web.http.HttpClientUtils;
|
||||
|
||||
/**
|
||||
* HTTP客户端测试工具类(支持HTTPS)
|
||||
* @author ThinkGem
|
||||
* @version 2017-3-27
|
||||
*/
|
||||
public class HttpClientUtilsTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
String content = HttpClientUtils.get("https://jeesite.com");
|
||||
System.out.println(content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -329,7 +329,7 @@
|
||||
</word>
|
||||
<word>
|
||||
<id>a63e3fda50530388ba263296184d8a6919a75791</id>
|
||||
<length>4000</length>
|
||||
<length>1000</length>
|
||||
<decimal>null</decimal>
|
||||
<array>false</array>
|
||||
<array_dimension>null</array_dimension>
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE js_app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks vargraphic(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content vargraphic(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE js_app_comment
|
||||
update_date datetime NOT NULL,
|
||||
remarks varchar(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content varchar(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE [js_app_comment]
|
||||
[update_date] datetime NOT NULL,
|
||||
[remarks] nvarchar(500),
|
||||
[create_by_name] varchar(200),
|
||||
[device_info] varchar(4000),
|
||||
[device_info] varchar(1000),
|
||||
[reply_date] date,
|
||||
[reply_content] nvarchar(500),
|
||||
[reply_user_code] varchar(64),
|
||||
|
||||
@@ -17,7 +17,7 @@ CREATE TABLE js_app_comment
|
||||
update_date datetime NOT NULL COMMENT '更新时间',
|
||||
remarks varchar(500) COMMENT '备注信息',
|
||||
create_by_name varchar(200) COMMENT '提问人员姓名',
|
||||
device_info varchar(4000) COMMENT '设备信息',
|
||||
device_info varchar(1000) COMMENT '设备信息',
|
||||
reply_date date COMMENT '回复时间',
|
||||
reply_content varchar(500) COMMENT '回复意见',
|
||||
reply_user_code varchar(64) COMMENT '回复人员',
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE js_app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks nvarchar2(500),
|
||||
create_by_name varchar2(200),
|
||||
device_info varchar2(4000),
|
||||
device_info varchar2(1000),
|
||||
reply_date date,
|
||||
reply_content nvarchar2(500),
|
||||
reply_user_code varchar2(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE js_app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks varchar(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content varchar(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>5.10.0.springboot3-SNAPSHOT</version>
|
||||
<version>5.7.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -38,13 +38,13 @@
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<developers>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>thinkgem</id>
|
||||
<name>WangZhen</name>
|
||||
<email>thinkgem at 163.com</email>
|
||||
<roles><role>Project lead</role></roles>
|
||||
<timezone>+8</timezone>
|
||||
<timezone>+8</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
*/
|
||||
package com.jeesite.modules.app.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* APP意见反馈Entity
|
||||
@@ -82,7 +84,7 @@ public class AppComment extends DataEntity<AppComment> {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
@Size(min=0, max=4000, message="设备信息长度不能超过 4000 个字符")
|
||||
@Size(min=0, max=1000, message="设备信息长度不能超过 1000 个字符")
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ package com.jeesite.modules.app.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
|
||||
@@ -6,8 +6,8 @@ package com.jeesite.modules.app.web;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
package com.jeesite.modules.app.web;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE ${_prefix}app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks vargraphic(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content vargraphic(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE ${_prefix}app_comment
|
||||
update_date datetime NOT NULL,
|
||||
remarks varchar(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content varchar(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE [${_prefix}app_comment]
|
||||
[update_date] datetime NOT NULL,
|
||||
[remarks] nvarchar(500),
|
||||
[create_by_name] varchar(200),
|
||||
[device_info] varchar(4000),
|
||||
[device_info] varchar(1000),
|
||||
[reply_date] date,
|
||||
[reply_content] nvarchar(500),
|
||||
[reply_user_code] varchar(64),
|
||||
|
||||
@@ -17,7 +17,7 @@ CREATE TABLE ${_prefix}app_comment
|
||||
update_date datetime NOT NULL COMMENT '更新时间',
|
||||
remarks varchar(500) COMMENT '备注信息',
|
||||
create_by_name varchar(200) COMMENT '提问人员姓名',
|
||||
device_info varchar(4000) COMMENT '设备信息',
|
||||
device_info varchar(1000) COMMENT '设备信息',
|
||||
reply_date date COMMENT '回复时间',
|
||||
reply_content varchar(500) COMMENT '回复意见',
|
||||
reply_user_code varchar(64) COMMENT '回复人员',
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE ${_prefix}app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks nvarchar2(500),
|
||||
create_by_name varchar2(200),
|
||||
device_info varchar2(4000),
|
||||
device_info varchar2(1000),
|
||||
reply_date date,
|
||||
reply_content nvarchar2(500),
|
||||
reply_user_code varchar2(64),
|
||||
|
||||
@@ -16,7 +16,7 @@ CREATE TABLE ${_prefix}app_comment
|
||||
update_date timestamp NOT NULL,
|
||||
remarks varchar(500),
|
||||
create_by_name varchar(200),
|
||||
device_info varchar(4000),
|
||||
device_info varchar(1000),
|
||||
reply_date date,
|
||||
reply_content varchar(500),
|
||||
reply_user_code varchar(64),
|
||||
|
||||
@@ -17,10 +17,4 @@
|
||||
5.6.0
|
||||
5.6.1
|
||||
5.7.0
|
||||
5.7.1
|
||||
5.8.0
|
||||
5.8.1
|
||||
5.9.0
|
||||
5.9.1
|
||||
5.9.2
|
||||
5.10.0
|
||||
5.7.1
|
||||
@@ -160,7 +160,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script>
|
||||
$('#inputForm').validate({
|
||||
$("#inputForm").validate({
|
||||
submitHandler: function(form){
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
js.showMessage(data.message);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${appComment}" action="${ctx}/app/appComment/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${appComment}" action="${ctx}/app/appComment/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('问题分类')}:</label>
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script>
|
||||
$('#inputForm').validate({
|
||||
$("#inputForm").validate({
|
||||
submitHandler: function(form){
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
js.showMessage(data.message);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${appUpgrade}" action="${ctx}/app/appUpgrade/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${appUpgrade}" action="${ctx}/app/appUpgrade/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('应用代号')}:</label>
|
||||
@@ -37,7 +37,7 @@
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('发布时间')}:</label>
|
||||
<div class="control-inline">
|
||||
<#form:input path="upDate" readonly="true" maxlength="20" class="form-control laydate width-date"
|
||||
<#form:input path="upDate" readonly="true" maxlength="20" class="form-control laydate width-datetime"
|
||||
dataFormat="date" data-type="date" data-format="yyyy-MM-dd"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
51
modules/cms/README.md
Normal file
51
modules/cms/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
# 技术交流
|
||||
|
||||
* 交流 QQ 群(千人大群):`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)`
|
||||
* 码云Gitee:<https://gitee.com/thinkgem/jeesite5>
|
||||
* GitHub:<https://github.com/thinkgem/jeesite5>
|
||||
* 作者博客:<https://my.oschina.net/thinkgem>
|
||||
* **帮助文档:**<http://docs.jeesite.com>
|
||||
* 官方网站:<http://jeesite.com>
|
||||
* 问题反馈:<http://jeesite.net> [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR)
|
||||
* 关注微信公众号,了解最新动态:
|
||||
|
||||

|
||||
|
||||
## 介绍
|
||||
|
||||
JeeSite CMS 内容管理,是一个轻量级的 Web 建站神器,可以快速进行企业网站、门户网站、个人博客、知识库等建设。
|
||||
|
||||
* 基础功能:站点管理、栏目管理、栏目权限、模板管理、内容发布
|
||||
* 高级功能:多租户、多站点、页面静态化访问、全文检索
|
||||
|
||||
规划内容:站内统计、标签管理、留言管理、相关文章选取、文章多栏目
|
||||
|
||||
## 快速体验
|
||||
|
||||
### 在线演示
|
||||
|
||||
1. 前端演示:<http://demo.jeesite.com/js/f/index-main.html>
|
||||
2. 后端演示:<http://demo.jeesite.com/js/a/index#/js/a/cms/index#内容发布>
|
||||
3. 账号:system
|
||||
4. 密码:admin
|
||||
|
||||
### 本地运行
|
||||
|
||||
1. 环境准备:`JDK 1.8 or 11、17`、`Maven 3.6+`、`MySQL 5.7 or 8.0`
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite5/tree/master/modules/cms>
|
||||
3. 打开文件:/web`/src/main/resources/config/application.yml` 配置JDBC连接
|
||||
4. 打开文件:/web`/pom.xml` 打开 `jeesite-module-cms` 模块(去掉的注释标记)
|
||||
5. 执行脚本:/web`/bin/init-data.bat` 初始化数据库
|
||||
5. 执行脚本:/web`/bin/run-tomcat.bat` 启动服务即可
|
||||
6. 浏览器访问:<http://127.0.0.1:8980/js/> 账号 system 密码 admin
|
||||
7. 部署常见问题:<https://jeesite.com/docs/faq/>
|
||||
|
||||
### 开发环境
|
||||
|
||||
1. 部署运行文档:<https://jeesite.com/docs/install-deploy/>
|
||||
2. 部署常见问题:<https://jeesite.com/docs/faq/>
|
||||
|
||||
## 在线文档
|
||||
|
||||
* <http://docs.jeesite.com>
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>5.10.0.springboot3-SNAPSHOT</version>
|
||||
<version>5.7.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.modules.cms.utils.CmsUtils;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.entity;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.entity.Extend;
|
||||
|
||||
@@ -14,8 +14,8 @@ import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.modules.cms.utils.CmsUtils;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,10 +6,10 @@ package com.jeesite.modules.cms.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.entity;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
|
||||
@@ -14,8 +14,8 @@ import com.jeesite.modules.cms.utils.CmsUtils;
|
||||
import com.jeesite.modules.sys.utils.CorpUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.entity;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
|
||||
@@ -6,7 +6,7 @@ package com.jeesite.modules.cms.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
@Autowired(required = false)
|
||||
private PageCacheService pageCacheService;
|
||||
|
||||
private static final ExecutorService updateExpiredWeightThreadPool = new ThreadPoolExecutor(5, 20,
|
||||
private static ExecutorService updateExpiredWeightThreadPool = new ThreadPoolExecutor(5, 20,
|
||||
60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
|
||||
new DefaultThreadFactory("cms-update-expired-weight"));
|
||||
|
||||
@@ -240,8 +240,7 @@ public class ArticleService extends CrudService<ArticleDao, Article> {
|
||||
public Page<Map<String, Object>> searchPage(Page<Map<String, Object>> page, String qStr,
|
||||
String qand, String qnot, String bd, String ed, Map<String, String> params) {
|
||||
if (articleIndexService == null) {
|
||||
page.addOtherData("message", text("您好,请安装全文检索模块后再试。" +
|
||||
"<a href=\"https://jeesite.com/docs/cms/\" target=\"_blank\">安装文档</a>"));
|
||||
page.addOtherData("message", text("您好,系统未安装全文检索模块。"));
|
||||
return page;
|
||||
}
|
||||
return articleIndexService.searchPage(page, qStr, qand, qnot, bd, ed, params);
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.jeesite.modules.cms.service.CategoryService;
|
||||
import com.jeesite.modules.cms.service.SiteService;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import javax.servlet.ServletContext;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -38,6 +38,7 @@ public class CmsUtils {
|
||||
private static final SiteService siteService = SpringUtils.getBean(SiteService.class);
|
||||
private static final CategoryService categoryService = SpringUtils.getBean(CategoryService.class);
|
||||
private static final ArticleService articleService = SpringUtils.getBean(ArticleService.class);
|
||||
private static final ServletContext context = SpringUtils.getBean(ServletContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,7 +243,7 @@ public class CmsUtils {
|
||||
*/
|
||||
public static String getUrlDynamic(Article article) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(Global.getCtxPath());
|
||||
str.append(Static.context.getContextPath());
|
||||
if (StringUtils.isNotBlank(article.getHref())) {
|
||||
if (article.getHref().contains("://")) {
|
||||
return article.getHref();
|
||||
@@ -264,7 +265,7 @@ public class CmsUtils {
|
||||
*/
|
||||
public static String getUrlDynamic(Category category) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(Global.getCtxPath()).append(Global.getFrontPath());
|
||||
str.append(Static.context.getContextPath()).append(Global.getFrontPath());
|
||||
if (StringUtils.isNotBlank(category.getHref())) {
|
||||
if (category.getHref().contains("://")) {
|
||||
return category.getHref();
|
||||
@@ -284,7 +285,7 @@ public class CmsUtils {
|
||||
*/
|
||||
public static String getUrlDynamic(Site site) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(Global.getCtxPath()).append(Global.getFrontPath());
|
||||
str.append(Static.context.getContextPath()).append(Global.getFrontPath());
|
||||
if (StringUtils.isNotBlank(site.getDomain())) {
|
||||
if (site.getDomain().contains("://")) {
|
||||
return site.getDomain();
|
||||
@@ -304,7 +305,7 @@ public class CmsUtils {
|
||||
*/
|
||||
public static String getAdminUrlDynamic(Category category) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(Global.getCtxPath()).append(Global.getAdminPath());
|
||||
str.append(Static.context.getContextPath()).append(Global.getAdminPath());
|
||||
String adminUrlParam = null; // 管理地址的参数
|
||||
// 如果试图配置里配置了管理路径,则使用视图中的管理路径
|
||||
if (StringUtils.isNotBlank(category.getViewConfig())) {
|
||||
@@ -388,8 +389,8 @@ public class CmsUtils {
|
||||
if (StringUtils.isBlank(src)) {
|
||||
return src;
|
||||
}
|
||||
if (src.startsWith(Global.getCtxPath() + "/userfiles")) {
|
||||
return src.substring(Global.getCtxPath().length());
|
||||
if (src.startsWith(Static.context.getContextPath() + "/userfiles")) {
|
||||
return src.substring(Static.context.getContextPath().length());
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
@@ -404,10 +405,10 @@ public class CmsUtils {
|
||||
if (StringUtils.isBlank(src)) {
|
||||
return src;
|
||||
}
|
||||
if (src.startsWith(Global.getCtxPath() + "/userfiles")) {
|
||||
if (src.startsWith(Static.context.getContextPath() + "/userfiles")) {
|
||||
return src;
|
||||
} else {
|
||||
return Global.getCtxPath() + src;
|
||||
return Static.context.getContextPath() + src;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,6 +494,10 @@ public class CmsUtils {
|
||||
return Static.articleService;
|
||||
}
|
||||
|
||||
public static ServletContext getServletContext() {
|
||||
return Static.context;
|
||||
}
|
||||
|
||||
public static <V> V getCache(String key) {
|
||||
return CacheUtils.get(CMS_CACHE, key);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.jeesite.common.collect.MapUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.idgen.IdGen;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.cms.entity.Article;
|
||||
import com.jeesite.modules.cms.entity.Category;
|
||||
@@ -18,6 +19,7 @@ import com.jeesite.modules.cms.service.FileTempleteService;
|
||||
import com.jeesite.modules.cms.utils.CmsUtils;
|
||||
import com.jeesite.modules.sys.entity.Office;
|
||||
import com.jeesite.modules.sys.utils.DictUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -323,7 +325,7 @@ public class CategoryController extends BaseController {
|
||||
@RequestMapping(value = "fixTreeData")
|
||||
@ResponseBody
|
||||
public String fixTreeData(Category category) {
|
||||
if (!category.currentUser().isAdmin()) {
|
||||
if (!UserUtils.getUser().isAdmin()) {
|
||||
return renderResult(Global.FALSE, "操作失败,只有管理员才能进行修复!");
|
||||
}
|
||||
categoryService.fixTreeData();
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.web;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
package com.jeesite.modules.cms.web;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -105,11 +105,10 @@ public class FrontController extends BaseController {
|
||||
|
||||
// 如果设置了外部链接,则跳转到指定链接
|
||||
if (StringUtils.isNotBlank(category.getHref())) {
|
||||
String ctxPath = Global.getCtxPath();
|
||||
if (category.getHref().startsWith(ctxPath)) {
|
||||
category.setHref(category.getHref().replaceFirst(ctxPath, StringUtils.EMPTY));
|
||||
if (category.getHref().startsWith(request.getContextPath())) {
|
||||
category.setHref(category.getHref().replaceFirst(request.getContextPath(), ""));
|
||||
}
|
||||
return REDIRECT + category.getHref();
|
||||
return "redirect:" + category.getHref();
|
||||
}
|
||||
|
||||
// 获取站点信息
|
||||
@@ -267,11 +266,10 @@ public class FrontController extends BaseController {
|
||||
|
||||
// 如果设置了外部链接,则跳转到指定链接
|
||||
if (StringUtils.isNotBlank(article.getHref())) {
|
||||
String ctxPath = Global.getCtxPath();
|
||||
if (article.getHref().startsWith(ctxPath)) {
|
||||
article.setHref(article.getHref().replaceFirst(ctxPath, StringUtils.EMPTY));
|
||||
if (article.getHref().startsWith(request.getContextPath())) {
|
||||
article.setHref(article.getHref().replaceFirst(request.getContextPath(), ""));
|
||||
}
|
||||
return REDIRECT + article.getHref();
|
||||
return "redirect:" + article.getHref();
|
||||
}
|
||||
|
||||
model.addAttribute("article", article);
|
||||
|
||||
@@ -6,8 +6,8 @@ package com.jeesite.modules.cmsfront.web;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@@ -25,10 +25,4 @@
|
||||
5.6.0
|
||||
5.6.1
|
||||
5.7.0
|
||||
5.7.1
|
||||
5.8.0
|
||||
5.8.1
|
||||
5.9.0
|
||||
5.9.1
|
||||
5.9.2
|
||||
5.10.0
|
||||
5.7.1
|
||||
@@ -1,4 +1,4 @@
|
||||
body{padding-top:50px;font-size:15px;background:#f7f8f9;font-family:Arial, sans-serif;}
|
||||
body{padding-top:50px;font-size:15px;background:#f7f8f9;}
|
||||
body>.navbar{-webkit-transition:background-color .3s ease-in;transition:background-color .3s ease-in}
|
||||
@media (min-width:768px){
|
||||
body>.navbar-transparent{background-color:transparent}
|
||||
@@ -51,7 +51,6 @@ footer p{clear:left;margin-bottom:0}
|
||||
#banner{margin-bottom:2em;text-align:center}
|
||||
}
|
||||
|
||||
.navbar-inverse {border-bottom:0;}
|
||||
.breadcrumb {border-radius:8px;background:transparent;padding:0;margin:2px 15px 21px 15px;}
|
||||
|
||||
.jumbotron {background:#fff;margin:48px auto;border:1px solid #ededed;box-shadow:0 1px 4px 0 rgb(0 0 0 / 5%);border-radius:8px!important;}
|
||||
@@ -65,9 +64,8 @@ footer p{clear:left;margin-bottom:0}
|
||||
.panel-title small .more {padding-top:4px;font-size:14px}
|
||||
|
||||
.nav-search {margin-top:9px;}
|
||||
.nav-search .form-control {height:30px;line-height:30px;padding:5px;border-radius:4px;}
|
||||
.nav-search .btn {height:31px;padding:5px 10px;border-radius:15px;outline:none;}
|
||||
.nav-search .btn:focus {outline:none;}
|
||||
.nav-search .form-control {height:30px;padding:5px;}
|
||||
.nav-search .btn {height:31px;padding:5px 10px;}
|
||||
|
||||
.main {background:#fff;box-shadow:0 1px 4px 0 rgb(0 0 0 / 8%);border-radius:0 0 8px 8px;padding:20px 10px;margin:0 -1px}
|
||||
.main-list {border-radius:8px;}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${article}" action="${ctx}/cms/article/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${article}" action="${ctx}/cms/article/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('栏目编码')}:</label>
|
||||
@@ -54,7 +54,7 @@
|
||||
<script>
|
||||
//# // 初始化DataGrid对象
|
||||
$('#dataGrid').dataGrid({
|
||||
searchForm: $('#searchForm'),
|
||||
searchForm: $("#searchForm"),
|
||||
columnModel: [
|
||||
{header:'${text("标题")}', name:'title', index:'a.category_code', width:350, align:"left", frozen:true, formatter: function(val, obj, row, act){
|
||||
return '<a href="${ctx}/cms/article/form?id='+row.id+'" class="btnList" data-title="${text("编辑文章")}">'+(val||row.id)+'</a>';
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${category}" action="${ctx}/cms/category/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${category}" action="${ctx}/cms/category/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<#form:hidden path="site.siteCode" maxlength="64" class="form-control width-120" />
|
||||
<div class="form-group">
|
||||
@@ -69,7 +69,7 @@
|
||||
<script>
|
||||
//# // 初始化DataGrid对象
|
||||
$('#dataGrid').dataGrid({
|
||||
searchForm: $('#searchForm'),
|
||||
searchForm: $("#searchForm"),
|
||||
columnModel: [
|
||||
{header:'${text("名称")}', name:'categoryName', index:'a.category_name', width:250, align:"left", frozen:true, formatter: function(val, obj, row, act){
|
||||
return '( '+row.categoryCode+' ) '+'<a href="${ctx}/cms/category/form?categoryCode='+row.categoryCode+'" class="btnList" data-title="${text("编辑栏目表")}">'+(val||row.id)+'</a>';
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script>
|
||||
$('#inputForm').validate({
|
||||
$("#inputForm").validate({
|
||||
submitHandler: function(form){
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
js.showMessage(data.message);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${comment}" action="${ctx}/cms/comment/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${comment}" action="${ctx}/cms/comment/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('栏目编码')}:</label>
|
||||
@@ -107,7 +107,7 @@
|
||||
<script>
|
||||
//# // 初始化DataGrid对象
|
||||
$('#dataGrid').dataGrid({
|
||||
searchForm: $('#searchForm'),
|
||||
searchForm: $("#searchForm"),
|
||||
columnModel: [
|
||||
{header:'${text('栏目编码')}', name:'categoryCode', index:'a.category_code', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
|
||||
return '<a href="${ctx}/cms/comment/form?id='+row.id+'" class="btnList" data-title="${text('编辑文章评论表')}">'+(val||row.id)+'</a>';
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script>
|
||||
$('#inputForm').validate({
|
||||
$("#inputForm").validate({
|
||||
submitHandler: function(form){
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
js.showMessage(data.message);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${report}" action="${ctx}/cms/report/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${report}" action="${ctx}/cms/report/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('举报来源')}:</label>
|
||||
@@ -59,7 +59,7 @@
|
||||
<script>
|
||||
//# // 初始化DataGrid对象
|
||||
$('#dataGrid').dataGrid({
|
||||
searchForm: $('#searchForm'),
|
||||
searchForm: $("#searchForm"),
|
||||
columnModel: [
|
||||
{header:'${text('举报来源')}', name:'reportSource', index:'a.report_source', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
|
||||
return '<a href="${ctx}/cms/report/form?id='+row.id+'" class="btnList" data-title="${text('编辑内容举报表')}">'+(val||row.id)+'</a>';
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${site}" action="${ctx}/cms/site/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${site}" action="${ctx}/cms/site/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('站点名称')}:</label>
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script>
|
||||
$('#inputForm').validate({
|
||||
$("#inputForm").validate({
|
||||
submitHandler: function(form){
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
js.showMessage(data.message);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<#form:form id="searchForm" model="${visitLog}" action="${ctx}/cms/visitLog/listData" method="post" class="form-inline "
|
||||
<#form:form id="searchForm" model="${visitLog}" action="${ctx}/cms/visitLog/listData" method="post" class="form-inline hide"
|
||||
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">${text('请求的URL地址')}:</label>
|
||||
@@ -66,7 +66,7 @@
|
||||
<script>
|
||||
//# // 初始化DataGrid对象
|
||||
$('#dataGrid').dataGrid({
|
||||
searchForm: $('#searchForm'),
|
||||
searchForm: $("#searchForm"),
|
||||
columnModel: [
|
||||
{header:'${text('请求的URL地址')}', name:'requestUrl', index:'a.request_url', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
|
||||
return '<a href="${ctx}/cms/visitLog/form?id='+row.id+'" class="btnList" data-title="${text('编辑访问日志表')}">'+(val||row.id)+'</a>';
|
||||
|
||||
@@ -13,6 +13,4 @@
|
||||
</div>
|
||||
</footer>
|
||||
<script src="${ctxStatic}/modules/cmsfront/themes/js/bootstrap.min.js?${_version}"></script>
|
||||
<script src="${ctxStatic}/modules/cmsfront/themes/js/custom.js?${_version}"></script>
|
||||
<script src="${ctxStatic}/ueditor/1.4/ueditor.parse.js"></script>
|
||||
<script>uParse('.uparse',{rootPath:'${ctxStatic}/ueditor/1.4/'})</script>
|
||||
<script src="${ctxStatic}/modules/cmsfront/themes/js/custom.js?${_version}"></script>
|
||||
@@ -40,9 +40,7 @@
|
||||
<div class="form-group" title="填写关键字,按 Enter 键进行全文检索...">
|
||||
<input type="text" name="q" class="form-control" placeholder="全站搜索...">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary hide">搜索</button>
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user