39 Commits

Author SHA1 Message Date
RuoYi
e9e0718895 若依 v4.8.0 2024-12-26 10:14:55 +08:00
RuoYi
adf61988fe 代码生成新增配置是否允许文件覆盖到本地 2024-12-25 12:00:03 +08:00
RuoYi
7c1cdcd73f 修复多选下拉框open导致页签空白问题(IBBP7A) 2024-12-24 23:59:56 +08:00
RuoYi
e011eaea48 升级jquery.validate到最新版本v1.21.0 2024-12-24 19:52:48 +08:00
RuoYi
120d549170 优化select2下拉框必填背景色无法清空问题(IBB9XN) 2024-12-24 15:58:02 +08:00
若依
ddd858ca73 !536 Fix version 4.7.9 SQL Injection
Merge pull request !536 from mrlihd/fix-479-sqli
2024-12-24 04:00:09 +00:00
Linh Hoang
0cdb4c7b9c Add vertical tab to blacklist 2024-12-23 16:21:49 +00:00
RuoYi
9c9bbc8e2c update README 2024-12-13 20:17:14 +08:00
RuoYi
4aac0058ea 修复类匿名注解访问失效问题 2024-12-11 12:38:57 +08:00
RuoYi
6bc1a6aeb1 优化时间控件清除按钮样式问题(IBA1NL) 2024-12-10 16:30:36 +08:00
RuoYi
9a833095cf 优化导入带标题文件关闭清理(IB9Q9U) 2024-12-10 16:11:41 +08:00
RuoYi
a47b6e350e 修复未被代理类匿名访问失效问题(IB4EJ0) 2024-12-10 14:20:56 +08:00
RuoYi
e0aad97d59 优化表格图片预览动态路径显示问题 2024-12-10 13:28:45 +08:00
RuoYi
1aa973d300 列宽拖动长内容自适应显示 2024-12-07 14:19:06 +08:00
RuoYi
39ebc000f0 Excel注解支持wrapText是否允许内容换行 2024-12-03 08:45:32 +08:00
RuoYi
50a53dfc97 修复导出子列表对象只能在最后的问题 2024-12-02 20:35:58 +08:00
RuoYi
54ba9b8c02 update ry-ui.js 2024-11-13 21:55:39 +08:00
RuoYi
e728c37b64 add timezone 2024-11-12 13:07:43 +08:00
RuoYi
0eaeba0298 update pom.xml 2024-11-08 16:30:36 +08:00
RuoYi
7b6ed52181 升级pom依赖到安全版本(IAWCAE) 2024-11-08 16:03:41 +08:00
RuoYi
72868aeb6f 支持自定义显示Excel属性列 2024-11-07 22:11:27 +08:00
RuoYi
c0afd904d0 修复匿名注解空值无效的问题(IASXHN) 2024-11-06 20:53:06 +08:00
RuoYi
cac84c1bab 升级spring-framework到安全版本(IASFCW) 2024-11-06 20:08:15 +08:00
RuoYi
fb4f63c883 优化身份证脱敏正则 2024-10-21 17:20:08 +08:00
RuoYi
66ebd480e1 升级oshi到最新版本6.6.5 2024-10-18 20:41:43 +08:00
RuoYi
758dd95c07 添加新群号:232896766 2024-10-18 20:41:22 +08:00
RuoYi
c0ce3fd7c2 修复角色禁用权限不失效问题 2024-09-21 10:58:42 +08:00
RuoYi
9b68013b2a 用户导入响应消息对名称安全处理 2024-09-13 21:13:04 +08:00
RuoYi
c34d9f0c09 修复记住我请求头过大的问题 2024-09-09 10:29:12 +08:00
RuoYi
3b968d735f 修复记住我失效的问题(IAPHA4) 2024-09-06 20:16:22 +08:00
RuoYi
b2a491c99a update content 2024-09-04 19:40:09 +08:00
RuoYi
13fffa0ba8 优化异步树表格折叠同步子状态 2024-09-03 19:07:24 +08:00
RuoYi
d9fbae538b 升级oshi到最新版本6.6.3 2024-08-30 21:19:35 +08:00
RuoYi
adb22846a4 update sqlkeyword 2024-08-30 21:14:12 +08:00
RuoYi
5bef005075 修改时间范围日期格式 2024-07-08 16:26:49 +08:00
RuoYi
ad5cd1921e 升级commons.io到最新版本2.16.1 2024-07-03 11:39:00 +08:00
RuoYi
c6c8f8b3fb remove sub resultType 2024-07-03 11:06:05 +08:00
RuoYi
e9550ab5bd 优化代码 2024-06-27 16:44:51 +08:00
RuoYi
447542656a 修复主子表数据显示问题(IA61OI) 2024-06-24 17:19:49 +08:00
59 changed files with 628 additions and 258 deletions

View File

@@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-dd77653d7c9f197dd9d93684f3c8dcfbab6.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.9</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.8.0</h1>
<h4 align="center">基于SpringBoot开发的轻量级Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi/stargazers"><img src="https://gitee.com/y_project/RuoYi/badge/star.svg?theme=gvp"></a>
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.7.9-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.8.0-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
@@ -17,10 +17,9 @@
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 前端基于 [Hplus(H+)](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。
* 前后端分离版本,请移步[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 感谢 [hplus](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;
## 内置功能
@@ -99,4 +98,4 @@
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/已满-339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc) [![加入QQ群](https://img.shields.io/badge/已满-130035985-blue.svg)](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [![加入QQ群](https://img.shields.io/badge/已满-143151071-blue.svg)](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [![加入QQ群](https://img.shields.io/badge/已满-158781320-blue.svg)](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [![加入QQ群](https://img.shields.io/badge/已满-201531282-blue.svg)](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [![加入QQ群](https://img.shields.io/badge/已满-101526938-blue.svg)](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [![加入QQ群](https://img.shields.io/badge/已满-264355400-blue.svg)](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [![加入QQ群](https://img.shields.io/badge/已满-298522656-blue.svg)](https://jq.qq.com/?_wv=1027&k=540WfdEr) [![加入QQ群](https://img.shields.io/badge/已满-139845794-blue.svg)](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [![加入QQ群](https://img.shields.io/badge/已满-185760789-blue.svg)](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [![加入QQ群](https://img.shields.io/badge/已满-175104288-blue.svg)](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [![加入QQ群](https://img.shields.io/badge/已满-174942938-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [![加入QQ群](https://img.shields.io/badge/287843737-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737)
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/已满-339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc) [![加入QQ群](https://img.shields.io/badge/已满-130035985-blue.svg)](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [![加入QQ群](https://img.shields.io/badge/已满-143151071-blue.svg)](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [![加入QQ群](https://img.shields.io/badge/已满-158781320-blue.svg)](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [![加入QQ群](https://img.shields.io/badge/已满-201531282-blue.svg)](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [![加入QQ群](https://img.shields.io/badge/已满-101526938-blue.svg)](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [![加入QQ群](https://img.shields.io/badge/已满-264355400-blue.svg)](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [![加入QQ群](https://img.shields.io/badge/已满-298522656-blue.svg)](https://jq.qq.com/?_wv=1027&k=540WfdEr) [![加入QQ群](https://img.shields.io/badge/已满-139845794-blue.svg)](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [![加入QQ群](https://img.shields.io/badge/已满-185760789-blue.svg)](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [![加入QQ群](https://img.shields.io/badge/已满-175104288-blue.svg)](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [![加入QQ群](https://img.shields.io/badge/已满-174942938-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [![加入QQ群](https://img.shields.io/badge/已满-287843737-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) [![加入QQ群](https://img.shields.io/badge/232896766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766)

50
pom.xml
View File

@@ -5,20 +5,20 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>4.7.9</version>
<version>4.8.0</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>4.7.9</ruoyi.version>
<ruoyi.version>4.8.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<spring-boot.version>2.5.15</spring-boot.version>
<shiro.version>1.13.0</shiro.version>
<spring-framework.version>5.3.33</spring-framework.version>
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
<druid.version>1.2.23</druid.version>
<bitwalker.version>1.21</bitwalker.version>
@@ -26,17 +26,21 @@
<swagger.version>3.0.0</swagger.version>
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
<fastjson.version>1.2.83</fastjson.version>
<oshi.version>6.6.1</oshi.version>
<commons.io.version>2.13.0</commons.io.version>
<oshi.version>6.6.5</oshi.version>
<commons.io.version>2.16.1</commons.io.version>
<poi.version>4.1.2</poi.version>
<velocity.version>2.3</velocity.version>
<!-- override dependency version -->
<tomcat.version>9.0.96</tomcat.version>
<logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringFramework的依赖配置-->
<!-- 覆盖SpringFramework的依赖配置-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
@@ -49,11 +53,43 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.15</version>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 覆盖logback的依赖配置-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- 覆盖tomcat的依赖配置-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>

View File

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

View File

@@ -129,11 +129,11 @@ public class DemoTableController extends BaseController
private final static List<DocumentModel> documents = new ArrayList<DocumentModel>();
{
documents.add(new DocumentModel(1, "247-XW·2024-D10-0001", "新闻热线[2024]000001", "筑路千条 幸福万家——新疆“四好农村路”十年成果显著", "新疆地域广袤农村公路是群众出行的重要选择。顾志峰介绍2014年以来的十年间新疆累计完成农村公路建设投资约1071亿元累计新改建农村公路11.99万公里。截至2023年底全疆农村公路总里程达15.6万公里农村公路乡镇通三级及以上公路比例达到90.3%、较大人口规模自然村通硬化路比例达到91.5%,农村公路路网进一步完善,特别是南疆四地州农村路网结构得到根本性改善"));
documents.add(new DocumentModel(1, "247-XW·2024-D10-0001", "新闻热线[2024]000001", "索尼射击游戏《Concord》停止运营玩家将获全额退款", "索尼宣布多人射击游戏《Concord》将于9月6日停止运营玩家将获得全额退款。游戏总监Ryan Ellis在给玩家的信中表示这款游戏首次发布“并没有像我们预期的那样顺利”。《Concord》的开发历时8年投资超过1.5亿美元。游戏在Steam平台的售价为40美元采用买断制销售模式。据SteamDB统计游戏上市后的最高同时在线人数为697人"));
documents.add(new DocumentModel(2, "247-XW·2024-D30-0002", "新闻热线[2024]000002", "网红账号被封,央媒:如此炫富毒瘤早就该拔了", "在社交平台上分享自己的生活日常,本来无可厚非。但无底线地展示物欲、宣扬拜金,取笑甚至嘲讽工薪者的烟火生活,就会遮蔽普通人的平凡质朴和坚韧奋斗,在无形中消解芸芸众生脚踏实地、自立自强的社会正气。对这种助长金钱至上、刺激公众焦虑,既污染网络生态,又撕裂社会和谐的炫富“毒瘤”,必须坚决拔除之。在国家有关部门的部署下,近日,多个网络平台开展“不良价值导向内容专项治理”行动,对“奢靡浪费”“炫富拜金”等问题从严打击,倡导理性、文明的消费观和价值观。"));
documents.add(new DocumentModel(3, "CT01-XW·2024-Y-0003", "新闻热线[2024]000003", "重庆一夫妻被骗至缅甸,家属:两人已被解救,预计很快能回国", "5月25日重庆一对夫妻在前往泰国后失联疑被诈骗集团骗至缅甸的消息引发广泛关注。警方已对此事立案调查而这对夫妻的亲属则每天生活在焦急和不安之中。亲属家都瘫痪了事情一经曝光迅速登上了热搜成为公众热议的话题。据了解这对夫妻原计划是去泰国谈生意但不幸的是他们的泰国之行变成了一场噩梦。亲属李先生透露4月14日他们夫妻二人抵达泰国不久后便疑似被人以10万元的价格卖到缅甸目前被困在缅甸妙瓦底的一个电信诈骗园区。"));
documents.add(new DocumentModel(4, "CT01-XW·2024-Y-0004", "新闻热线[2024]000004", "江滨社区联合派出所、金霞消防站开展电动自行车安全隐患夜查活动", "近日,长沙市开福区江滨社区联合派出所、金霞消防站深入居民小区、单位场所,以电动车自行车火灾防范为重点,开展消防安全夜查行动。此次夜查紧紧围绕老旧居民区、“三合一”场所、沿街门店、夜间经营使用场所等场所开展监督检查,重点检查电动自行车违规停放充电、堵塞疏散通道和安全出口,架空层违规作为电动自行车停放充电场所,电动自行车违规“进楼入户”“飞线充电”,电动自行车擅自改装等五大类问题。"));
documents.add(new DocumentModel(5, "CT01-XW·2024-Y-0005", "新闻热线[2024]000005", "奋力建设“七个岳阳”,筑牢民生保障 奔向美好生活", "岳阳市委八届六次全会提出坚持“1376”总体思路着力推动高质量发展。“1”即始终牢记习近平总书记“守护好一江碧水”殷殷嘱托;“3”即在锚定“三高四新”美好蓝图中强化融入长江经济带、省域副中心、内陆地区改革开放高地三种意识;“7”即全面把握打造实力岳阳、富饶岳阳、美丽岳阳、开放岳阳、幸福岳阳、平安岳阳、新风岳阳“七个岳阳”目标任务;“6”即抓紧抓实“抓产业、促协调、优生态、扩开放、惠民生、防风险”六项重点工作。“1376”总体思路站位高远契合实际是岳阳深入学习贯彻落实习近平新时代中国特色社会主义思想向着强国建设、民族复兴宏伟目标奋勇前进的行动方案、奋进号令。为全面展示岳阳锚定新坐标、攀登新高度的奋斗姿态营造催人奋进的舆论氛围从2月1日起湖南日报社岳阳分社联动岳阳日报社、岳阳市广播电视台等主流媒体推出《奋力建设“七个岳阳”》系列报道。敬请关注"));
documents.add(new DocumentModel(5, "CT01-XW·2024-Y-0005", "新闻热线[2024]000005", "《黑神话》让海外玩家迷上“悟空”", "备受全球玩家瞩目的首款国产3A游戏《黑神话悟空》日前正式发布。精美绝伦的东方美学世界、精彩纷呈的中国神话故事、酣畅淋漓的游戏体验这款游戏为全球玩家带来一场视觉与文化的双重盛宴。从“悟空”成功出海的背后海外人士看到了中国游戏产业的巨大进步感受到了中国文化的多元精彩并对下一个“悟空”的诞生及更多中国文化产品走向世界充满期待"));
documents.add(new DocumentModel(6, "CT01-XW·2024-Y-0006", "新闻热线[2024]000006", "市场状况充满挑战极星宣布裁员全球约15%的员工", "据路透社报道极星周五以“充满挑战的市场状况”为由宣布计划在全球范围内裁减约450个职位。此次裁员之际许多人都对电动汽车需求降温表示担忧而且极星预计汽车业务最早将在2025年开始实现收支平衡。极星发言人表示“作为该商业计划的一部分我们需要调整我们的业务和运营规模。” “这涉及减少外部支出,遗憾的是,还包括我们的员工数量。”该公司还表示,希望减少对沃尔沃及其母公司吉利外部融资的依赖,最近还表示希望削减成本并提高电动汽车的利润率。"));
documents.add(new DocumentModel(7, "CT01-XW·2024-Y-0007", "新闻热线[2024]000007", "浙江隐秘富豪涉百亿非法集资案,部分资金流入新造车公司", "5月10日、11日上海北广投资管理有限公司下称“北广投”非法集资案在上海黄浦区人民法院一审公开开庭审理北广投实控人周敏、法定代表人朱江等30余名中高管被控非法吸收公众存款罪。根据财新报道这一案件中非法集资的资金有部分流入了两家新能源车企——爱驰汽车、万象汽车。同时有多位投资人引述与经侦部门沟通时的说法称该案事发时未兑付金额有130余亿元其中去往广微控股45亿元、万象汽车63亿元、爱驰汽车15亿元。"));
documents.add(new DocumentModel(8, "CT01-XW·2024-Y-0008", "新闻热线[2024]000008", "特斯拉宣布Model Y升级搭载HW4.0硬件售价仍25.89万元起", "2月1日特斯拉官方宣布ModelY升级。外观上新增ModelY专属色“快银车漆”并采用烈焰红代替中国红、星空灰代替冷光银性能上ModelY全系配备全新一代自动辅助驾驶硬件(HW4.0)通过搭载超远距离双目摄像头ModelY的最远探测距离达424米。由此特斯拉全系车型均配备了自动辅助驾驶硬件HW4.0。在售价方面特斯拉中国官网显示ModelY车型依然保持原价。ModelY后轮驱动版25.89万元起、ModelY长续航版29.99万元起、ModelY高性能版售价36.39万元起。"));

View File

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

View File

@@ -689,6 +689,7 @@
if (_isExpanded || _isCollapsed) {
var tr = $(this).parent().parent();
var row_id = tr.attr("id");
var row_pid = tr.attr("pid");
var _id = tr.attr("data-id");
var _ls = target.find("tbody").find("tr[id^='" + row_id + "_']");
if (!options.pagination) {
@@ -717,18 +718,36 @@
var _ls = target.find("tbody").find("tr[id^='" + row_id + "_']");
if (_ls && _ls.length > 0) {
if (_isExpanded) {
$.each(_ls, function(index, item) {
$(item).css("display", "none");
});
if (row_pid == "row_root") {
$('table tr[id^="' + row_id + '_"]').css("display", "none");
$('table tr[id^="' + row_id + '_"]').each(function(i,n) {
var _isExpanded = $(n).find(".treetable-expander").hasClass(options.expanderExpandedClass);
if (_isExpanded) {
$(n).find(".treetable-expander").trigger("click");
}
})
} else {
$.each(_ls, function(index, item) {
$(item).css("display", "none");
var _isExpanded = $(item).find(".treetable-expander").hasClass(options.expanderExpandedClass);
if (_isExpanded) {
$(item).find(".treetable-expander").trigger("click");
}
});
}
} else {
$.each(_ls, function(index, item) {
var _icon = $(item).eq(options.expandColumn).find(".treetable-expander");
if (_icon && _icon.hasClass(options.expanderExpandedClass)) {
$(item).css("display", "table");
} else {
$(item).css("display", "table");
}
});
if (row_pid == "row_root") {
$('table tr[pid="' + row_id + '"]').css("display", "table");
} else {
$.each(_ls, function(index, item) {
var _p_icon = $("#" + $(item).attr("pid")).children().eq(options.expandColumn).find(".treetable-expander");
var _isExpanded = _p_icon.hasClass(options.expanderExpandedClass);
var _isCollapsed = _p_icon.hasClass(options.expanderCollapsedClass);
if (row_id == $(item).attr("pid")) {
$(item).css("display", "table");
}
});
}
}
} else {
if (options.pagination) {

File diff suppressed because one or more lines are too long

View File

@@ -3036,11 +3036,6 @@ body.boxed-layout #wrapper {
display: block;
}
.clear {
display: block;
overflow: hidden;
}
a {
cursor: pointer;
}

File diff suppressed because one or more lines are too long

View File

@@ -350,11 +350,11 @@ label.error {
right: 42px;
}
.select2-hidden-accessible + label.error {
.select2-hidden-accessible + label.error, select.error + label.error {
right: 38px;
}
.Validform_error,input.error,textarea.error,select.error,label.error+.select2-container--bootstrap .select2-selection--single {
.Validform_error,input.error,textarea.error,select.error,select.error+label.error+.select2-container--bootstrap .select2-selection--single {
background-color: #fbe2e2;
border-color: #c66161;
color: #c00

View File

@@ -71,7 +71,7 @@ function openToCurrentTab(obj) {
if (isScrollToTop) {
$(obj).show().siblings('.RuoYi_iframe').hide();
} else {
$(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"});
$(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
}
}
@@ -312,10 +312,11 @@ $(function() {
// 添加选项卡对应的iframe
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-refresh="' + isRefresh + '" seamless></iframe>';
if (isScrollToTop) {
$('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
$('.mainContent').find('iframe.RuoYi_iframe').hide();
} else {
$('.mainContent').find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"}).parents('.mainContent').append(str1);
$('.mainContent').find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
}
$('.mainContent').append(str1);
$.modal.loading("数据加载中,请稍候...");

View File

@@ -283,10 +283,11 @@ function createMenuItem(dataUrl, menuName, isRefresh) {
// 添加选项卡对应的iframe
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" data-panel="' + panelUrl + '" seamless></iframe>';
if (isScrollToTop) {
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide();
} else {
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"}).parents('.mainContent').append(str1);
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
}
$('.mainContent', topWindow).append(str1);
window.parent.$.modal.loading("数据加载中,请稍候...");
$('.mainContent iframe:visible', topWindow).on('load', function() {
@@ -360,7 +361,7 @@ function openToCurrentTab(obj) {
if (isScrollToTop) {
$(obj).show().siblings('.RuoYi_iframe').hide();
} else {
$(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"});
$(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute", "left": "0", "top": "0"});
}
}

View File

@@ -52,7 +52,7 @@ var table = {
toolbar: "toolbar",
loadingFontSize: 13,
striped: false,
escape: false,
escape: true,
firstLoad: true,
showFooter: false,
search: false,
@@ -260,7 +260,6 @@ var table = {
type: 1,
closeBtn: true,
shadeClose: true,
area: ['auto', 'auto'],
content: "<img src='" + src + "' height='" + height + "' width='" + width + "'/>"
});
} else if ($.common.equals("blank", target)) {
@@ -920,6 +919,7 @@ var table = {
fix: false,
area: [_width + 'px', _height + 'px'],
content: _url,
closeBtn: $.common.isEmpty(options.closeBtn) ? 1 : options.closeBtn,
shadeClose: $.common.isEmpty(options.shadeClose) ? true : options.shadeClose,
skin: options.skin,
// options.btn设置为0表示不显示按钮

View File

@@ -128,7 +128,8 @@
$("#datetimepicker-demo-2").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
autoclose: true,
clearBtn:true
});
$("#datetimepicker-demo-3").datetimepicker({

View File

@@ -17,7 +17,7 @@
<h2>若依后台管理系统</h2>
<p>ruoyi是一个完全响应式基于Bootstrap3.3.7最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.7.9
<b>当前版本:</b>v4.8.0
</p>
<p>
<span class="label label-warning">免费开源</span>
@@ -56,7 +56,7 @@
<h3>你好,若依 </h3>
<p>H+是一个完全响应式基于Bootstrap3.3.7最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.7.9
<b>当前版本:</b>v4.8.0
</p>
<p>
<span class="label label-warning">开源免费</span>

View File

@@ -38,7 +38,16 @@
},
{
field : 'userName',
title : '用户姓名'
title : '用户姓名',
cellStyle: function (value, row, index) {
return { css: { "min-width": "100px", "white-space": "nowrap", "text-overflow": "ellipsis", "overflow": "hidden", "max-width": "200px" } }
},
formatter: function(value, row, index) {
if (index == 0) {
value = value + ",测试用户姓名,这是一条长文本,可以通过拖拽自适应内容显示。。。。";
}
return $.table.tooltip(value, 30, "open");
}
},
{
field : 'userPhone',

View File

@@ -12,7 +12,7 @@
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.22.6}" rel="stylesheet"/>
<link th:href="@{/css/animate.min.css?v=20210831}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css?v=20210831}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
</head>
<!-- 通用JS -->
@@ -26,9 +26,9 @@
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=1.22.6}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js?v=1.22.6}"></script>
<!-- jquery-validate 表单验证插件 -->
<script th:src="@{/ajax/libs/validate/jquery.validate.min.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/jquery.validate.min.js?v=1.21.0}"></script>
<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.21.0}"></script>
<script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.21.0}"></script>
<!-- bootstrap-table 表格树插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.22.6}"></script>
<!-- 遮罩层 -->
@@ -36,8 +36,8 @@
<script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js?v=3.7.0}"></script>
<script th:src="@{/ajax/libs/layui/layui.min.js?v=2.8.18}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
</div>
<!-- ztree树插件 -->

View File

@@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css?v=20200902}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
<style type="text/css">.fixed-sidebar .nav:not(.navbar-toolbar)>li.active{border-left:0px!important;}</style>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
@@ -321,8 +321,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:src="@{/js/resize-tabs.js}"></script>

View File

@@ -14,7 +14,7 @@
<link th:href="@{/css/animate.min.css}" rel="stylesheet"/>
<link th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
<div id="wrapper">
@@ -267,8 +267,8 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
<script th:src="@{/ruoyi/index.js?v=20201208}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:inline="javascript">

View File

@@ -38,7 +38,7 @@
<script src="../static/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script>
<script src="../static/js/three.min.js" th:src="@{/js/three.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
</body>
<script th:inline="javascript">
var ctx = [[@{/}]];

View File

@@ -9,7 +9,7 @@
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@@ -76,7 +76,7 @@
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
</body>
</html>

View File

@@ -79,7 +79,7 @@
<div class="ibox-content">
<p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
</p>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <s>满101526938</s> <s>满264355400</s> <s>满298522656</s> <s>满139845794</s> <s>满185760789</s> <s>满175104288</s> <s>满174942938</s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737" target="_blank">287843737</a>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <s>满339522636</s> <s>满130035985</s> <s>满143151071</s> <s>满158781320</s> <s>满201531282</s> <s>满101526938</s> <s>满264355400</s> <s>满298522656</s> <s>满139845794</s> <s>满185760789</s> <s>满175104288</s> <s>满174942938</s> <s>满287843737</s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766" target="_blank">232896766</a>
</p>
<p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
</p>
@@ -96,13 +96,52 @@
<div class="ibox-content no-padding">
<div class="panel-body">
<div class="panel-group" id="version">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v480">v4.8.0</a><code class="pull-right">2024.12.26</code>
</h5>
</div>
<div id="v480" class="panel-collapse collapse in">
<div class="panel-body">
<ol>
<li>支持自定义显示Excel属性列</li>
<li>表格默认转义HTML字符串</li>
<li>新增列宽拖动长内容自适应显示示例</li>
<li>Excel注解支持wrapText是否允许内容换行</li>
<li>代码生成新增配置是否允许文件覆盖到本地</li>
<li>升级oshi到最新版本6.6.5</li>
<li>升级tomcat到最新版本9.0.96</li>
<li>升级logback到最新版本1.2.13</li>
<li>升级commons.io到最新版本2.16.1</li>
<li>升级spring-framework到最新版本5.3.39</li>
<li>升级jquery.validate到最新版本v1.21.0</li>
<li>优化导入带标题文件关闭清理</li>
<li>代码生成创建表屏蔽违规的字符</li>
<li>修复主子表数据显示问题</li>
<li>修复记住我请求头过大的问题</li>
<li>修复角色禁用权限不失效问题</li>
<li>修复类匿名注解访问失效问题</li>
<li>修复导出子列表对象只能在最后的问题</li>
<li>修复多选下拉框open导致页签空白问题</li>
<li>优化身份证脱敏正则</li>
<li>优化查询时间范围日期格式</li>
<li>优化异步树表格折叠同步子状态</li>
<li>优化时间控件清除按钮样式问题</li>
<li>优化表格图片预览动态路径显示问题</li>
<li>优化select2下拉框必填背景色无法清空问题</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v479">v4.7.9</a><code class="pull-right">2024.06.06</code>
</h5>
</div>
<div id="v479" class="panel-collapse collapse in">
<div id="v479" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<li>通知公告新增详细显示</li>

View File

@@ -9,7 +9,7 @@
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.8.0}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
@@ -75,7 +75,7 @@
<script src="../static/ajax/libs/validate/jquery.validate.extend.js" th:src="@{/ajax/libs/validate/jquery.validate.extend.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
<script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script>
</body>
</html>

View File

@@ -140,7 +140,7 @@
</ul>
</body>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.8.0}"></script>
<script type="text/javascript">
//皮肤样式列表
var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];

View File

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

View File

@@ -83,6 +83,11 @@ public @interface Excel
*/
public String prompt() default "";
/**
* 是否允许内容换行
*/
public boolean wrapText() default false;
/**
* 设置只能选择不能输入的列内容.
*/

View File

@@ -21,6 +21,9 @@ public class UserConstants
/** 用户封禁状态 */
public static final String USER_DISABLE = "1";
/** 角色正常状态 */
public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */
public static final String ROLE_DISABLE = "1";

View File

@@ -25,14 +25,14 @@ public class BaseEntity implements Serializable
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
/** 备注 */

View File

@@ -23,7 +23,7 @@ public enum DesensitizedType
/**
* 身份证中间10位星号替换
*/
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
/**
* 手机号中间4位星号替换

View File

@@ -36,4 +36,32 @@ public class ExceptionUtil
}
return StringUtils.defaultString(msg);
}
/**
* 检测异常e被触发的原因是不是因为异常cause。
*
* @param e 捕获的异常。
* @param cause 异常触发原因。
* @return 如果异常e是由cause类异常触发则返回true否则返回false。
*/
public static boolean isCausedBy(final Throwable e, final Class<? extends Throwable> cause)
{
if (cause.isAssignableFrom(e.getClass()))
{
return true;
}
else
{
Throwable t = e.getCause();
while (t != null && t != e)
{
if (cause.isAssignableFrom(t.getClass()))
{
return true;
}
t = t.getCause();
}
return false;
}
}
}

View File

@@ -25,7 +25,7 @@ public class FileUploadUtils
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 默认的文件名最大长度 100

View File

@@ -194,6 +194,11 @@ public class ExcelUtil<T>
*/
public Class<T> clazz;
/**
* 需要显示列属性
*/
public String[] includeFields;
/**
* 需要排除列属性
*/
@@ -204,11 +209,20 @@ public class ExcelUtil<T>
this.clazz = clazz;
}
/**
* 仅在Excel中显示列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
*/
public void showColumn(String... fields)
{
this.includeFields = fields;
}
/**
* 隐藏Excel中列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
* @throws Exception
*/
public void hideColumn(String... fields)
{
@@ -238,8 +252,6 @@ public class ExcelUtil<T>
{
if (StringUtils.isNotEmpty(title))
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1;
if (isSubList())
{
@@ -250,7 +262,7 @@ public class ExcelUtil<T>
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
}
}
@@ -261,23 +273,31 @@ public class ExcelUtil<T>
{
if (isSubList())
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum);
int excelNum = 0;
int column = 0;
int subFieldSize = subFields != null ? subFields.size() : 0;
for (Object[] objects : fields)
{
Field field = (Field) objects[0];
Excel attr = (Excel) objects[1];
Cell headCell1 = subRow.createCell(excelNum);
headCell1.setCellValue(attr.name());
headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
excelNum++;
}
int headFirstRow = excelNum - 1;
int headLastRow = headFirstRow + subFields.size() - 1;
if (headLastRow > headFirstRow)
{
sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
if (Collection.class.isAssignableFrom(field.getType()))
{
Cell cell = subRow.createCell(column);
cell.setCellValue(attr.name());
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
if (subFieldSize > 1)
{
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
sheet.addMergedRegion(cellAddress);
}
column += subFieldSize;
}
else
{
Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name());
cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
}
}
rownum++;
}
@@ -290,11 +310,23 @@ public class ExcelUtil<T>
* @return 转换后集合
*/
public List<T> importExcel(InputStream is)
{
return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum)
{
List<T> list = null;
try
{
list = importExcel(is, 0);
list = importExcel(StringUtils.EMPTY, is, titleNum);
}
catch (Exception e)
{
@@ -308,18 +340,6 @@ public class ExcelUtil<T>
return list;
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
/**
* 对excel表单指定表格索引名转换成list
*
@@ -711,64 +731,91 @@ public class ExcelUtil<T>
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
int rowNo = (1 + rownum) - startNo;
int currentRowNum = rownum + 1; // 从标题行后开始
for (int i = startNo; i < endNo; i++)
{
rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
row = sheet.createRow(rowNo);
// 得到导出对象.
row = sheet.createRow(currentRowNum);
T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
if (Collection.class.isAssignableFrom(field.getType()))
{
boolean subFirst = false;
for (Object obj : subList)
try
{
if (subFirst)
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
if (subList != null && !subList.isEmpty())
{
rowNo++;
row = sheet.createRow(rowNo);
}
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
int subIndex = 0;
for (Object subVo : subList)
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
Row subRow = sheet.getRow(currentRowNum + subIndex);
if (subRow == null)
{
subRow = sheet.createRow(currentRowNum + subIndex);
}
int subColumn = column;
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
}
subIndex++;
}
subIndex++;
column += subFields.size();
}
subFirst = true;
}
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
catch (Exception e)
{
log.error("填充集合数据失败", e);
}
}
else
{
this.addCell(excel, row, vo, field, column++);
// 创建单元格并设置值
addCell(excel, row, vo, field, column);
if (maxSubListSize > 1 && excel.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
}
column++;
}
}
currentRowNum += maxSubListSize;
}
}
/**
* 获取子列表最大数
*/
private int getCurrentMaxSubListSize(T vo)
{
int maxSubListSize = 1;
for (Object[] os : fields)
{
Field field = (Field) os[0];
if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
if (subList != null && !subList.isEmpty())
{
maxSubListSize = Math.max(maxSubListSize, subList.size());
}
}
catch (Exception e)
{
log.error("获取集合大小失败", e);
}
}
}
return maxSubListSize;
}
/**
@@ -903,7 +950,7 @@ public class ExcelUtil<T>
*/
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{
String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
@@ -919,6 +966,7 @@ public class ExcelUtil<T>
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex());
style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
@@ -947,7 +995,7 @@ public class ExcelUtil<T>
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -1085,10 +1133,12 @@ public class ExcelUtil<T>
cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
if (subMergedLastRowNum >= subMergedFirstRowNum)
{
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
}
}
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
@@ -1429,6 +1479,7 @@ public class ExcelUtil<T>
*/
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{
field.setAccessible(true);
Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr()))
{
@@ -1488,46 +1539,83 @@ public class ExcelUtil<T>
List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields)
if (StringUtils.isNotEmpty(includeFields))
{
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
for (Field field : tempFields)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
addField(fields, field);
}
}
}
else if (StringUtils.isNotEmpty(excludeFields))
{
for (Field field : tempFields)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{
addField(fields, field);
}
}
}
else
{
for (Field field : tempFields)
{
addField(fields, field);
}
}
return fields;
}
/**
* 添加字段信息
*/
public void addField(List<Object[]> fields, Field field)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (StringUtils.isNotEmpty(includeFields))
{
if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
else
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
fields.add(new Object[] { field, attr });
}
}
}
}
return fields;
}
/**

View File

@@ -13,7 +13,7 @@ public class SqlUtil
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)

View File

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

View File

@@ -7,6 +7,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.context.PermissionContextHolder;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
@@ -71,8 +72,7 @@ public class DataScopeAspect
if (!currentUser.isAdmin())
{
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), permission);
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
}
}
}
@@ -92,7 +92,7 @@ public class DataScopeAspect
List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
}
@@ -101,7 +101,7 @@ public class DataScopeAspect
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (conditions.contains(dataScope))
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
{
continue;
}
@@ -150,7 +150,7 @@ public class DataScopeAspect
conditions.add(dataScope);
}
// 多角色情况下,所有角色都不包含传递过来的权限字符这个时候sqlString也会为空所以要限制一下,不查询任何数据
// 角色都不包含传递过来的权限字符这个时候sqlString也会为空所以要限制一下,不查询任何数据
if (StringUtils.isEmpty(conditions))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));

View File

@@ -15,7 +15,6 @@ import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -28,6 +27,7 @@ import com.ruoyi.common.utils.security.CipherUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.rememberMe.CustomCookieRememberMeManager;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
@@ -369,9 +369,9 @@ public class ShiroConfig
/**
* 记住我
*/
public CookieRememberMeManager rememberMeManager()
public CustomCookieRememberMeManager rememberMeManager()
{
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
CustomCookieRememberMeManager cookieRememberMeManager = new CustomCookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
if (StringUtils.isNotEmpty(cipherKey))
{

View File

@@ -37,52 +37,74 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(Controller.class);
for (Object bean : controllers.values())
{
if (!(bean instanceof Advised))
Class<?> beanClass;
if (bean instanceof Advised)
{
continue;
beanClass = ((Advised) bean).getTargetSource().getTarget().getClass();
}
Class<?> beanClass = ((Advised) bean).getTargetSource().getTarget().getClass();
RequestMapping base = beanClass.getAnnotation(RequestMapping.class);
String[] baseUrl = {};
if (Objects.nonNull(base))
else
{
baseUrl = base.value();
beanClass = bean.getClass();
}
Method[] methods = beanClass.getDeclaredMethods();
for (Method method : methods)
// 处理类级别的匿名访问注解
if (beanClass.isAnnotationPresent(Anonymous.class))
{
if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(RequestMapping.class))
RequestMapping baseMapping = beanClass.getAnnotation(RequestMapping.class);
if (Objects.nonNull(baseMapping))
{
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(GetMapping.class))
{
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(PostMapping.class))
{
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(PutMapping.class))
{
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(DeleteMapping.class))
{
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
String[] baseUrl = baseMapping.value();
for (String url : baseUrl)
{
urls.add(prefix(url) + "/*");
}
continue;
}
}
// 处理方法级别的匿名访问注解
Method[] methods = beanClass.getDeclaredMethods();
for (Method method : methods)
{
if (method.isAnnotationPresent(Anonymous.class))
{
RequestMapping baseMapping = beanClass.getAnnotation(RequestMapping.class);
String[] baseUrl = {};
if (Objects.nonNull(baseMapping))
{
baseUrl = baseMapping.value();
}
if (method.isAnnotationPresent(RequestMapping.class))
{
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(GetMapping.class))
{
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(PostMapping.class))
{
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(PutMapping.class))
{
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
else if (method.isAnnotationPresent(DeleteMapping.class))
{
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
String[] uri = requestMapping.value();
urls.addAll(rebuildUrl(baseUrl, uri));
}
}
}
}
}
@@ -91,9 +113,16 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
List<String> urls = new ArrayList<>();
for (String base : bases)
{
for (String uri : uris)
if (uris.length > 0)
{
urls.add(prefix(base) + prefix(uri));
for (String uri : uris)
{
urls.add(prefix(base) + prefix(uri));
}
}
else
{
urls.add(prefix(base));
}
}
return urls;

View File

@@ -0,0 +1,79 @@
package com.ruoyi.framework.shiro.rememberMe;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.shiro.service.SysLoginService;
/**
* 自定义CookieRememberMeManager
*
* @author ruoyi
*/
public class CustomCookieRememberMeManager extends CookieRememberMeManager
{
/**
* 记住我时去掉角色的permissions权限字符串防止http请求头过大。
*/
@Override
protected void rememberIdentity(Subject subject, PrincipalCollection principalCollection)
{
Map<SysRole, Set<String>> rolePermissions = new HashMap<>();
// 清除角色的permissions权限字符串
for (Object principal : principalCollection)
{
if (principal instanceof SysUser)
{
List<SysRole> roles = ((SysUser) principal).getRoles();
for (SysRole role : roles)
{
rolePermissions.put(role, role.getPermissions());
role.setPermissions(null);
}
}
}
byte[] bytes = convertPrincipalsToBytes(principalCollection);
// 恢复角色的permissions权限字符串
for (Object principal : principalCollection)
{
if (principal instanceof SysUser)
{
List<SysRole> roles = ((SysUser) principal).getRoles();
for (SysRole role : roles)
{
role.setPermissions(rolePermissions.get(role));
}
}
}
rememberSerializedIdentity(subject, bytes);
}
/**
* 取记住我身份时恢复角色permissions权限字符串。
*/
@Override
public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext)
{
PrincipalCollection principals = super.getRememberedPrincipals(subjectContext);
if (principals == null || principals.isEmpty())
{
return principals;
}
for (Object principal : principals)
{
if (principal instanceof SysUser)
{
SpringUtils.getBean(SysLoginService.class).setRolePermission((SysUser) principal);
}
}
return principals;
}
}

View File

@@ -163,8 +163,11 @@ public class SysLoginService
// 设置permissions属性以便数据权限匹配权限
for (SysRole role : roles)
{
Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL))
{
Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
}
}
}
}

View File

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

View File

@@ -21,12 +21,15 @@ public class GenConfig
/** 生成包路径 */
public static String packageName;
/** 自动去除表前缀默认是false */
/** 自动去除表前缀 */
public static boolean autoRemovePre;
/** 表前缀(类名不会包含表前缀) */
/** 表前缀 */
public static String tablePrefix;
/** 是否允许生成文件覆盖到本地(自定义路径) */
public static boolean allowOverwrite;
public static String getAuthor()
{
return author;
@@ -70,4 +73,15 @@ public class GenConfig
{
GenConfig.tablePrefix = tablePrefix;
}
public static boolean isAllowOverwrite()
{
return allowOverwrite;
}
@Value("${allowOverwrite}")
public void setAllowOverwrite(boolean allowOverwrite)
{
GenConfig.allowOverwrite = allowOverwrite;
}
}

View File

@@ -32,6 +32,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.PermissionUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
import com.ruoyi.generator.config.GenConfig;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.service.IGenTableColumnService;
@@ -259,6 +260,10 @@ public class GenController extends BaseController
@ResponseBody
public AjaxResult genCode(@PathVariable("tableName") String tableName)
{
if (!GenConfig.isAllowOverwrite())
{
return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
}
genTableService.generatorCode(tableName);
return AjaxResult.success();
}

View File

@@ -8,4 +8,6 @@ gen:
# 自动去除表前缀默认是false
autoRemovePre: false
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
tablePrefix: sys_
tablePrefix: sys_
# 是否允许生成文件覆盖到本地(自定义路径),默认不允许
allowOverwrite: false

View File

@@ -26,7 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
<collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
</resultMap>
<resultMap type="GenTableColumn" id="GenTableColumnResult">
@@ -67,13 +67,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
</if>
<if test="params.beginTime != null and params.beginTime != ''">
and date_format(create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''">
and date_format(create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
</where>
</select>
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_schema = (select database())
AND table_name NOT LIKE 'QRTZ_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT LIKE 'qrtz\_%' AND table_name NOT LIKE 'gen\_%'
AND table_name NOT IN (select table_name from gen_table)
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
@@ -86,7 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectDbTableListByNames" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
where table_name NOT LIKE 'qrtz\_%' and table_name NOT LIKE 'gen\_%' and table_schema = (select database())
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
@@ -158,12 +164,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sysdate()
)
</insert>
<update id="createTable">
<update id="createTable">
${sql}
</update>
<update id="updateGenTable" parameterType="GenTable">
</update>
<update id="updateGenTable" parameterType="GenTable">
update gen_table
<set>
<if test="tableName != null">table_name = #{tableName},</if>

View File

@@ -40,7 +40,7 @@ public class ${ClassName} extends ${Entity}
#if($parentheseIndex != -1)
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
#elseif($column.javaType == 'Date')
@JsonFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
#else
@Excel(name = "${comment}")

View File

@@ -31,7 +31,7 @@ public class ${subClassName} extends BaseEntity
#if($parentheseIndex != -1)
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
#elseif($column.javaType == 'Date')
@JsonFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
#else
@Excel(name = "${comment}")

View File

@@ -15,7 +15,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#if($table.sub)
<resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
<collection property="${subclassName}List" ofType="${subClassName}" column="${subTableFkName}" select="select${subClassName}List" />
<collection property="${subclassName}List" ofType="${subClassName}" column="${pkColumn.columnName}" select="select${subClassName}List" />
</resultMap>
<resultMap type="${subClassName}" id="${subClassName}Result">
@@ -81,7 +81,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
#if($table.sub)
<select id="select${subClassName}List" resultType="${subClassName}" resultMap="${subClassName}Result">
<select id="select${subClassName}List" resultMap="${subClassName}Result">
select#foreach ($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
from ${subTableName}
where ${subTableFkName} = #{${subTableFkName}}

View File

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

View File

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

View File

@@ -1131,7 +1131,7 @@
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.8.0}"></script>
<script th:src="@{/js/cron.js}"></script>
<script th:inline="javascript">
var prefix = [[@{/}]] + "monitor/job";

View File

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

View File

@@ -42,7 +42,7 @@ public class SysUserOnline extends BaseEntity
/** session最后访问时间 */
private Date lastAccessTime;
/** 超时时间,单位为分钟 */
/** 超时时间,单位为毫秒 */
private Long expireTime;
/** 在线状态 */

View File

@@ -3,6 +3,7 @@ package com.ruoyi.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,9 +17,11 @@ import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.html.EscapeUtil;
import com.ruoyi.common.utils.security.Md5Utils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysPost;
@@ -529,7 +532,12 @@ public class SysUserServiceImpl implements ISysUserService
catch (Exception e)
{
failureNum++;
String msg = "<br/>" + failureNum + "、账号 " + user.getLoginName() + " 导入失败:";
String loginName = user.getLoginName();
if (ExceptionUtil.isCausedBy(e, ConstraintViolationException.class))
{
loginName = EscapeUtil.clean(loginName);
}
String msg = "<br/>" + failureNum + "、账号 " + loginName + " 导入失败:";
failureMsg.append(msg + e.getMessage());
log.error(msg, e);
}

View File

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

View File

@@ -40,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</select>
<select id="selectDictDataByType" parameterType="SysDictData" resultMap="SysDictDataResult">
<select id="selectDictDataByType" parameterType="String" resultMap="SysDictDataResult">
<include refid="selectDictDataVo"/>
where status = '0' and dict_type = #{dictType} order by dict_sort asc
</select>

View File

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

View File

@@ -52,10 +52,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND r.data_scope = #{dataScope}
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(r.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
and date_format(r.create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
and date_format(r.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}

View File

@@ -76,10 +76,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
AND date_format(u.create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
AND date_format(u.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET (#{deptId},ancestors) ))