Compare commits
77 Commits
v4.7.8
...
springboot
Author | SHA1 | Date | |
---|---|---|---|
f92c573936 | |||
edbc074351 | |||
90dab826bf | |||
69020cfc50 | |||
c122c21b95 | |||
38583efa51 | |||
a7fa724fc3 | |||
428c9aa5eb | |||
05e2c28343 | |||
60a6765f09 | |||
76fb2cf1f8 | |||
96bf7d5c17 | |||
1324818e46 | |||
ba00eea7d4 | |||
75946b4ebc | |||
e286718a1b | |||
40b2bb4c46 | |||
6096bb5e05 | |||
00e2fab203 | |||
c65919c600 | |||
0a6ff25875 | |||
c22d0af018 | |||
e33e13d3b4 | |||
32e448b6b4 | |||
116bed00a5 | |||
4f5bf990bf | |||
0144cb855f | |||
e8f9bfb5c6 | |||
56b1354496 | |||
8e1a89bcbe | |||
4c9bfd8683 | |||
ec6d84aa88 | |||
05c29a2a6c | |||
18ef1ea816 | |||
3c574b45dc | |||
0e08cc7ca4 | |||
b2d832edab | |||
60889185d8 | |||
b95280aba2 | |||
96b2c0d9b7 | |||
f0efa914fe | |||
edb1c614d0 | |||
61c2e96aaa | |||
f31e6bd1bb | |||
f5805fd79e | |||
55913e8707 | |||
45f71a5125 | |||
4218cf7cfd | |||
4963454f23 | |||
85cf318a94 | |||
82a0eaed4a | |||
f6ce55be47 | |||
fd37e8b4a7 | |||
d43fea60e2 | |||
05075e21a3 | |||
f2f6b25ed2 | |||
4a5ea50a14 | |||
81c1ffb07e | |||
6dd8bbfc38 | |||
bcb6222c61 | |||
0ce40fc039 | |||
0cde5c2446 | |||
69714747d7 | |||
83b90c3267 | |||
5b19d33af9 | |||
c8fd0b0470 | |||
8c8d53a9cc | |||
f84b77993c | |||
192c0c5241 | |||
92d121175d | |||
d6e599d6ac | |||
a4c8026265 | |||
90022df5a6 | |||
0699c2350a | |||
fd4fe83e9f | |||
4933ea6d2f | |||
07ddbfeabf |
@ -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.8</h1>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.9</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.8-brightgreen.svg"></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/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||
</p>
|
||||
|
||||
@ -99,4 +99,4 @@
|
||||
|
||||
## 若依交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR)
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766)
|
84
pom.xml
84
pom.xml
@ -5,49 +5,50 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>4.7.8</version>
|
||||
<version>4.7.9</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>4.7.8</ruoyi.version>
|
||||
<ruoyi.version>4.7.9</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<shiro.version>1.13.0</shiro.version>
|
||||
<shiro.version>2.0.1</shiro.version>
|
||||
<mybatis-spring-boot.version>3.0.3</mybatis-spring-boot.version>
|
||||
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
|
||||
<druid.version>1.2.20</druid.version>
|
||||
<druid.version>1.2.23</druid.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
<kaptcha.version>2.3.3</kaptcha.version>
|
||||
<swagger.version>3.0.0</swagger.version>
|
||||
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
|
||||
<pagehelper.boot.version>2.1.0</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<oshi.version>6.4.7</oshi.version>
|
||||
<commons.io.version>2.11.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>
|
||||
<springdoc.version>2.6.0</springdoc.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- SpringBoot的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.5.15</version>
|
||||
<version>3.3.5</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
@ -62,6 +63,14 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
@ -69,7 +78,15 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
<version>${shiro.version}</version>
|
||||
<!-- 排除仍使用了javax.servlet的依赖 -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
@ -86,6 +103,25 @@
|
||||
<version>${thymeleaf.extras.shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${mybatis-spring-boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
@ -107,17 +143,11 @@
|
||||
<version>${oshi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger3依赖 -->
|
||||
<!-- spring-doc -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-boot-starter</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
@ -206,13 +236,19 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<parameters>true</parameters>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.7.8</version>
|
||||
<version>4.7.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
@ -30,23 +30,16 @@
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
|
||||
<!-- swagger3-->
|
||||
<!-- spring-doc -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
@ -89,7 +82,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warName>${project.artifactId}</warName>
|
||||
@ -123,6 +116,7 @@
|
||||
<exclude>**/*.min.js</exclude>
|
||||
<exclude>**/*.min.css</exclude>
|
||||
<exclude>**/fileinput.js</exclude>
|
||||
<exclude>**/validate/**</exclude>
|
||||
<exclude>**/bootstrap-table/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
|
@ -2,8 +2,8 @@ package com.ruoyi.web.controller.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -16,6 +16,7 @@ import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.annotation.Excel.ColumnType;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
@ -125,6 +126,22 @@ public class DemoTableController extends BaseController
|
||||
columns.add(new UserTableColumn("用户邮箱", "userEmail"));
|
||||
columns.add(new UserTableColumn("用户状态", "status"));
|
||||
}
|
||||
|
||||
private final static List<DocumentModel> documents = new ArrayList<DocumentModel>();
|
||||
{
|
||||
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", "《黑神话》让海外玩家迷上“悟空”", "备受全球玩家瞩目的首款国产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万元起。"));
|
||||
documents.add(new DocumentModel(9, "CT01-XW·2024-D10-0009", "新闻热线[2024]000009", "华为手机归来,谁最受伤?", "低迷周期下的智能手机市场在2023年下半年迎来了华为的回归,这也给本就竞争激烈的市场环境带来了更大变数。1月29日,有消息称,华为已注册“星耀手机”品牌商标,定位中端手机市场,但上述消息并未获得华为方面确认。“目前星耀的相关信息我们看到了,但是没有获得产品信息以及启动线下铺货的通知。对于和其他品牌的二选一问题,听其他省份的经销商说过,但目前(华为渠道)这边也没有更多动作。”一位广东区域的华为核心经销商对记者说。但华为手机的反扑已经开始。在多家调研机构公布的2023年四季度智能手机出货数据中,华为手机的量正在明显上升,当季增幅在35%到47%之间。不过,从全年数据来看,并未登上前五榜单。"));
|
||||
documents.add(new DocumentModel(10, "CT01-XW·2024-D10-0010", "新闻热线[2024]000010", "疯狂裁员的硅谷大厂:除了AI,其它都是将就", "放眼望去,近期科技企业财报形势一片大好,裁员浪潮却仍在不断蔓延。国内职场动态看脉脉,那硅谷裁员情况就得看layoff.fyi了。数据显示,2024年,103家科技企业进行了裁员,28963位员工失去了饭碗。其中,电子支付公司PayPal大笔一挥,裁掉2500人,微软则在开年就裁掉1900人。回望2023年,谷歌、Meta、亚马逊、微软均为裁员重灾区,裁员人数在一万左右。具体而言,谷歌近日披露的财报指出,2023年谷歌解雇了12000多名员工,光是在遣散费和其他费用上就花费了21亿美元。而且裁员费用还在不断增加,2024年刚过去一个月,谷歌就已经花费了7亿美元用来裁员。"));
|
||||
documents.add(new DocumentModel(11, "CT01-XW·2024-D30-0011", "新闻热线[2024]000011", "国产手机品牌重新崛起背后:市场正在逐步恢复活力,竞争也愈发激烈", "2024年伊始,随着全球经济的逐渐复苏,手机消费市场也展现出勃勃生机。中国信通院最新数据显示,2023年中国市场手机出货量实现了6.5%的同比增长,其中5G手机增长势头更为强劲,占比高达82.8%。1月25日,国际数据公司(IDC)发布了最新手机季度跟踪报告,揭示了中国智能手机市场在2023年第四季度的出货量情况。报告显示,该季度中国智能手机市场出货量达到了约7363万台,同比增长1.2%。这是在连续十个季度同比下降后,中国智能手机市场首次实现反弹。这一积极信号表明,市场正在逐步恢复活力,各大品牌之间的竞争也愈发激烈。"));
|
||||
documents.add(new DocumentModel(12, "CT01-XW·2024-D30-0012", "新闻热线[2024]000012", "SpaceX将于1月31日向国际空间站发射天鹅号货运飞船", "1月29日消息,美国太空探索技术公司SpaceX计划于当地时间1月30日,利用“猎鹰9号”火箭从佛罗里达州肯尼迪航天中心发射诺斯罗普·格鲁曼公司的“天鹅号”货运飞船至国际空间站。此次任务是执行NG-20商业补给,将运送约8200多磅的物资、设备及科学实验器材。"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索相关
|
||||
@ -209,6 +226,15 @@ public class DemoTableController extends BaseController
|
||||
return prefix + "/remember";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格保存状态
|
||||
*/
|
||||
@GetMapping("/cookie")
|
||||
public String cookie()
|
||||
{
|
||||
return prefix + "/cookie";
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至指定页
|
||||
*/
|
||||
@ -390,6 +416,15 @@ public class DemoTableController extends BaseController
|
||||
return prefix + "/dynamicColumns";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格虚拟滚动
|
||||
*/
|
||||
@GetMapping("/virtualScroll")
|
||||
public String virtualScroll()
|
||||
{
|
||||
return prefix + "/virtualScroll";
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义视图分页
|
||||
*/
|
||||
@ -399,6 +434,15 @@ public class DemoTableController extends BaseController
|
||||
return prefix + "/customView";
|
||||
}
|
||||
|
||||
/**
|
||||
* 全文索引
|
||||
*/
|
||||
@GetMapping("/textSearch")
|
||||
public String textSearch()
|
||||
{
|
||||
return prefix + "/textSearch";
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步加载表格树
|
||||
*/
|
||||
@ -473,6 +517,57 @@ public class DemoTableController extends BaseController
|
||||
return rspData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全文索引数据
|
||||
*/
|
||||
@PostMapping("/text/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo textList(BaseEntity baseEntity)
|
||||
{
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
List<DocumentModel> documentList = new ArrayList<DocumentModel>(Arrays.asList(new DocumentModel[documents.size()]));
|
||||
Collections.copy(documentList, documents);
|
||||
// 查询条件过滤
|
||||
if (StringUtils.isNotEmpty(baseEntity.getSearchValue()))
|
||||
{
|
||||
documentList.clear();
|
||||
for (DocumentModel document : documents)
|
||||
{
|
||||
boolean indexFlag = false;
|
||||
if (document.getTitle().contains(baseEntity.getSearchValue()))
|
||||
{
|
||||
indexFlag = true;
|
||||
document.setTitle(document.getTitle().replace(baseEntity.getSearchValue(), "<font color=\"red\">" + baseEntity.getSearchValue() + "</font>"));
|
||||
}
|
||||
if (document.getContent().contains(baseEntity.getSearchValue()))
|
||||
{
|
||||
indexFlag = true;
|
||||
document.setContent(document.getContent().replace(baseEntity.getSearchValue(), "<font color=\"red\">" + baseEntity.getSearchValue() + "</font>"));
|
||||
}
|
||||
if (indexFlag)
|
||||
{
|
||||
documentList.add(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
|
||||
{
|
||||
rspData.setRows(documentList);
|
||||
rspData.setTotal(documentList.size());
|
||||
return rspData;
|
||||
}
|
||||
Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
|
||||
Integer pageSize = pageDomain.getPageNum() * 10;
|
||||
if (pageSize > documentList.size())
|
||||
{
|
||||
pageSize = documentList.size();
|
||||
}
|
||||
rspData.setRows(documentList.subList(pageNum, pageSize));
|
||||
rspData.setTotal(documentList.size());
|
||||
return rspData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询树表数据
|
||||
*/
|
||||
@ -844,3 +939,85 @@ class AreaModel
|
||||
this.isTreeLeaf = isTreeLeaf;
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentModel
|
||||
{
|
||||
/** 编号 */
|
||||
private int tableId;
|
||||
|
||||
/** 档号 */
|
||||
private String archiveNo;
|
||||
|
||||
/** 文件编号 */
|
||||
private String docNo;
|
||||
|
||||
/** 标题 */
|
||||
private String title;
|
||||
|
||||
/** 内容 */
|
||||
private String content;
|
||||
|
||||
public DocumentModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentModel(int tableId, String archiveNo, String docNo, String title, String content)
|
||||
{
|
||||
this.tableId = tableId;
|
||||
this.archiveNo = archiveNo;
|
||||
this.docNo = docNo;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public int getTableId()
|
||||
{
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public String getArchiveNo()
|
||||
{
|
||||
return archiveNo;
|
||||
}
|
||||
|
||||
public String getDocNo()
|
||||
{
|
||||
return docNo;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getContent()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setTableId(int tableId)
|
||||
{
|
||||
this.tableId = tableId;
|
||||
}
|
||||
|
||||
public void setArchiveNo(String archiveNo)
|
||||
{
|
||||
this.archiveNo = archiveNo;
|
||||
}
|
||||
|
||||
public void setDocNo(String docNo)
|
||||
{
|
||||
this.docNo = docNo;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setContent(String content)
|
||||
{
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,12 @@ package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -2,8 +2,8 @@ package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
@ -99,6 +99,17 @@ public class SysNoticeController extends BaseController
|
||||
return toAjax(noticeService.updateNotice(notice));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询公告详细
|
||||
*/
|
||||
@RequiresPermissions("system:notice:list")
|
||||
@GetMapping("/view/{noticeId}")
|
||||
public String view(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
|
||||
{
|
||||
mmap.put("notice", noticeService.selectNoticeById(noticeId));
|
||||
return prefix + "/view";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除公告
|
||||
*/
|
||||
|
@ -24,6 +24,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
@ -129,6 +130,8 @@ public class SysUserController extends BaseController
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(@Validated SysUser user)
|
||||
{
|
||||
deptService.checkDeptDataScope(user.getDeptId());
|
||||
roleService.checkRoleDataScope(user.getRoleIds());
|
||||
if (!userService.checkLoginNameUnique(user))
|
||||
{
|
||||
return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
|
||||
@ -143,6 +146,7 @@ public class SysUserController extends BaseController
|
||||
}
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||
user.setPwdUpdateDate(DateUtils.getNowDate());
|
||||
user.setCreateBy(getLoginName());
|
||||
return toAjax(userService.insertUser(user));
|
||||
}
|
||||
@ -187,6 +191,8 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
userService.checkUserAllowed(user);
|
||||
userService.checkUserDataScope(user.getUserId());
|
||||
deptService.checkDeptDataScope(user.getDeptId());
|
||||
roleService.checkRoleDataScope(user.getRoleIds());
|
||||
if (!userService.checkLoginNameUnique(user))
|
||||
{
|
||||
return error("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
|
||||
@ -257,6 +263,7 @@ public class SysUserController extends BaseController
|
||||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||
{
|
||||
userService.checkUserDataScope(userId);
|
||||
roleService.checkRoleDataScope(roleIds);
|
||||
userService.insertUserAuth(userId, roleIds);
|
||||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return success();
|
||||
|
@ -15,19 +15,16 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
/**
|
||||
* swagger 用户测试方法
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api("用户信息管理")
|
||||
@Tag(name = "用户信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/test/user")
|
||||
public class TestController extends BaseController
|
||||
@ -37,19 +34,19 @@ public class TestController extends BaseController
|
||||
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
|
||||
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户列表")
|
||||
|
||||
@Operation(summary = "获取用户列表")
|
||||
@GetMapping("/list")
|
||||
public R<List<UserEntity>> userList()
|
||||
{
|
||||
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
|
||||
return R.ok(userList);
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户详细")
|
||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
||||
|
||||
@Operation(summary = "获取用户详细")
|
||||
@GetMapping("/{userId}")
|
||||
public R<UserEntity> getUser(@PathVariable Integer userId)
|
||||
public R<UserEntity> getUser(@PathVariable(name = "userId")
|
||||
Integer userId)
|
||||
{
|
||||
if (!users.isEmpty() && users.containsKey(userId))
|
||||
{
|
||||
@ -60,14 +57,8 @@ public class TestController extends BaseController
|
||||
return R.fail("用户不存在");
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("新增用户")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
|
||||
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
|
||||
})
|
||||
|
||||
@Operation(summary = "新增用户")
|
||||
@PostMapping("/save")
|
||||
public R<String> save(UserEntity user)
|
||||
{
|
||||
@ -78,10 +69,11 @@ public class TestController extends BaseController
|
||||
users.put(user.getUserId(), user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("更新用户")
|
||||
|
||||
@Operation(summary = "更新用户")
|
||||
@PutMapping("/update")
|
||||
public R<String> update(@RequestBody UserEntity user)
|
||||
public R<String> update(@RequestBody
|
||||
UserEntity user)
|
||||
{
|
||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||
{
|
||||
@ -95,11 +87,11 @@ public class TestController extends BaseController
|
||||
users.put(user.getUserId(), user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("删除用户信息")
|
||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
||||
|
||||
@Operation(summary = "删除用户信息")
|
||||
@DeleteMapping("/{userId}")
|
||||
public R<String> delete(@PathVariable Integer userId)
|
||||
public R<String> delete(@PathVariable(name = "userId")
|
||||
Integer userId)
|
||||
{
|
||||
if (!users.isEmpty() && users.containsKey(userId))
|
||||
{
|
||||
@ -113,26 +105,26 @@ public class TestController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
@ApiModel(value = "UserEntity", description = "用户实体")
|
||||
@Schema(description = "用户实体")
|
||||
class UserEntity
|
||||
{
|
||||
@ApiModelProperty("用户ID")
|
||||
@Schema(title = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("用户名称")
|
||||
|
||||
@Schema(title = "用户名称")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("用户密码")
|
||||
|
||||
@Schema(title = "用户密码")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty("用户手机")
|
||||
|
||||
@Schema(title = "用户手机")
|
||||
private String mobile;
|
||||
|
||||
|
||||
public UserEntity()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public UserEntity(Integer userId, String username, String password, String mobile)
|
||||
{
|
||||
this.userId = userId;
|
||||
@ -140,42 +132,42 @@ class UserEntity
|
||||
this.password = password;
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
|
||||
public Integer getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
|
||||
public void setUserId(Integer userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
public String getMobile()
|
||||
{
|
||||
return mobile;
|
||||
}
|
||||
|
||||
|
||||
public void setMobile(String mobile)
|
||||
{
|
||||
this.mobile = mobile;
|
||||
|
@ -1,17 +1,15 @@
|
||||
package com.ruoyi.web.core.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
|
||||
/**
|
||||
* Swagger2的接口配置
|
||||
@ -21,47 +19,47 @@ import springfox.documentation.spring.web.plugins.Docket;
|
||||
@Configuration
|
||||
public class SwaggerConfig
|
||||
{
|
||||
/** 是否开启swagger */
|
||||
@Value("${swagger.enabled}")
|
||||
private boolean enabled;
|
||||
/** 系统基础配置 */
|
||||
@Autowired
|
||||
private RuoYiConfig ruoyiConfig;
|
||||
|
||||
/**
|
||||
* 创建API
|
||||
* 自定义的 OpenAPI 对象
|
||||
*/
|
||||
@Bean
|
||||
public Docket createRestApi()
|
||||
public OpenAPI customOpenApi()
|
||||
{
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
// 是否启用Swagger
|
||||
.enable(enabled)
|
||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||
.apiInfo(apiInfo())
|
||||
// 设置哪些接口暴露给Swagger展示
|
||||
.select()
|
||||
// 扫描所有有注解的api,用这种方式更灵活
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
// 扫描指定包中的swagger注解
|
||||
//.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
return new OpenAPI().components(new Components()
|
||||
// 设置认证的请求头
|
||||
.addSecuritySchemes("apikey", securityScheme()))
|
||||
.addSecurityItem(new SecurityRequirement().addList("apikey"))
|
||||
.info(getApiInfo());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SecurityScheme securityScheme()
|
||||
{
|
||||
return new SecurityScheme()
|
||||
.type(SecurityScheme.Type.APIKEY)
|
||||
.name("Authorization")
|
||||
.in(SecurityScheme.In.HEADER)
|
||||
.scheme("Bearer");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加摘要信息
|
||||
*/
|
||||
private ApiInfo apiInfo()
|
||||
@SuppressWarnings("static-access")
|
||||
public Info getApiInfo()
|
||||
{
|
||||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder()
|
||||
// 设置标题
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
// 描述
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
// 作者信息
|
||||
.contact(new Contact(RuoYiConfig.getName(), null, null))
|
||||
// 版本
|
||||
.version("版本号:" + RuoYiConfig.getVersion())
|
||||
.build();
|
||||
return new Info()
|
||||
// 设置标题
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
// 描述
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
// 作者信息
|
||||
.contact(new Contact().name(ruoyiConfig.getName()))
|
||||
// 版本
|
||||
.version("版本号:" + ruoyiConfig.getVersion());
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 4.7.8
|
||||
version: 4.7.9
|
||||
# 版权年份
|
||||
copyrightYear: 2023
|
||||
copyrightYear: 2024
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||
@ -127,6 +127,20 @@ shiro:
|
||||
# 是否开启记住我
|
||||
enabled: true
|
||||
|
||||
# Springdoc配置
|
||||
springdoc:
|
||||
api-docs:
|
||||
path: /v3/api-docs
|
||||
swagger-ui:
|
||||
enabled: true
|
||||
path: /swagger-ui.html
|
||||
tags-sorter: alpha
|
||||
group-configs:
|
||||
- group: 'default'
|
||||
display-name: '测试模块'
|
||||
paths-to-match: '/**'
|
||||
packages-to-scan: com.ruoyi.web.controller.tool
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
# 过滤开关
|
||||
@ -135,8 +149,3 @@ xss:
|
||||
excludes: /system/notice/*
|
||||
# 匹配链接
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
|
||||
# Swagger配置
|
||||
swagger:
|
||||
# 是否开启swagger
|
||||
enabled: true
|
||||
|
File diff suppressed because one or more lines are too long
@ -49,8 +49,8 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
<button class="auto-refresh ${this.constants.buttonsClass}
|
||||
${this.options.autoRefreshStatus ? ` ${this.constants.classes.buttonActive}` : ''}"
|
||||
type="button" name="autoRefresh" title="${this.options.formatAutoRefresh()}">
|
||||
${ this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh) : ''}
|
||||
${ this.options.showButtonText ? this.options.formatAutoRefresh() : ''}
|
||||
${this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh) : ''}
|
||||
${this.options.showButtonText ? this.options.formatAutoRefresh() : ''}
|
||||
</button>
|
||||
`,
|
||||
event: this.toggleAutoRefresh
|
||||
|
@ -0,0 +1,606 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||
*/
|
||||
var Utils = $.fn.bootstrapTable.utils
|
||||
var UtilsCookie = {
|
||||
cookieIds: {
|
||||
sortOrder: 'bs.table.sortOrder',
|
||||
sortName: 'bs.table.sortName',
|
||||
sortPriority: 'bs.table.sortPriority',
|
||||
pageNumber: 'bs.table.pageNumber',
|
||||
pageList: 'bs.table.pageList',
|
||||
hiddenColumns: 'bs.table.hiddenColumns',
|
||||
cardView: 'bs.table.cardView',
|
||||
customView: 'bs.table.customView',
|
||||
searchText: 'bs.table.searchText',
|
||||
reorderColumns: 'bs.table.reorderColumns',
|
||||
filterControl: 'bs.table.filterControl',
|
||||
filterBy: 'bs.table.filterBy'
|
||||
},
|
||||
getCurrentHeader (that) {
|
||||
return that.options.height ? that.$tableHeader : that.$header
|
||||
},
|
||||
getCurrentSearchControls (that) {
|
||||
return that.options.height ? 'table select, table input' : 'select, input'
|
||||
},
|
||||
isCookieSupportedByBrowser () {
|
||||
return navigator.cookieEnabled
|
||||
},
|
||||
isCookieEnabled (that, cookieName) {
|
||||
return that.options.cookiesEnabled.includes(cookieName)
|
||||
},
|
||||
setCookie (that, cookieName, cookieValue) {
|
||||
if (
|
||||
!that.options.cookie ||
|
||||
!UtilsCookie.isCookieEnabled(that, cookieName)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
return that._storage.setItem(`${that.options.cookieIdTable}.${cookieName}`, cookieValue)
|
||||
},
|
||||
getCookie (that, cookieName) {
|
||||
if (
|
||||
!cookieName ||
|
||||
!UtilsCookie.isCookieEnabled(that, cookieName)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
return that._storage.getItem(`${that.options.cookieIdTable}.${cookieName}`)
|
||||
},
|
||||
deleteCookie (that, cookieName) {
|
||||
return that._storage.removeItem(`${that.options.cookieIdTable}.${cookieName}`)
|
||||
},
|
||||
calculateExpiration (cookieExpire) {
|
||||
const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
|
||||
|
||||
cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
|
||||
|
||||
switch (time.toLowerCase()) {
|
||||
case 's':
|
||||
cookieExpire = +cookieExpire
|
||||
break
|
||||
case 'mi':
|
||||
cookieExpire *= 60
|
||||
break
|
||||
case 'h':
|
||||
cookieExpire = cookieExpire * 60 * 60
|
||||
break
|
||||
case 'd':
|
||||
cookieExpire = cookieExpire * 24 * 60 * 60
|
||||
break
|
||||
case 'm':
|
||||
cookieExpire = cookieExpire * 30 * 24 * 60 * 60
|
||||
break
|
||||
case 'y':
|
||||
cookieExpire = cookieExpire * 365 * 24 * 60 * 60
|
||||
break
|
||||
default:
|
||||
cookieExpire = undefined
|
||||
break
|
||||
}
|
||||
if (!cookieExpire) {
|
||||
return ''
|
||||
}
|
||||
const d = new Date()
|
||||
|
||||
d.setTime(d.getTime() + cookieExpire * 1000)
|
||||
return d.toGMTString()
|
||||
},
|
||||
initCookieFilters (that) {
|
||||
setTimeout(() => {
|
||||
const parsedCookieFilters = JSON.parse(
|
||||
UtilsCookie.getCookie(that, UtilsCookie.cookieIds.filterControl))
|
||||
|
||||
if (!that._filterControlValuesLoaded && parsedCookieFilters) {
|
||||
const cachedFilters = {}
|
||||
const header = UtilsCookie.getCurrentHeader(that)
|
||||
const searchControls = UtilsCookie.getCurrentSearchControls(that)
|
||||
|
||||
const applyCookieFilters = (element, filteredCookies) => {
|
||||
filteredCookies.forEach(cookie => {
|
||||
const value = element.value.toString()
|
||||
const text = cookie.text
|
||||
|
||||
if (
|
||||
text === '' ||
|
||||
element.type === 'radio' &&
|
||||
value !== text
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
element.tagName === 'INPUT' &&
|
||||
element.type === 'radio' &&
|
||||
value === text
|
||||
) {
|
||||
element.checked = true
|
||||
cachedFilters[cookie.field] = text
|
||||
} else if (element.tagName === 'INPUT') {
|
||||
element.value = text
|
||||
cachedFilters[cookie.field] = text
|
||||
} else if (
|
||||
element.tagName === 'SELECT' &&
|
||||
that.options.filterControlContainer
|
||||
) {
|
||||
element.value = text
|
||||
cachedFilters[cookie.field] = text
|
||||
} else if (text !== '' && element.tagName === 'SELECT') {
|
||||
cachedFilters[cookie.field] = text
|
||||
for (const currentElement of element) {
|
||||
if (currentElement.value === text) {
|
||||
currentElement.selected = true
|
||||
return
|
||||
}
|
||||
}
|
||||
const option = document.createElement('option')
|
||||
|
||||
option.value = text
|
||||
option.text = text
|
||||
element.add(option, element[1])
|
||||
element.selectedIndex = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let filterContainer = header
|
||||
|
||||
if (that.options.filterControlContainer) {
|
||||
filterContainer = $(`${that.options.filterControlContainer}`)
|
||||
}
|
||||
|
||||
filterContainer.find(searchControls).each(function () {
|
||||
const field = $(this).closest('[data-field]').data('field')
|
||||
const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
|
||||
|
||||
applyCookieFilters(this, filteredCookies)
|
||||
})
|
||||
|
||||
that.initColumnSearch(cachedFilters)
|
||||
that._filterControlValuesLoaded = true
|
||||
that.initServer()
|
||||
}
|
||||
}, 250)
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
cookie: false,
|
||||
cookieExpire: '2h',
|
||||
cookiePath: null,
|
||||
cookieDomain: null,
|
||||
cookieSecure: null,
|
||||
cookieSameSite: 'Lax',
|
||||
cookieIdTable: '',
|
||||
cookiesEnabled: [
|
||||
'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority',
|
||||
'bs.table.pageNumber', 'bs.table.pageList',
|
||||
'bs.table.hiddenColumns', 'bs.table.searchText',
|
||||
'bs.table.filterControl', 'bs.table.filterBy',
|
||||
'bs.table.reorderColumns', 'bs.table.cardView', 'bs.table.customView'
|
||||
],
|
||||
cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
|
||||
cookieCustomStorageGet: null,
|
||||
cookieCustomStorageSet: null,
|
||||
cookieCustomStorageDelete: null,
|
||||
// internal variable
|
||||
_filterControls: [],
|
||||
_filterControlValuesLoaded: false,
|
||||
_storage: {
|
||||
setItem: undefined,
|
||||
getItem: undefined,
|
||||
removeItem: undefined
|
||||
}
|
||||
})
|
||||
|
||||
$.fn.bootstrapTable.methods.push('getCookies')
|
||||
$.fn.bootstrapTable.methods.push('deleteCookie')
|
||||
|
||||
Object.assign($.fn.bootstrapTable.utils, {
|
||||
setCookie: UtilsCookie.setCookie,
|
||||
getCookie: UtilsCookie.getCookie
|
||||
})
|
||||
|
||||
$.BootstrapTable = class extends $.BootstrapTable {
|
||||
init () {
|
||||
if (this.options.cookie) {
|
||||
if (
|
||||
this.options.cookieStorage === 'cookieStorage' &&
|
||||
!UtilsCookie.isCookieSupportedByBrowser()
|
||||
) {
|
||||
throw new Error('Cookies are not enabled in this browser.')
|
||||
}
|
||||
|
||||
this.configureStorage()
|
||||
|
||||
// FilterBy logic
|
||||
const filterByCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterBy)
|
||||
|
||||
if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) {
|
||||
throw new Error('The cookie value of filterBy must be a json!')
|
||||
}
|
||||
|
||||
let filterByCookie = {}
|
||||
|
||||
try {
|
||||
filterByCookie = JSON.parse(filterByCookieValue)
|
||||
} catch (e) {
|
||||
throw new Error('Could not parse the json of the filterBy cookie!')
|
||||
}
|
||||
this.filterColumns = filterByCookie ? filterByCookie : {}
|
||||
|
||||
// FilterControl logic
|
||||
this._filterControls = []
|
||||
this._filterControlValuesLoaded = false
|
||||
|
||||
this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
|
||||
this.options.cookiesEnabled.replace('[', '').replace(']', '')
|
||||
.replace(/'/g, '').replace(/ /g, '').split(',') :
|
||||
this.options.cookiesEnabled
|
||||
|
||||
if (this.options.filterControl) {
|
||||
const that = this
|
||||
|
||||
this.$el.on('column-search.bs.table', (e, field, text) => {
|
||||
let isNewField = true
|
||||
|
||||
for (let i = 0; i < that._filterControls.length; i++) {
|
||||
if (that._filterControls[i].field === field) {
|
||||
that._filterControls[i].text = text
|
||||
isNewField = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (isNewField) {
|
||||
that._filterControls.push({
|
||||
field,
|
||||
text
|
||||
})
|
||||
}
|
||||
|
||||
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that._filterControls))
|
||||
}).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
|
||||
}
|
||||
}
|
||||
super.init()
|
||||
}
|
||||
|
||||
initServer (...args) {
|
||||
if (
|
||||
this.options.cookie &&
|
||||
this.options.filterControl &&
|
||||
!this._filterControlValuesLoaded
|
||||
) {
|
||||
const cookie = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterControl))
|
||||
|
||||
if (cookie) {
|
||||
return
|
||||
}
|
||||
}
|
||||
super.initServer(...args)
|
||||
}
|
||||
|
||||
initTable (...args) {
|
||||
super.initTable(...args)
|
||||
this.initCookie()
|
||||
}
|
||||
|
||||
onSort (...args) {
|
||||
super.onSort(...args)
|
||||
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.options.sortName === undefined || this.options.sortOrder === undefined) {
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||
} else {
|
||||
this.options.sortPriority = null
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
|
||||
}
|
||||
}
|
||||
|
||||
onMultipleSort (...args) {
|
||||
super.onMultipleSort(...args)
|
||||
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.options.sortPriority === undefined) {
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||
} else {
|
||||
this.options.sortName = undefined
|
||||
this.options.sortOrder = undefined
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority))
|
||||
}
|
||||
}
|
||||
|
||||
onPageNumber (...args) {
|
||||
super.onPageNumber(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||
}
|
||||
|
||||
onPageListChange (...args) {
|
||||
super.onPageListChange(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList,
|
||||
this.options.pageSize === this.options.formatAllRows() ? 'all' : this.options.pageSize)
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||
}
|
||||
|
||||
onPagePre (...args) {
|
||||
super.onPagePre(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||
}
|
||||
|
||||
onPageNext (...args) {
|
||||
super.onPageNext(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||
}
|
||||
|
||||
_toggleColumn (...args) {
|
||||
super._toggleColumn(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
|
||||
}
|
||||
|
||||
_toggleAllColumns (...args) {
|
||||
super._toggleAllColumns(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
|
||||
}
|
||||
|
||||
toggleView () {
|
||||
super.toggleView()
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.cardView, this.options.cardView)
|
||||
}
|
||||
|
||||
toggleCustomView () {
|
||||
super.toggleCustomView()
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.customView, this.customViewDefaultView)
|
||||
}
|
||||
|
||||
selectPage (page) {
|
||||
super.selectPage(page)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
|
||||
}
|
||||
|
||||
onSearch (event) {
|
||||
super.onSearch(event, arguments.length > 1 ? arguments[1] : true)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
if (this.options.search) {
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||
}
|
||||
|
||||
initHeader (...args) {
|
||||
if (this.options.reorderableColumns && this.options.cookie) {
|
||||
this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.reorderColumns))
|
||||
}
|
||||
super.initHeader(...args)
|
||||
}
|
||||
|
||||
persistReorderColumnsState (that) {
|
||||
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder))
|
||||
}
|
||||
|
||||
filterBy (...args) {
|
||||
super.filterBy(...args)
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
|
||||
}
|
||||
|
||||
initCookie () {
|
||||
if (!this.options.cookie) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.options.cookieIdTable === '' || this.options.cookieExpire === '') {
|
||||
console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
|
||||
this.options.cookie = false // Make sure that the cookie extension is disabled
|
||||
return
|
||||
}
|
||||
|
||||
const sortOrderCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||
const sortOrderNameCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortName)
|
||||
let sortPriorityCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||
const pageNumberCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageNumber)
|
||||
const pageListCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageList)
|
||||
const searchTextCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.searchText)
|
||||
const cardViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.cardView)
|
||||
const customViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.customView)
|
||||
const hiddenColumnsCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.hiddenColumns)
|
||||
|
||||
let hiddenColumnsCookie = {}
|
||||
|
||||
try {
|
||||
hiddenColumnsCookie = JSON.parse(hiddenColumnsCookieValue)
|
||||
} catch (e) {
|
||||
throw new Error('Could not parse the json of the hidden columns cookie!', hiddenColumnsCookieValue)
|
||||
}
|
||||
|
||||
try {
|
||||
sortPriorityCookie = JSON.parse(sortPriorityCookie)
|
||||
} catch (e) {
|
||||
throw new Error('Could not parse the json of the sortPriority cookie!', sortPriorityCookie)
|
||||
}
|
||||
|
||||
if (!sortPriorityCookie) {
|
||||
// sortOrder
|
||||
this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
|
||||
// sortName
|
||||
this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
|
||||
} else {
|
||||
this.options.sortOrder = undefined
|
||||
this.options.sortName = undefined
|
||||
}
|
||||
|
||||
// sortPriority
|
||||
this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority
|
||||
|
||||
if (this.options.sortOrder || this.options.sortName) {
|
||||
// sortPriority
|
||||
this.options.sortPriority = null
|
||||
}
|
||||
|
||||
// pageNumber
|
||||
this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
|
||||
// pageSize
|
||||
this.options.pageSize = pageListCookie ? pageListCookie === 'all' ?
|
||||
this.options.formatAllRows() : +pageListCookie : this.options.pageSize
|
||||
// searchText
|
||||
if (UtilsCookie.isCookieEnabled(this, UtilsCookie.cookieIds.searchText) && this.options.searchText === '') {
|
||||
this.options.searchText = searchTextCookie ? searchTextCookie : ''
|
||||
}
|
||||
// cardView
|
||||
if (cardViewCookie !== null) {
|
||||
this.options.cardView = cardViewCookie === 'true' ? cardViewCookie : false
|
||||
}
|
||||
this.customViewDefaultView = customViewCookie === 'true'
|
||||
|
||||
if (hiddenColumnsCookie) {
|
||||
for (const column of this.columns) {
|
||||
if (!column.switchable) {
|
||||
continue
|
||||
}
|
||||
|
||||
column.visible = this.isSelectionColumn(column) ||
|
||||
!hiddenColumnsCookie.includes(column.field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCookies () {
|
||||
const bootstrapTable = this
|
||||
const cookies = {}
|
||||
|
||||
for (const [key, value] of Object.entries(UtilsCookie.cookieIds)) {
|
||||
cookies[key] = UtilsCookie.getCookie(bootstrapTable, value)
|
||||
if (key === 'columns' || key === 'hiddenColumns' || key === 'sortPriority') {
|
||||
cookies[key] = JSON.parse(cookies[key])
|
||||
}
|
||||
}
|
||||
return cookies
|
||||
}
|
||||
|
||||
deleteCookie (cookieName) {
|
||||
if (!cookieName) {
|
||||
return
|
||||
}
|
||||
|
||||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds[cookieName])
|
||||
}
|
||||
|
||||
configureStorage () {
|
||||
const that = this
|
||||
|
||||
this._storage = {}
|
||||
switch (this.options.cookieStorage) {
|
||||
case 'cookieStorage':
|
||||
this._storage.setItem = function (cookieName, cookieValue) {
|
||||
document.cookie = [
|
||||
cookieName, '=', encodeURIComponent(cookieValue),
|
||||
`; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
|
||||
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
|
||||
that.options.cookieSecure ? '; secure' : '',
|
||||
`;SameSite=${that.options.cookieSameSite}`
|
||||
].join('')
|
||||
}
|
||||
this._storage.getItem = function (cookieName) {
|
||||
const value = `; ${document.cookie}`
|
||||
const parts = value.split(`; ${cookieName}=`)
|
||||
|
||||
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
|
||||
}
|
||||
this._storage.removeItem = function (cookieName) {
|
||||
document.cookie = [
|
||||
encodeURIComponent(cookieName), '=',
|
||||
'; expires=Thu, 01 Jan 1970 00:00:00 GMT',
|
||||
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
|
||||
`;SameSite=${that.options.cookieSameSite}`
|
||||
].join('')
|
||||
}
|
||||
break
|
||||
case 'localStorage':
|
||||
this._storage.setItem = function (cookieName, cookieValue) {
|
||||
localStorage.setItem(cookieName, cookieValue)
|
||||
}
|
||||
this._storage.getItem = function (cookieName) {
|
||||
return localStorage.getItem(cookieName)
|
||||
}
|
||||
this._storage.removeItem = function (cookieName) {
|
||||
localStorage.removeItem(cookieName)
|
||||
}
|
||||
break
|
||||
case 'sessionStorage':
|
||||
this._storage.setItem = function (cookieName, cookieValue) {
|
||||
sessionStorage.setItem(cookieName, cookieValue)
|
||||
}
|
||||
this._storage.getItem = function (cookieName) {
|
||||
return sessionStorage.getItem(cookieName)
|
||||
}
|
||||
this._storage.removeItem = function (cookieName) {
|
||||
sessionStorage.removeItem(cookieName)
|
||||
}
|
||||
break
|
||||
case 'customStorage':
|
||||
if (
|
||||
!this.options.cookieCustomStorageSet ||
|
||||
!this.options.cookieCustomStorageGet ||
|
||||
!this.options.cookieCustomStorageDelete
|
||||
) {
|
||||
throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
|
||||
}
|
||||
|
||||
this._storage.setItem = function (cookieName, cookieValue) {
|
||||
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '')
|
||||
}
|
||||
this._storage.getItem = function (cookieName) {
|
||||
return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '')
|
||||
}
|
||||
this._storage.removeItem = function (cookieName) {
|
||||
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '')
|
||||
}
|
||||
|
||||
break
|
||||
default:
|
||||
throw new Error('Storage method not supported.')
|
||||
}
|
||||
}
|
||||
}
|
@ -5,65 +5,81 @@
|
||||
|
||||
var Utils = $.fn.bootstrapTable.utils
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
customView: false,
|
||||
showCustomView: false,
|
||||
showCustomViewButton: false
|
||||
customViewDefaultView: false
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
customView: {
|
||||
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||
customViewOn: {
|
||||
bootstrap3: 'glyphicon glyphicon-list',
|
||||
bootstrap5: 'bi-list',
|
||||
bootstrap4: 'fa fa-list',
|
||||
semantic: 'fa fa-list',
|
||||
foundation: 'fa fa-list',
|
||||
bulma: 'fa fa-list',
|
||||
materialize: 'list'
|
||||
}[$.fn.bootstrapTable.theme] || 'fa-list',
|
||||
customViewOff: {
|
||||
bootstrap3: 'glyphicon glyphicon-eye-open',
|
||||
bootstrap5: 'bi-eye',
|
||||
bootstrap4: 'fa fa-eye',
|
||||
semantic: 'fa fa-eye',
|
||||
foundation: 'fa fa-eye',
|
||||
bulma: 'fa fa-eye',
|
||||
materialize: 'remove_red_eye'
|
||||
}[$.fn.bootstrapTable.theme] || 'fa-eye'
|
||||
bootstrap5: 'bi-grid',
|
||||
bootstrap4: 'fa fa-th',
|
||||
semantic: 'fa fa-th',
|
||||
foundation: 'fa fa-th',
|
||||
bulma: 'fa fa-th',
|
||||
materialize: 'grid_on'
|
||||
}[$.fn.bootstrapTable.theme] || 'fa-th'
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
onCustomViewPostBody () {
|
||||
return false
|
||||
},
|
||||
onCustomViewPreBody () {
|
||||
return false
|
||||
},
|
||||
onToggleCustomView () {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.locales, {
|
||||
formatToggleCustomView () {
|
||||
return 'Toggle custom view'
|
||||
Object.assign($.fn.bootstrapTable.locales, {
|
||||
formatToggleCustomViewOn () {
|
||||
return 'Show custom view'
|
||||
},
|
||||
formatToggleCustomViewOff () {
|
||||
return 'Hide custom view'
|
||||
}
|
||||
})
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
|
||||
$.fn.bootstrapTable.methods.push('toggleCustomView')
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
Object.assign($.fn.bootstrapTable.events, {
|
||||
'custom-view-post-body.bs.table': 'onCustomViewPostBody',
|
||||
'custom-view-pre-body.bs.table': 'onCustomViewPreBody'
|
||||
'custom-view-pre-body.bs.table': 'onCustomViewPreBody',
|
||||
'toggle-custom-view.bs.table': 'onToggleCustomView'
|
||||
})
|
||||
|
||||
$.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
init () {
|
||||
this.showCustomView = this.options.showCustomView
|
||||
this.customViewDefaultView = this.options.customViewDefaultView
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
initToolbar (...args) {
|
||||
if (this.options.customView && this.options.showCustomViewButton) {
|
||||
if (this.options.customView && this.options.showCustomView) {
|
||||
this.buttons = Object.assign(this.buttons, {
|
||||
customView: {
|
||||
text: this.options.formatToggleCustomView(),
|
||||
icon: this.options.icons.customView,
|
||||
text: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
|
||||
icon: this.options.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff,
|
||||
event: this.toggleCustomView,
|
||||
attributes: {
|
||||
'aria-label': this.options.formatToggleCustomView(),
|
||||
title: this.options.formatToggleCustomView()
|
||||
'aria-label': this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
|
||||
title: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -84,7 +100,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
$table.hide()
|
||||
$customViewContainer.hide()
|
||||
if (!this.options.customView || !this.showCustomView) {
|
||||
if (!this.options.customView || !this.customViewDefaultView) {
|
||||
$table.show()
|
||||
return
|
||||
}
|
||||
@ -103,7 +119,17 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}
|
||||
|
||||
toggleCustomView () {
|
||||
this.showCustomView = !this.showCustomView
|
||||
this.customViewDefaultView = !this.customViewDefaultView
|
||||
|
||||
const icon = this.options.showButtonIcons ? this.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff : ''
|
||||
const text = this.options.showButtonText ? this.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn() : ''
|
||||
|
||||
this.$toolbar.find('button[name="customView"]')
|
||||
.html(`${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon)} ${text}`)
|
||||
.attr('aria-label', text)
|
||||
.attr('title', text)
|
||||
|
||||
this.initBody()
|
||||
this.trigger('toggle-custom-view', this.customViewDefaultView)
|
||||
}
|
||||
}
|
||||
}
|
@ -19,28 +19,20 @@ const TYPE_NAME = {
|
||||
pdf: 'PDF'
|
||||
}
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
showExport: false,
|
||||
exportDataType: 'basic', // basic, all, selected
|
||||
exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
|
||||
exportOptions: {
|
||||
onCellHtmlData (cell, rowIndex, colIndex, htmlData) {
|
||||
if (cell.is('th')) {
|
||||
return cell.find('.th-inner').text()
|
||||
}
|
||||
|
||||
return htmlData
|
||||
}
|
||||
},
|
||||
exportOptions: {},
|
||||
exportFooter: false
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.columnDefaults, {
|
||||
Object.assign($.fn.bootstrapTable.columnDefaults, {
|
||||
forceExport: false,
|
||||
forceHide: false
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||
export: {
|
||||
bootstrap3: 'glyphicon-export icon-share',
|
||||
bootstrap5: 'bi-download',
|
||||
@ -49,24 +41,28 @@ $.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
}[$.fn.bootstrapTable.theme] || 'fa-download'
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.locales, {
|
||||
Object.assign($.fn.bootstrapTable.locales, {
|
||||
formatExport () {
|
||||
return 'Export data'
|
||||
}
|
||||
})
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
|
||||
$.fn.bootstrapTable.methods.push('exportTable')
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onExportSaved (exportedRows) {
|
||||
return false
|
||||
},
|
||||
onExportStarted () {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
'export-saved.bs.table': 'onExportSaved'
|
||||
Object.assign($.fn.bootstrapTable.events, {
|
||||
'export-saved.bs.table': 'onExportSaved',
|
||||
'export-started.bs.table': 'onExportStarted'
|
||||
})
|
||||
|
||||
$.BootstrapTable = class extends $.BootstrapTable {
|
||||
@ -84,6 +80,10 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
exportTypes = types.map(t => t.slice(1, -1))
|
||||
}
|
||||
|
||||
if (typeof o.exportOptions === 'string') {
|
||||
o.exportOptions = Utils.calculateObjectValue(null, o.exportOptions)
|
||||
}
|
||||
|
||||
this.$export = this.$toolbar.find('>.columns div.export')
|
||||
if (this.$export.length) {
|
||||
this.updateExportButton()
|
||||
@ -93,13 +93,13 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
this.buttons = Object.assign(this.buttons, {
|
||||
export: {
|
||||
html:
|
||||
(() => {
|
||||
() => {
|
||||
if (exportTypes.length === 1) {
|
||||
return `
|
||||
<div class="export ${this.constants.classes.buttonsDropdown}"
|
||||
data-type="${exportTypes[0]}">
|
||||
<button class="${this.constants.buttonsClass}"
|
||||
aria-label="Export"
|
||||
aria-label="${o.formatExport()}"
|
||||
type="button"
|
||||
title="${o.formatExport()}">
|
||||
${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''}
|
||||
@ -114,7 +114,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
html.push(`
|
||||
<div class="export ${this.constants.classes.buttonsDropdown}">
|
||||
<button class="${this.constants.buttonsClass} dropdown-toggle"
|
||||
aria-label="Export"
|
||||
aria-label="${o.formatExport()}"
|
||||
${this.constants.dataToggle}="dropdown"
|
||||
type="button"
|
||||
title="${o.formatExport()}">
|
||||
@ -136,7 +136,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
html.push(this.constants.html.toolbarDropdown[1], '</div>')
|
||||
return html.join('')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -152,19 +152,15 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
let $exportButtons = this.$export.find('[data-type]')
|
||||
|
||||
if (exportTypes.length === 1) {
|
||||
$exportButtons = this.$export.find('button')
|
||||
$exportButtons = this.$export
|
||||
}
|
||||
|
||||
$exportButtons.click(e => {
|
||||
e.preventDefault()
|
||||
|
||||
const type = $(e.currentTarget).data('type')
|
||||
const exportOptions = {
|
||||
type,
|
||||
escape: false
|
||||
}
|
||||
|
||||
this.exportTable(exportOptions)
|
||||
this.trigger('export-started')
|
||||
this.exportTable({
|
||||
type: $(e.currentTarget).data('type')
|
||||
})
|
||||
})
|
||||
this.handleToolbar()
|
||||
}
|
||||
@ -206,7 +202,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
o.exportOptions.ignoreColumn = [detailViewIndex].concat(o.exportOptions.ignoreColumn || [])
|
||||
}
|
||||
|
||||
if (o.exportFooter) {
|
||||
if (o.exportFooter && o.height) {
|
||||
const $footerRow = this.$tableFooter.find('tr').first()
|
||||
const footerData = {}
|
||||
const footerHtml = []
|
||||
@ -240,7 +236,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
options.fileName = o.exportOptions.fileName()
|
||||
}
|
||||
|
||||
this.$el.tableExport($.extend({
|
||||
this.$el.tableExport(Utils.extend({
|
||||
onAfterSaveToFile: () => {
|
||||
if (o.exportFooter) {
|
||||
this.load(data)
|
||||
@ -277,15 +273,17 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
this.$el.one(eventName, () => {
|
||||
setTimeout(() => {
|
||||
const data = this.getData()
|
||||
|
||||
doExport(() => {
|
||||
this.options.virtualScroll = virtualScroll
|
||||
this.togglePagination()
|
||||
})
|
||||
this.trigger('export-saved', data)
|
||||
}, 0)
|
||||
})
|
||||
this.options.virtualScroll = false
|
||||
this.togglePagination()
|
||||
this.trigger('export-saved', this.getData())
|
||||
} else if (o.exportDataType === 'selected') {
|
||||
let data = this.getData()
|
||||
let selectedData = this.getSelections()
|
||||
@ -334,4 +332,4 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
.prop('disabled', !this.getSelections().length)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @webSite: http://djhvscf.github.io/Blog
|
||||
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||
*/
|
||||
|
||||
@ -18,7 +17,7 @@ const debounce = (func, wait) => {
|
||||
}
|
||||
}
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
mobileResponsive: false,
|
||||
minWidth: 562,
|
||||
minHeight: undefined,
|
||||
@ -108,9 +107,9 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
changeView (width, height) {
|
||||
if (this.options.minHeight) {
|
||||
if ((width <= this.options.minWidth) && (height <= this.options.minHeight)) {
|
||||
if (width <= this.options.minWidth && height <= this.options.minHeight) {
|
||||
this.conditionCardView()
|
||||
} else if ((width > this.options.minWidth) && (height > this.options.minHeight)) {
|
||||
} else if (width > this.options.minWidth && height > this.options.minHeight) {
|
||||
this.conditionFullView()
|
||||
}
|
||||
} else if (width <= this.options.minWidth) {
|
||||
@ -121,4 +120,4 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
this.resetView()
|
||||
}
|
||||
}
|
||||
}
|
@ -4,76 +4,80 @@
|
||||
|
||||
var Utils = $.fn.bootstrapTable.utils
|
||||
|
||||
function printPageBuilderDefault (table) {
|
||||
function printPageBuilderDefault (table, styles) {
|
||||
return `
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css" media="print">
|
||||
@page {
|
||||
size: auto;
|
||||
margin: 25px 0 25px 0;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css" media="all">
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 12px;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid grey;
|
||||
}
|
||||
th, td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
p {
|
||||
font-weight: bold;
|
||||
margin-left:20px;
|
||||
}
|
||||
table {
|
||||
width:94%;
|
||||
margin-left:3%;
|
||||
margin-right:3%;
|
||||
}
|
||||
div.bs-table-print {
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<title>Print Table</title>
|
||||
<body>
|
||||
<p>Printed on: ${new Date} </p>
|
||||
<div class="bs-table-print">${table}</div>
|
||||
</body>
|
||||
</html>`
|
||||
<html>
|
||||
<head>
|
||||
${styles}
|
||||
<style type="text/css" media="print">
|
||||
@page {
|
||||
size: auto;
|
||||
margin: 25px 0 25px 0;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css" media="all">
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 12px;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid grey;
|
||||
}
|
||||
th, td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
p {
|
||||
font-weight: bold;
|
||||
margin-left:20px;
|
||||
}
|
||||
table {
|
||||
width: 94%;
|
||||
margin-left: 3%;
|
||||
margin-right: 3%;
|
||||
}
|
||||
div.bs-table-print {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<title>Print Table</title>
|
||||
<body>
|
||||
<p>Printed on: ${new Date} </p>
|
||||
<div class="bs-table-print">${table}</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
|
||||
$.extend($.fn.bootstrapTable.locales, {
|
||||
Object.assign($.fn.bootstrapTable.locales, {
|
||||
formatPrint () {
|
||||
return 'Print'
|
||||
}
|
||||
})
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
showPrint: false,
|
||||
printAsFilteredAndSortedOnUI: true,
|
||||
printSortColumn: undefined,
|
||||
printSortOrder: 'asc',
|
||||
printPageBuilder (table) {
|
||||
return printPageBuilderDefault(table)
|
||||
printStyles: [],
|
||||
printPageBuilder (table, styles) {
|
||||
return printPageBuilderDefault(table, styles)
|
||||
}
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
|
||||
Object.assign($.fn.bootstrapTable.columnDefaults, {
|
||||
printFilter: undefined,
|
||||
printIgnore: false,
|
||||
printFormatter: undefined
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||
print: {
|
||||
bootstrap3: 'glyphicon-print icon-share',
|
||||
bootstrap5: 'bi-printer',
|
||||
'bootstrap-table': 'icon-printer'
|
||||
}[$.fn.bootstrapTable.theme] || 'fa-print'
|
||||
})
|
||||
@ -133,10 +137,15 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}
|
||||
|
||||
doPrint (data) {
|
||||
const canPrint = column => {
|
||||
return !column.printIgnore && column.visible
|
||||
}
|
||||
|
||||
const formatValue = (row, i, column) => {
|
||||
const value_ = Utils.getItemField(row, column.field, this.options.escape, column.escape)
|
||||
const value = Utils.calculateObjectValue(column,
|
||||
column.printFormatter || column.formatter,
|
||||
[$.common.getItemField(row, column.field), row, i], $.common.getItemField(row, column.field))
|
||||
[value_, row, i], value_)
|
||||
|
||||
return typeof value === 'undefined' || value === null ?
|
||||
this.options.undefinedText : value
|
||||
@ -149,7 +158,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
for (const columns of columnsArray) {
|
||||
html.push('<tr>')
|
||||
for (let h = 0; h < columns.length; h++) {
|
||||
if (!columns[h].printIgnore) {
|
||||
if (canPrint(columns[h])) {
|
||||
html.push(
|
||||
`<th
|
||||
${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
|
||||
@ -162,7 +171,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
html.push('</thead><tbody>')
|
||||
|
||||
const dontRender = []
|
||||
const notRender = []
|
||||
|
||||
if (this.mergedCells) {
|
||||
for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
||||
@ -174,7 +183,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
|
||||
const col = currentMergedCell.col + cs
|
||||
|
||||
dontRender.push(`${row },${ col}`)
|
||||
notRender.push(`${row},${col}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,11 +216,11 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}
|
||||
|
||||
if (
|
||||
!columns[j].printIgnore && columns[j].field &&
|
||||
(
|
||||
!dontRender.includes(`${i },${ j}`) ||
|
||||
(rowspan > 0 && colspan > 0)
|
||||
)
|
||||
canPrint(columns[j]) &&
|
||||
(
|
||||
!notRender.includes(`${i},${j}`) ||
|
||||
rowspan > 0 && colspan > 0
|
||||
)
|
||||
) {
|
||||
if (rowspan > 0 && colspan > 0) {
|
||||
html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>')
|
||||
@ -221,7 +230,6 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
html.push('</tr>')
|
||||
}
|
||||
|
||||
@ -231,7 +239,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
for (const columns of columnsArray) {
|
||||
for (let h = 0; h < columns.length; h++) {
|
||||
if (!columns[h].printIgnore) {
|
||||
if (canPrint(columns)) {
|
||||
const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr'))
|
||||
const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '')
|
||||
|
||||
@ -252,8 +260,8 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}
|
||||
let reverse = sortOrder !== 'asc'
|
||||
|
||||
reverse = -((+reverse) || -1)
|
||||
return data.sort((a, b) => reverse * (a[colName].localeCompare(b[colName])))
|
||||
reverse = -(+reverse || -1)
|
||||
return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName]))
|
||||
}
|
||||
|
||||
const filterRow = (row, filters) => {
|
||||
@ -275,11 +283,30 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
|
||||
const table = buildTable(data, this.options.columns)
|
||||
const newWin = window.open('')
|
||||
const printStyles = typeof this.options.printStyles === 'string' ?
|
||||
this.options.printStyles.replace(/\[|\]| /g, '').toLowerCase().split(',') :
|
||||
this.options.printStyles
|
||||
const styles = printStyles.map(it =>
|
||||
`<link rel="stylesheet" href="${it}" />`).join('')
|
||||
|
||||
newWin.document.write(this.options.printPageBuilder.call(this, table))
|
||||
const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder,
|
||||
[table, styles], printPageBuilderDefault(table, styles))
|
||||
const startPrint = () => {
|
||||
newWin.focus()
|
||||
newWin.print()
|
||||
newWin.close()
|
||||
}
|
||||
|
||||
newWin.document.write(calculatedPrintPage)
|
||||
newWin.document.close()
|
||||
newWin.focus()
|
||||
newWin.print()
|
||||
newWin.close()
|
||||
|
||||
if (printStyles.length) {
|
||||
const links = document.getElementsByTagName('link')
|
||||
const lastLink = links[links.length - 1]
|
||||
|
||||
lastLink.onload = startPrint
|
||||
} else {
|
||||
startPrint()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @webSite: http://djhvscf.github.io/Blog
|
||||
* @update: https://github.com/wenzhixin
|
||||
* @version: v1.2.0
|
||||
*/
|
||||
@ -60,7 +59,7 @@ const filterFn = () => {
|
||||
}
|
||||
}
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
reorderableColumns: false,
|
||||
maxMovingRows: 10,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -70,7 +69,7 @@ $.extend($.fn.bootstrapTable.defaults, {
|
||||
dragaccept: null
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
Object.assign($.fn.bootstrapTable.events, {
|
||||
'reorder-column.bs.table': 'onReorderColumn'
|
||||
})
|
||||
|
||||
@ -84,7 +83,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
return
|
||||
}
|
||||
|
||||
this.makeRowsReorderable()
|
||||
this.makeColumnsReorderable()
|
||||
}
|
||||
|
||||
_toggleColumn (...args) {
|
||||
@ -94,7 +93,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
return
|
||||
}
|
||||
|
||||
this.makeRowsReorderable()
|
||||
this.makeColumnsReorderable()
|
||||
}
|
||||
|
||||
toggleView (...args) {
|
||||
@ -108,7 +107,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
return
|
||||
}
|
||||
|
||||
this.makeRowsReorderable()
|
||||
this.makeColumnsReorderable()
|
||||
}
|
||||
|
||||
resetView (...args) {
|
||||
@ -118,10 +117,10 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
return
|
||||
}
|
||||
|
||||
this.makeRowsReorderable()
|
||||
this.makeColumnsReorderable()
|
||||
}
|
||||
|
||||
makeRowsReorderable (order = null) {
|
||||
makeColumnsReorderable (order = null) {
|
||||
try {
|
||||
$(this.$el).dragtable('destroy')
|
||||
} catch (e) {
|
||||
@ -208,6 +207,6 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
orderColumns (order) {
|
||||
this.columnsSortOrder = order
|
||||
this.makeRowsReorderable()
|
||||
this.makeColumnsReorderable()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @webSite: http://djhvscf.github.io/Blog
|
||||
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||
*/
|
||||
|
||||
@ -8,11 +7,11 @@ const rowAttr = (row, index) => ({
|
||||
id: `customId_${index}`
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
reorderableRows: false,
|
||||
onDragStyle: null,
|
||||
onDropStyle: null,
|
||||
onDragClass: 'reorder_rows_onDragClass',
|
||||
onDragClass: 'reorder-rows-on-drag-class',
|
||||
dragHandle: '>tbody>tr>td:not(.bs-checkbox)',
|
||||
useRowAttrFunc: false,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -26,10 +25,14 @@ $.extend($.fn.bootstrapTable.defaults, {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onReorderRow (newData) {
|
||||
return false
|
||||
},
|
||||
onDragStop () {},
|
||||
onAllowDrop () {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
Object.assign($.fn.bootstrapTable.events, {
|
||||
'reorder-row.bs.table': 'onReorderRow'
|
||||
})
|
||||
|
||||
@ -61,6 +64,8 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
onDragStyle: this.options.onDragStyle,
|
||||
onDropStyle: this.options.onDropStyle,
|
||||
onDragClass: this.options.onDragClass,
|
||||
onAllowDrop: (hoveredRow, draggedRow) => this.onAllowDrop(hoveredRow, draggedRow),
|
||||
onDragStop: (table, draggedRow) => this.onDragStop(table, draggedRow),
|
||||
onDragStart: (table, droppedRow) => this.onDropStart(table, droppedRow),
|
||||
onDrop: (table, droppedRow) => this.onDrop(table, droppedRow),
|
||||
dragHandle: this.options.dragHandle
|
||||
@ -74,8 +79,26 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
this.options.onReorderRowsDrag(this.data[this.draggingIndex])
|
||||
}
|
||||
|
||||
onDragStop (table, draggedRow) {
|
||||
const rowIndexDraggedRow = $(draggedRow).data('index')
|
||||
const draggedRowItem = this.data[rowIndexDraggedRow]
|
||||
|
||||
this.options.onDragStop(table, draggedRowItem, draggedRow)
|
||||
}
|
||||
|
||||
onAllowDrop (hoveredRow, draggedRow) {
|
||||
const rowIndexDraggedRow = $(draggedRow).data('index')
|
||||
const rowIndexHoveredRow = $(hoveredRow).data('index')
|
||||
const draggedRowItem = this.data[rowIndexDraggedRow]
|
||||
const hoveredRowItem = this.data[rowIndexHoveredRow]
|
||||
|
||||
return this.options.onAllowDrop(hoveredRowItem, draggedRowItem, hoveredRow, draggedRow)
|
||||
}
|
||||
|
||||
onDrop (table) {
|
||||
this.$draggingTd.css('cursor', '')
|
||||
const pageNum = this.options.pageNumber
|
||||
const pageSize = this.options.pageSize
|
||||
const newData = []
|
||||
|
||||
for (let i = 0; i < table.tBodies[0].rows.length; i++) {
|
||||
@ -88,13 +111,17 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
const draggingRow = this.data[this.draggingIndex]
|
||||
const droppedIndex = newData.indexOf(this.data[this.draggingIndex])
|
||||
const droppedRow = this.data[droppedIndex]
|
||||
const index = this.options.data.indexOf(this.data[droppedIndex])
|
||||
const index = (pageNum - 1) * pageSize + this.options.data.indexOf(this.data[droppedIndex])
|
||||
|
||||
this.options.data.splice(this.options.data.indexOf(draggingRow), 1)
|
||||
this.options.data.splice(index, 0, draggingRow)
|
||||
|
||||
this.initSearch()
|
||||
|
||||
if (this.options.sidePagination === 'server') {
|
||||
this.data = [...this.options.data]
|
||||
}
|
||||
|
||||
// Call the user defined function
|
||||
this.options.onReorderRowsDrop(droppedRow)
|
||||
|
||||
@ -115,4 +142,4 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
|
||||
super.initSort()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @webSite: http://djhvscf.github.io/Blog
|
||||
* @version: v2.0.0
|
||||
*/
|
||||
|
||||
@ -30,7 +29,7 @@ const reInitResizable = that => {
|
||||
initResizable(that)
|
||||
}
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
Object.assign($.fn.bootstrapTable.defaults, {
|
||||
resizable: false
|
||||
})
|
||||
|
||||
@ -66,4 +65,4 @@ $.BootstrapTable = class extends $.BootstrapTable {
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -131,6 +131,9 @@
|
||||
$th = $('<th style="width:36px"></th>');
|
||||
} else {
|
||||
$th = $('<th style="' + ((column.width) ? ('width:' + column.width + ((column.widthUnit) ? column.widthUnit : 'px')) : '') + '" class="' + column.field + '_cls"></th>');
|
||||
if (column.align) {
|
||||
$th.css("text-align", column.align);
|
||||
}
|
||||
}
|
||||
if((!target.isFixWidth)&& column.width){
|
||||
target.isFixWidth = column.width.indexOf("px")>-1?true:false;
|
||||
@ -686,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) {
|
||||
@ -714,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
File diff suppressed because one or more lines are too long
@ -1,49 +1,53 @@
|
||||
/*this is basic form validation using for validation person's basic information author:Clara Guo data:2017/07/20*/
|
||||
$(document).ready(function(){
|
||||
$.validator.setDefaults({
|
||||
submitHandler: function(form) {
|
||||
form.submit();
|
||||
submitHandler: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
//手机号码验证身份证正则合并:(^\d{15}$)|(^\d{17}([0-9]|X)$)
|
||||
jQuery.validator.addMethod("isPhone",function(value,element){
|
||||
});
|
||||
// 非法字符验证
|
||||
jQuery.validator.addMethod("specialSign",function(value,element) {
|
||||
var char = /^[^<>"'|\\]+$/;
|
||||
return this.optional(element) || (char.test(value));
|
||||
},"不能包含非法字符:< > \" ' \\\ |");
|
||||
// 手机号码验证身份证正则合并:(^\d{15}$)|(^\d{17}([0-9]|X)$)
|
||||
jQuery.validator.addMethod("isPhone",function(value,element) {
|
||||
var length = value.length;
|
||||
var phone=/^1[3-9]\d{9}$/;
|
||||
var phone = /^1[3-9]\d{9}$/;
|
||||
return this.optional(element)||(length == 11 && phone.test(value));
|
||||
},"请填写正确的11位手机号");
|
||||
//电话号码验证
|
||||
jQuery.validator.addMethod("isTel",function(value,element){
|
||||
// 电话号码验证
|
||||
jQuery.validator.addMethod("isTel",function(value,element) {
|
||||
var tel = /^(0\d{2,3}-)?\d{7,8}$/g;//区号3,4位,号码7,8位
|
||||
return this.optional(element) || (tel.test(value));
|
||||
},"请填写正确的座机号码");
|
||||
//姓名校验
|
||||
jQuery.validator.addMethod("isName",function(value,element){
|
||||
var name=/^[\u4e00-\u9fa5]{2,6}$/;
|
||||
// 姓名校验
|
||||
jQuery.validator.addMethod("isName",function(value,element) {
|
||||
var name = /^[\u4e00-\u9fa5]{2,6}$/;
|
||||
return this.optional(element) || (name.test(value));
|
||||
},"姓名只能用汉字,长度2-4位");
|
||||
//校验用户名
|
||||
jQuery.validator.addMethod("isUserName",function(value,element){
|
||||
var userName=/^[a-zA-Z0-9]{2,13}$/;
|
||||
// 校验用户名
|
||||
jQuery.validator.addMethod("isUserName",function(value,element) {
|
||||
var userName = /^[a-zA-Z0-9]{2,13}$/;
|
||||
return this.optional(element) || (userName).test(value);
|
||||
},'请输入数字或者字母,不包含特殊字符');
|
||||
|
||||
//校验身份证
|
||||
jQuery.validator.addMethod("isIdentity",function(value,element){
|
||||
var id= /^(\d{15}$|^\d{18}$|^\d{17}(\d|X))$/;
|
||||
// 校验身份证
|
||||
jQuery.validator.addMethod("isIdentity",function(value,element) {
|
||||
var id = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X))$/;
|
||||
return this.optional(element) || (id.test(value));
|
||||
},"请输入正确的15或18位身份证号,末尾若为X请大写");
|
||||
//校验二代身份证
|
||||
jQuery.validator.addMethod("isIdentity18",function(value,element){
|
||||
var id= /^(^\d{17}(\d|X))$/;
|
||||
// 校验二代身份证
|
||||
jQuery.validator.addMethod("isIdentity18",function(value,element) {
|
||||
var id = /^(^\d{17}(\d|X))$/;
|
||||
return this.optional(element) || (id.test(value));
|
||||
},"请输入正确的18位身份证号,末尾若为X请大写");
|
||||
//校验出生日期
|
||||
jQuery.validator.addMethod("isBirth",function(value,element){
|
||||
// 校验出生日期
|
||||
jQuery.validator.addMethod("isBirth",function(value,element) {
|
||||
var birth = /^(19|20)\d{2}-(1[0-2]|0?[1-9])-(0?[1-9]|[1-2][0-9]|3[0-1])$/;
|
||||
return this.optional(element) || (birth).test(value);
|
||||
},"出生日期格式示例2000-01-01");
|
||||
//校验IP地址
|
||||
jQuery.validator.addMethod("isIp",function(value,element){
|
||||
// 校验IP地址
|
||||
jQuery.validator.addMethod("isIp",function(value,element) {
|
||||
var ip = /^(?:(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:1[0-9][0-9]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:2[0-4][0-9])|(?:25[0-5])|(?:1[0-9][0-9])|(?:[1-9][0-9])|(?:[0-9]))$/;
|
||||
return this.optional(element) || (ip).test(value);
|
||||
},"IP地址格式示例127.0.0.1");
|
||||
@ -53,7 +57,7 @@ $(document).ready(function(){
|
||||
jQuery.validator.addMethod("gt", function(value, element, param) {
|
||||
return value > param;
|
||||
}, $.validator.format("输入值必须大于{0}"));
|
||||
//校验新旧密码是否相同
|
||||
// 校验新旧密码是否相同
|
||||
jQuery.validator.addMethod("isdiff",function(){
|
||||
var p1=$("#pwdOld").val();
|
||||
var p2=$("#pwdNew").val();
|
||||
@ -63,7 +67,7 @@ $(document).ready(function(){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
//校验新密码和确认密码是否相同
|
||||
// 校验新密码和确认密码是否相同
|
||||
jQuery.validator.addMethod("issame",function(){
|
||||
var p3=$("#confirm_password").val();
|
||||
var p4=$("#pwdNew").val();
|
||||
@ -73,7 +77,7 @@ $(document).ready(function(){
|
||||
return false;
|
||||
}
|
||||
});
|
||||
//校验基础信息表单
|
||||
// 校验基础信息表单
|
||||
$("#basicInfoForm").validate({
|
||||
errorElement:'span',
|
||||
errorClass:'help-block error-mes',
|
||||
@ -133,11 +137,11 @@ $(document).ready(function(){
|
||||
}
|
||||
});
|
||||
|
||||
//校验修改密码表单
|
||||
// 校验修改密码表单
|
||||
$("#modifyPwd").validate({
|
||||
onfocusout: function(element) { $(element).valid()},
|
||||
debug:false, //表示校验通过后是否直接提交表单
|
||||
onkeyup:false, //表示按键松开时候监听验证
|
||||
debug:false, // 表示校验通过后是否直接提交表单
|
||||
onkeyup:false, // 表示按键松开时候监听验证
|
||||
rules:{
|
||||
pwdOld:{
|
||||
required:true,
|
||||
|
@ -150,12 +150,26 @@ body.signin {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.form-control{
|
||||
border-radius: 1px!important;
|
||||
padding: 6px 12px!important;
|
||||
height: 34px!important;
|
||||
.form-control {
|
||||
border-radius: 1px!important;
|
||||
padding: 6px 12px!important;
|
||||
height: 34px!important;
|
||||
}
|
||||
|
||||
.form-control:focus{
|
||||
.form-control:focus {
|
||||
border-color: #1ab394 !important;
|
||||
}
|
||||
|
||||
body .layer-ext-moon-msg[type="dialog"]{
|
||||
min-width: 100px !important;
|
||||
}
|
||||
body .layer-ext-moon-msg {
|
||||
background-color: rgba(0,0,0,0.6);
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
body .layer-ext-moon-msg .layui-layer-content{
|
||||
padding: 12px 25px;
|
||||
text-align: center;
|
||||
}
|
@ -1 +1 @@
|
||||
html{height:100%}body.signin{height:auto;background:url(../img/login-background.jpg) no-repeat center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}.signinpanel{width:750px;margin:10% auto 0;color:rgba(255,255,255,.95)}.signinpanel .logopanel{float:none;width:auto;padding:0;background:0}.signinpanel .signin-info ul{list-style:none;padding:0;margin:20px 0}.signinpanel .form-control{display:block;margin-top:15px}.signinpanel .uname{background:#fff url(../img/user.png) no-repeat 95% center;color:#333}.signinpanel .pword{background:#fff url(../img/locked.png) no-repeat 95% center;color:#333}.signinpanel .code{background:#fff no-repeat 95% center;color:#333;margin:0 0 15px 0}.signinpanel .btn{margin-top:15px}.signinpanel form{background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.3);-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);box-shadow:0 3px 0 rgba(12,12,12,.03);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:30px}.signup-footer{border-top:solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top:15px}@media screen and (max-width:768px){.signinpanel,.signuppanel{margin:0 auto;width:380px!important;padding:20px}.signinpanel form{margin-top:20px}.signup-footer,.signuppanel .form-control{margin-bottom:10px}.signup-footer .pull-left,.signup-footer .pull-right{float:none!important;text-align:center}.signinpanel .signin-info ul{display:none}}@media screen and (max-width:320px){.signinpanel,.signuppanel{margin:0 20px;width:auto}}.checkbox-custom{position:relative;padding:0 15px 0 25px;margin-bottom:7px;display:inline-block}.checkbox-custom input[type="checkbox"]{opacity:0;position:absolute;cursor:pointer;z-index:2;margin:-6px 0 0 0;top:50%;left:3px}.checkbox-custom label:before{content:'';position:absolute;top:50%;left:0;margin-top:-9px;width:18px;height:17px;display:inline-block;border-radius:2px;border:1px solid #bbb;background:#fff}.checkbox-custom input[type="checkbox"]:checked+label:after{position:absolute;display:inline-block;font-family:'Glyphicons Halflings';content:"\e013";top:42%;left:3px;margin-top:-5px;font-size:11px;line-height:1;width:16px;height:16px;color:#333}.checkbox-custom label{cursor:pointer;line-height:1.2;font-weight:normal;margin-bottom:0;text-align:left}.form-control,.form-control:focus,.has-error .form-control:focus,.has-success .form-control:focus,.has-warning .form-control:focus,.navbar-collapse,.navbar-form,.navbar-form-custom .form-control:focus,.navbar-form-custom .form-control:hover,.open .btn.dropdown-toggle,.panel,.popover,.progress,.progress-bar{box-shadow:none}.form-control{border-radius:1px!important;padding:6px 12px!important;height:34px!important}.form-control:focus{border-color:#1ab394!important}
|
||||
html{height:100%}body.signin{height:auto;background:url(../img/login-background.jpg) no-repeat center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}.signinpanel{width:750px;margin:10% auto 0;color:rgba(255,255,255,.95)}.signinpanel .logopanel{float:none;width:auto;padding:0;background:0}.signinpanel .signin-info ul{list-style:none;padding:0;margin:20px 0}.signinpanel .form-control{display:block;margin-top:15px}.signinpanel .uname{background:#fff url(../img/user.png) no-repeat 95% center;color:#333}.signinpanel .pword{background:#fff url(../img/locked.png) no-repeat 95% center;color:#333}.signinpanel .code{background:#fff no-repeat 95% center;color:#333;margin:0 0 15px 0}.signinpanel .btn{margin-top:15px}.signinpanel form{background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.3);-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);box-shadow:0 3px 0 rgba(12,12,12,.03);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:30px}.signup-footer{border-top:solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top:15px}@media screen and (max-width:768px){.signinpanel,.signuppanel{margin:0 auto;width:380px!important;padding:20px}.signinpanel form{margin-top:20px}.signup-footer,.signuppanel .form-control{margin-bottom:10px}.signup-footer .pull-left,.signup-footer .pull-right{float:none!important;text-align:center}.signinpanel .signin-info ul{display:none}}@media screen and (max-width:320px){.signinpanel,.signuppanel{margin:0 20px;width:auto}}.checkbox-custom{position:relative;padding:0 15px 0 25px;margin-bottom:7px;display:inline-block}.checkbox-custom input[type="checkbox"]{opacity:0;position:absolute;cursor:pointer;z-index:2;margin:-6px 0 0 0;top:50%;left:3px}.checkbox-custom label:before{content:'';position:absolute;top:50%;left:0;margin-top:-9px;width:18px;height:17px;display:inline-block;border-radius:2px;border:1px solid #bbb;background:#fff}.checkbox-custom input[type="checkbox"]:checked+label:after{position:absolute;display:inline-block;font-family:'Glyphicons Halflings';content:"\e013";top:42%;left:3px;margin-top:-5px;font-size:11px;line-height:1;width:16px;height:16px;color:#333}.checkbox-custom label{cursor:pointer;line-height:1.2;font-weight:normal;margin-bottom:0;text-align:left}.form-control,.form-control:focus,.has-error .form-control:focus,.has-success .form-control:focus,.has-warning .form-control:focus,.navbar-collapse,.navbar-form,.navbar-form-custom .form-control:focus,.navbar-form-custom .form-control:hover,.open .btn.dropdown-toggle,.panel,.popover,.progress,.progress-bar{box-shadow:none}.form-control{border-radius:1px!important;padding:6px 12px!important;height:34px!important}.form-control:focus{border-color:#1ab394!important}body .layer-ext-moon-msg[type="dialog"]{min-width:100px!important}body .layer-ext-moon-msg{background-color:rgba(0,0,0,0.6);color:#fff;border:0}body .layer-ext-moon-msg .layui-layer-content{padding:12px 25px;text-align:center}
|
@ -384,12 +384,12 @@ label.error {
|
||||
position: relative;
|
||||
padding-left: 25px;
|
||||
padding-right: 15px;
|
||||
padding-top: 8px;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.icheckbox, .icheckbox-blue, .iradio, .iradio-blue, .iradio-purple {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
top: 7px;
|
||||
left: 0
|
||||
}
|
||||
|
||||
@ -1067,7 +1067,7 @@ table.rc-table-resizing thead > th > a {
|
||||
}
|
||||
|
||||
/** 表格行拖拽样式 **/
|
||||
.reorder_rows_onDragClass td {
|
||||
.reorder-rows-on-drag-class td {
|
||||
color:yellow!important;
|
||||
background-color:#999!important;
|
||||
text-shadow:0 0 10px black,0 0 10px black,0 0 8px black,0 0 6px black,0 0 6px black;
|
||||
|
@ -2,11 +2,6 @@
|
||||
* 首页方法封装处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
layer.config({
|
||||
extend: 'moon/style.css',
|
||||
skin: 'layer-ext-moon'
|
||||
});
|
||||
|
||||
var isMobile = false;
|
||||
var sidebarHeight = isMobile ? '100%' : '96%';
|
||||
|
||||
@ -61,7 +56,7 @@ $(window).bind("load resize", function() {
|
||||
$(".slimScrollDiv").css({ "overflow": "hidden" });
|
||||
$('.navbar-static-side').fadeOut();
|
||||
} else {
|
||||
if($('body').hasClass('canvas-menu')) {
|
||||
if ($('body').hasClass('canvas-menu')) {
|
||||
$('body').addClass('fixed-sidebar');
|
||||
$('body').removeClass('canvas-menu');
|
||||
$("body").removeClass("mini-navbar");
|
||||
@ -118,7 +113,7 @@ function fixedSidebar() {
|
||||
|
||||
// 设置锚点
|
||||
function setIframeUrl(href) {
|
||||
if($.common.equals("history", mode)) {
|
||||
if ($.common.equals("history", mode)) {
|
||||
storage.set('publicPath', href);
|
||||
} else {
|
||||
var nowUrl = window.location.href;
|
||||
@ -353,7 +348,6 @@ $(function() {
|
||||
var panelUrl = $(this).parents('.menuTab').data('panel');
|
||||
// 当前元素处于活动状态
|
||||
if ($(this).parents('.menuTab').hasClass('active')) {
|
||||
syncMenuTab($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
|
||||
// 当前元素后面有同辈元素,使后面的一个元素处于活动状态
|
||||
if ($(this).parents('.menuTab').next('.menuTab').length) {
|
||||
@ -407,7 +401,7 @@ $(function() {
|
||||
}
|
||||
});
|
||||
|
||||
if($.common.isNotEmpty(panelUrl)){
|
||||
if ($.common.isNotEmpty(panelUrl)) {
|
||||
$('.menuTab[data-id="' + panelUrl + '"]').addClass('active').siblings('.menuTab').removeClass('active');
|
||||
$('.mainContent .RuoYi_iframe').each(function() {
|
||||
if ($(this).data('id') == panelUrl) {
|
||||
@ -432,7 +426,7 @@ $(function() {
|
||||
});
|
||||
}
|
||||
scrollToTab($('.menuTab.active'));
|
||||
syncMenuTab($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
syncMenuTab($.common.isNotEmpty(panelUrl) ? panelUrl : $('.page-tabs-content').find('.active').attr('data-id'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5,16 +5,10 @@
|
||||
|
||||
var startLayDate;
|
||||
var endLayDate;
|
||||
var isScrollToTop = parent.isScrollToTop;
|
||||
|
||||
$(function() {
|
||||
|
||||
// layer扩展皮肤
|
||||
if (window.layer !== undefined) {
|
||||
layer.config({
|
||||
extend: 'moon/style.css',
|
||||
skin: 'layer-ext-moon'
|
||||
});
|
||||
}
|
||||
|
||||
// 回到顶部绑定
|
||||
if ($.fn.toTop !== undefined) {
|
||||
$('#scroll-up').toTop();
|
||||
@ -48,7 +42,7 @@ $(function() {
|
||||
});
|
||||
|
||||
// laydate 时间控件绑定
|
||||
if ($(".select-time").length > 0) {
|
||||
if ($(".select-time").length > 0 && $('#startTime').length > 0 && $('#endTime').length > 0) {
|
||||
layui.use('laydate', function() {
|
||||
var laydate = layui.laydate;
|
||||
startLayDate = laydate.render({
|
||||
@ -231,7 +225,7 @@ var refreshItem = function(){
|
||||
/** 关闭选项卡 */
|
||||
var closeItem = function(dataId){
|
||||
var topWindow = $(window.parent.document);
|
||||
if($.common.isNotEmpty(dataId)){
|
||||
if ($.common.isNotEmpty(dataId)) {
|
||||
window.parent.$.modal.closeLoading();
|
||||
// 根据dataId关闭指定选项卡
|
||||
$('.menuTab[data-id="' + dataId + '"]', topWindow).remove();
|
||||
@ -241,7 +235,7 @@ var closeItem = function(dataId){
|
||||
}
|
||||
var panelUrl = window.frameElement.getAttribute('data-panel');
|
||||
$('.page-tabs-content .active i', topWindow).click();
|
||||
if($.common.isNotEmpty(panelUrl)){
|
||||
if ($.common.isNotEmpty(panelUrl)) {
|
||||
$('.menuTab[data-id="' + panelUrl + '"]', topWindow).addClass('active').siblings('.menuTab').removeClass('active');
|
||||
$('.mainContent .RuoYi_iframe', topWindow).each(function() {
|
||||
if ($(this).data('id') == panelUrl) {
|
||||
@ -288,7 +282,7 @@ 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 (parent.isScrollToTop) {
|
||||
if (isScrollToTop) {
|
||||
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
|
||||
} else {
|
||||
$('.mainContent', topWindow).find('iframe.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"}).parents('.mainContent').append(str1);
|
||||
@ -363,7 +357,7 @@ function activeWindow() {
|
||||
}
|
||||
|
||||
function openToCurrentTab(obj) {
|
||||
if (parent.isScrollToTop) {
|
||||
if (isScrollToTop) {
|
||||
$(obj).show().siblings('.RuoYi_iframe').hide();
|
||||
} else {
|
||||
$(obj).css({"visibility": "visible", "position": "static"}).siblings('.RuoYi_iframe').css({"visibility": "hidden", "position": "absolute"});
|
||||
@ -373,22 +367,22 @@ function openToCurrentTab(obj) {
|
||||
/** 密码规则范围验证 */
|
||||
function checkpwd(chrtype, password) {
|
||||
if (chrtype == 1) {
|
||||
if(!$.common.numValid(password)){
|
||||
if (!$.common.numValid(password)) {
|
||||
$.modal.alertWarning("密码只能为0-9数字");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 2) {
|
||||
if(!$.common.enValid(password)){
|
||||
if (!$.common.enValid(password)) {
|
||||
$.modal.alertWarning("密码只能为a-z和A-Z字母");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 3) {
|
||||
if(!$.common.enNumValid(password)){
|
||||
if (!$.common.enNumValid(password)) {
|
||||
$.modal.alertWarning("密码必须包含字母以及数字");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 4) {
|
||||
if(!$.common.charValid(password)){
|
||||
if (!$.common.charValid(password)) {
|
||||
$.modal.alertWarning("密码必须包含字母、数字、以及特殊符号<font color='red'>~!@#$%^&*()-=_+</font>");
|
||||
return false;
|
||||
}
|
||||
@ -398,14 +392,14 @@ function checkpwd(chrtype, password) {
|
||||
|
||||
/** 开始时间/时分秒 */
|
||||
function beginOfTime(date) {
|
||||
if($.common.isNotEmpty(date)) {
|
||||
if ($.common.isNotEmpty(date)) {
|
||||
return $.common.sprintf("%s 00:00:00", date);
|
||||
}
|
||||
}
|
||||
|
||||
/** 结束时间/时分秒 */
|
||||
function endOfTime(date) {
|
||||
if($.common.isNotEmpty(date)) {
|
||||
if ($.common.isNotEmpty(date)) {
|
||||
return $.common.sprintf("%s 23:59:59", date);
|
||||
}
|
||||
}
|
||||
|
@ -48,11 +48,11 @@ var table = {
|
||||
paginationLoop: false,
|
||||
pageSize: 10,
|
||||
pageNumber: 1,
|
||||
pageList: [10, 25, 50],
|
||||
pageList: [10, 25, 50, 100],
|
||||
toolbar: "toolbar",
|
||||
loadingFontSize: 13,
|
||||
striped: false,
|
||||
escape: false,
|
||||
escape: true,
|
||||
firstLoad: true,
|
||||
showFooter: false,
|
||||
search: false,
|
||||
@ -103,6 +103,7 @@ var table = {
|
||||
showFooter: options.showFooter, // 是否显示表尾
|
||||
iconSize: 'outline', // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
|
||||
toolbar: '#' + options.toolbar, // 指定工作栏
|
||||
virtualScroll: options.virtualScroll, // 是否启动虚拟滚动(大量数据纯展示时使用)
|
||||
loadingFontSize: options.loadingFontSize, // 自定义加载文本的字体大小
|
||||
sidePagination: options.sidePagination, // server启用服务端分页client客户端分页
|
||||
search: options.search, // 是否显示搜索框功能
|
||||
@ -318,7 +319,7 @@ var table = {
|
||||
_value = _value.replace(/\'/g,"'");
|
||||
_value = _value.replace(/\"/g,""");
|
||||
var actions = [];
|
||||
actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;width:5px;z-index:-1" type="text" value="%s"/>', _value));
|
||||
actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;z-index:-1" type="text" value="%s"/>', _value));
|
||||
actions.push($.common.sprintf('<a href="###" class="tooltip-show" data-toggle="tooltip" data-target="%s" title="%s">%s</a>', _target, _value, _text));
|
||||
return actions.join('');
|
||||
} else {
|
||||
@ -365,7 +366,7 @@ var table = {
|
||||
if ($.common.isNotEmpty(pageSize)) {
|
||||
params.pageSize = pageSize;
|
||||
}
|
||||
if ($.common.isNotEmpty(tableId)){
|
||||
if ($.common.isNotEmpty(tableId)) {
|
||||
$("#" + tableId).bootstrapTable('refresh', params);
|
||||
} else{
|
||||
$("#" + table.options.id).bootstrapTable('refresh', params);
|
||||
@ -425,7 +426,7 @@ var table = {
|
||||
shadeClose: true,
|
||||
btn1: function(index, layero){
|
||||
var file = layero.find('#file').val();
|
||||
if (file == '' || (!$.common.endWith(file, '.xls') && !$.common.endWith(file, '.xlsx'))){
|
||||
if (file == '' || (!$.common.endWith(file, '.xls') && !$.common.endWith(file, '.xlsx'))) {
|
||||
$.modal.msgWarning("请选择后缀为 “xls”或“xlsx”的文件。");
|
||||
return false;
|
||||
}
|
||||
@ -806,7 +807,7 @@ var table = {
|
||||
},
|
||||
// 获取iframe页的DOM
|
||||
getChildFrame: function (index) {
|
||||
if ($.common.isEmpty(index)){
|
||||
if ($.common.isEmpty(index)) {
|
||||
var index = parent.layer.getFrameIndex(window.name);
|
||||
return parent.layer.getChildFrame('body', index);
|
||||
} else {
|
||||
@ -815,7 +816,7 @@ var table = {
|
||||
},
|
||||
// 关闭窗体
|
||||
close: function (index) {
|
||||
if ($.common.isEmpty(index)){
|
||||
if ($.common.isEmpty(index)) {
|
||||
var index = parent.layer.getFrameIndex(window.name);
|
||||
parent.layer.close(index);
|
||||
} else {
|
||||
@ -919,6 +920,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表示不显示按钮
|
||||
|
@ -8,18 +8,15 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$.validator.setDefaults({
|
||||
submitHandler: function() {
|
||||
login();
|
||||
}
|
||||
});
|
||||
|
||||
function login() {
|
||||
$.modal.loading($("#btnSubmit").data("loading"));
|
||||
var username = $.common.trim($("input[name='username']").val());
|
||||
var password = $.common.trim($("input[name='password']").val());
|
||||
var validateCode = $("input[name='validateCode']").val();
|
||||
var rememberMe = $("input[name='rememberme']").is(':checked');
|
||||
if($.common.isEmpty(validateCode) && captchaEnabled) {
|
||||
$.modal.msg("请输入验证码");
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: ctx + "login",
|
||||
@ -29,13 +26,16 @@ function login() {
|
||||
"validateCode": validateCode,
|
||||
"rememberMe": rememberMe
|
||||
},
|
||||
beforeSend: function () {
|
||||
$.modal.loading($("#btnSubmit").data("loading"));
|
||||
},
|
||||
success: function(r) {
|
||||
if (r.code == web_status.SUCCESS) {
|
||||
location.href = ctx + 'index';
|
||||
} else {
|
||||
$('.imgcode').click();
|
||||
$(".code").val("");
|
||||
$.modal.msg(r.msg);
|
||||
$('.imgcode').click();
|
||||
$(".code").val("");
|
||||
$.modal.msg(r.msg);
|
||||
}
|
||||
$.modal.closeLoading();
|
||||
}
|
||||
@ -60,6 +60,9 @@ function validateRule() {
|
||||
password: {
|
||||
required: icon + "请输入您的密码",
|
||||
}
|
||||
},
|
||||
submitHandler: function(form) {
|
||||
login();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -7,17 +7,14 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$.validator.setDefaults({
|
||||
submitHandler: function() {
|
||||
register();
|
||||
}
|
||||
});
|
||||
|
||||
function register() {
|
||||
$.modal.loading($("#btnSubmit").data("loading"));
|
||||
var username = $.common.trim($("input[name='username']").val());
|
||||
var password = $.common.trim($("input[name='password']").val());
|
||||
var validateCode = $("input[name='validateCode']").val();
|
||||
if($.common.isEmpty(validateCode) && captchaEnabled) {
|
||||
$.modal.msg("请输入验证码");
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: ctx + "register",
|
||||
@ -26,6 +23,9 @@ function register() {
|
||||
"password": password,
|
||||
"validateCode": validateCode
|
||||
},
|
||||
beforeSend: function () {
|
||||
$.modal.loading($("#btnSubmit").data("loading"));
|
||||
},
|
||||
success: function(r) {
|
||||
if (r.code == web_status.SUCCESS) {
|
||||
layer.alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", {
|
||||
@ -57,7 +57,8 @@ function validateRule() {
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
minlength: 5
|
||||
minlength: 5,
|
||||
specialSign: true
|
||||
},
|
||||
confirmPassword: {
|
||||
required: true,
|
||||
@ -77,6 +78,9 @@ function validateRule() {
|
||||
required: icon + "请再次输入您的密码",
|
||||
equalTo: icon + "两次密码输入不一致"
|
||||
}
|
||||
},
|
||||
submitHandler: function(form) {
|
||||
register();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -91,7 +91,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="font-noraml">分组多选</label>
|
||||
<label class="font-noraml">分组单选</label>
|
||||
<select class="form-control noselect2 selectpicker">
|
||||
<optgroup label="--请选择开发语言--">
|
||||
<option value="Java">Java</option>
|
||||
|
@ -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.8
|
||||
<b>当前版本:</b>v4.7.9
|
||||
</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.8
|
||||
<b>当前版本:</b>v4.7.9
|
||||
</p>
|
||||
<p>
|
||||
<span class="label label-warning">开源免费</span>
|
||||
|
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
|
||||
<head>
|
||||
<th:block th:include="include :: header('表格保存状态')" />
|
||||
</head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table" data-cookie="true" data-cookie-id-table="userTableId"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-cookie-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
var datas = [[${@dict.getType('sys_normal_disable')}]];
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
search: true,
|
||||
showSearch: false,
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
columns: [{
|
||||
field: 'state',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field : 'userId',
|
||||
title : '用户ID'
|
||||
},
|
||||
{
|
||||
field : 'userCode',
|
||||
title : '用户编号'
|
||||
},
|
||||
{
|
||||
field : 'userName',
|
||||
title : '用户姓名'
|
||||
},
|
||||
{
|
||||
field : 'userPhone',
|
||||
title : '用户手机'
|
||||
},
|
||||
{
|
||||
field : 'userEmail',
|
||||
title : '用户邮箱'
|
||||
},
|
||||
{
|
||||
field : 'userBalance',
|
||||
title : '用户余额'
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '用户状态',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
var actions = [];
|
||||
actions.push('<a class="btn btn-success btn-xs" href="javascript:;"><i class="fa fa-edit"></i>编辑</a> ');
|
||||
actions.push('<a class="btn btn-danger btn-xs" href="javascript:;"><i class="fa fa-remove"></i>删除</a>');
|
||||
return actions.join('');
|
||||
}
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -9,7 +9,7 @@
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table" data-page-size="10"
|
||||
data-show-custom-view="true" data-custom-view="customViewFormatter"
|
||||
data-show-custom-view-button="true">
|
||||
data-custom-view-default-view="true">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
|
||||
<head>
|
||||
<th:block th:include="include :: header('全文搜索')" />
|
||||
</head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table" data-page-size="10" data-search-align="left"
|
||||
data-show-custom-view="true" data-custom-view="customViewFormatter"
|
||||
data-custom-view-default-view="true">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="textSearchTemplate">
|
||||
<div class="col-sm-12">
|
||||
<p style="margin-top:10px;line-height:1.5;">
|
||||
<span style="color:blue;font-size:medium">%title%</span><br>
|
||||
<span style="color:#000000;font-size:medium">%content%</span><br>
|
||||
<span style="color:#008000;font-size:medium">
|
||||
档号:<a href="javascript:void(0)" onclick="handleView('%tableId%', '%archiveNo%')">%archiveNo%</a>
|
||||
%docNo%
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-custom-view-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/text/list",
|
||||
search: true,
|
||||
showSearch: false,
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
showExport: true,
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field : 'tableId',
|
||||
title : '编号',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field : 'archiveNo',
|
||||
title : '档号'
|
||||
},
|
||||
{
|
||||
field : 'docNo',
|
||||
title : '文件编号'
|
||||
},
|
||||
{
|
||||
field : 'title',
|
||||
title : '标题',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value, 20, "open");
|
||||
}
|
||||
},
|
||||
{
|
||||
field : 'content',
|
||||
title : '内容',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value, 30, "open");
|
||||
}
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
function customViewFormatter (data) {
|
||||
var template = $('#textSearchTemplate').html()
|
||||
var view = ''
|
||||
if(data.length > 0) {
|
||||
$.each(data, function (i, row) {
|
||||
view += template.replace('%tableId%', row.tableId)
|
||||
.replaceAll('%archiveNo%', row.archiveNo)
|
||||
.replace('%title%', row.title)
|
||||
.replace('%docNo%', row.docNo)
|
||||
.replace('%content%', truncateString(row.content, 500))
|
||||
})
|
||||
return `<div class="row mx-0">${view}</div>`;
|
||||
} else {
|
||||
return `<div class="row mx-0"><div class="col-sm-12"><p style="margin-top:10px;line-height:1.5;"><span style="font-size:medium">没有找到记录。请检查过滤条件。</span></p></div></div>`
|
||||
}
|
||||
}
|
||||
|
||||
function handleView(tableId, archiveNo) {
|
||||
alert("tableId:" + tableId + ",archiveNo:" + archiveNo);
|
||||
}
|
||||
|
||||
function truncateString(str, maxLength) {
|
||||
if (str.length > maxLength) {
|
||||
return str.slice(0, maxLength) + '...';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.search-input').css('width', '320px');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
|
||||
<head>
|
||||
<th:block th:include="include :: header('表格虚拟滚动')" />
|
||||
</head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
<div class="btn-group-sm" id="toolbar" role="group">
|
||||
<a class="btn btn-success" onclick="loadRows()">
|
||||
<i class="fa fa-plus"></i> 加载10000行数据
|
||||
</a>
|
||||
<a class="btn btn-info" onclick="appendRows()">
|
||||
<i class="fa fa-edit"></i> 追加10000行数据
|
||||
</a>
|
||||
<span id="total" class="badge badge-success"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<script>
|
||||
var total = 0
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
data: getData(20),
|
||||
height: 400,
|
||||
sidePagination: "client",
|
||||
pagination: false,
|
||||
showSearch: false,
|
||||
virtualScroll: true,
|
||||
columns: [{
|
||||
field : 'userId',
|
||||
title : '用户ID'
|
||||
},
|
||||
{
|
||||
field : 'userCode',
|
||||
title : '用户编号'
|
||||
},
|
||||
{
|
||||
field : 'userName',
|
||||
title : '用户姓名'
|
||||
},
|
||||
{
|
||||
field : 'userPhone',
|
||||
title : '用户手机'
|
||||
},
|
||||
{
|
||||
field : 'userEmail',
|
||||
title : '用户邮箱'
|
||||
},
|
||||
{
|
||||
field : 'userBalance',
|
||||
title : '用户余额'
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
function getData(number, isAppend) {
|
||||
if (!isAppend) {
|
||||
total = 0
|
||||
}
|
||||
var data = []
|
||||
for (var i = total; i < total + number; i++) {
|
||||
var randomId = 100 + ~~ (Math.random() * 100);
|
||||
data.push({
|
||||
userId: i + 1,
|
||||
userCode: 2000000 + randomId,
|
||||
userName: '测试' + randomId,
|
||||
userPhone: '1588888888',
|
||||
userEmail: 'ry1@qq.com',
|
||||
userBalance: 10 + randomId,
|
||||
})
|
||||
}
|
||||
if (isAppend) {
|
||||
total += number
|
||||
} else {
|
||||
total = number
|
||||
}
|
||||
$('#total').text(total);
|
||||
return data;
|
||||
}
|
||||
|
||||
function loadRows() {
|
||||
$('#bootstrap-table').bootstrapTable('load', getData(10000))
|
||||
}
|
||||
|
||||
function appendRows() {
|
||||
$('#bootstrap-table').bootstrapTable('append', getData(10000, true))
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -9,10 +9,10 @@
|
||||
<link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/font-awesome.min.css?v=4.7.0}" rel="stylesheet"/>
|
||||
<!-- bootstrap-table 表格插件样式 -->
|
||||
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.18.3}" rel="stylesheet"/>
|
||||
<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.8}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
|
||||
</head>
|
||||
|
||||
<!-- 通用JS -->
|
||||
@ -22,22 +22,22 @@
|
||||
<script th:src="@{/js/jquery.min.js?v=3.6.3}"></script>
|
||||
<script th:src="@{/js/bootstrap.min.js?v=3.3.7}"></script>
|
||||
<!-- bootstrap-table 表格插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=1.22.6}"></script>
|
||||
<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>
|
||||
<!-- bootstrap-table 表格树插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.22.6}"></script>
|
||||
<!-- 遮罩层 -->
|
||||
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script>
|
||||
<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.8}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.8}"></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>
|
||||
</div>
|
||||
|
||||
<!-- ztree树插件 -->
|
||||
@ -170,20 +170,20 @@
|
||||
|
||||
<!-- 表格行拖拽插件 -->
|
||||
<div th:fragment="bootstrap-table-reorder-rows-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js?v=1.22.6}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-rows/jquery.tablednd.js?v=1.0.3}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格列拖拽插件 -->
|
||||
<div th:fragment="bootstrap-table-reorder-columns-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-columns/jquery.dragtable.js?v=5.3.5}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格列宽拖动插件 -->
|
||||
<div th:fragment="bootstrap-table-resizable-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/resizable/jquery.resizableColumns.min.js?v=0.1.0}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格行内编辑插件 -->
|
||||
@ -192,31 +192,36 @@
|
||||
</div>
|
||||
<div th:fragment="bootstrap-table-editable-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js?v=1.5.1}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格导出插件 -->
|
||||
<div th:fragment="bootstrap-table-export-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js?v=1.22.6}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/tableExport.min.js?v=1.10.24}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格冻结列插件 -->
|
||||
<div th:fragment="bootstrap-table-fixed-columns-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格自动刷新插件 -->
|
||||
<div th:fragment="bootstrap-table-auto-refresh-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格打印插件 -->
|
||||
<div th:fragment="bootstrap-table-print-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格视图分页插件 -->
|
||||
<div th:fragment="bootstrap-table-custom-view-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js?v=1.18.3}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格保存状态插件 -->
|
||||
<div th:fragment="bootstrap-table-cookie-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js?v=1.22.6}"></script>
|
||||
</div>
|
||||
|
@ -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.8}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" 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">
|
||||
@ -125,8 +125,10 @@
|
||||
<li><a class="menuItem" th:href="@{/demo/table/footer}">数据汇总</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/groupHeader}">组合表头</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/export}">表格导出</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/textSearch}">全文索引</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/exportSelected}">导出选择列</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/remember}">翻页记住选择</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/cookie}">表格保存状态</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/pageGo}">跳转至指定页</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/params}">自定义查询参数</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/multi}">初始多表格</a></li>
|
||||
@ -147,6 +149,7 @@
|
||||
<li><a class="menuItem" th:href="@{/demo/table/refresh}">表格自动刷新</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/print}">表格打印配置</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/dynamicColumns}">表格动态列</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/virtualScroll}">表格虚拟滚动</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/customView}">自定义视图分页</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/asynTree}">异步加载表格树</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/other}">表格其他操作</a></li>
|
||||
@ -318,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.8}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.7.8}"></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/index.js?v=20201208}"></script>
|
||||
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
|
||||
<script th:src="@{/js/resize-tabs.js}"></script>
|
||||
@ -336,7 +339,7 @@ var mode = "history";
|
||||
var historyPath = storage.get("historyPath");
|
||||
// 是否页签与菜单联动
|
||||
var isLinkage = true;
|
||||
//是否页签切换滚动到顶部
|
||||
// 是否页签切换滚动到顶部
|
||||
var isScrollToTop = true;
|
||||
|
||||
// 本地主题优先,未设置取系统配置
|
||||
|
@ -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.8}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
|
||||
</head>
|
||||
<body class="fixed-sidebar full-height-layout gray-bg" th:classappend="${isMobile} ? 'canvas-menu'" style="overflow: hidden">
|
||||
<div id="wrapper">
|
||||
@ -105,8 +105,10 @@
|
||||
<li><a class="menuItem" th:href="@{/demo/table/footer}">数据汇总</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/groupHeader}">组合表头</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/export}">表格导出</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/textSearch}">全文索引</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/exportSelected}">导出选择列</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/remember}">翻页记住选择</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/cookie}">表格保存状态</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/pageGo}">跳转至指定页</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/params}">自定义查询参数</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/multi}">初始多表格</a></li>
|
||||
@ -127,6 +129,7 @@
|
||||
<li><a class="menuItem" th:href="@{/demo/table/refresh}">表格自动刷新</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/print}">表格打印配置</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/dynamicColumns}">表格动态列</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/virtualScroll}">表格虚拟滚动</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/customView}">自定义视图分页</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/asynTree}">异步加载表格树</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/other}">表格其他操作</a></li>
|
||||
@ -264,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.8}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.7.8}"></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/index.js?v=20201208}"></script>
|
||||
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
|
||||
<script th:inline="javascript">
|
||||
|
@ -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.8}"></script>
|
||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.9}"></script>
|
||||
</body>
|
||||
<script th:inline="javascript">
|
||||
var ctx = [[@{/}]];
|
||||
|
@ -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.8}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
|
||||
<!-- 360浏览器急速模式 -->
|
||||
<meta name="renderer" content="webkit">
|
||||
<!-- 避免IE使用兼容模式 -->
|
||||
@ -65,18 +65,18 @@
|
||||
</div>
|
||||
<div class="signup-footer">
|
||||
<div class="pull-left">
|
||||
Copyright © 2018-2023 ruoyi.vip All Rights Reserved. <br>
|
||||
Copyright © 2018-2024 ruoyi.vip All Rights Reserved. <br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; var captchaEnabled = [[${captchaEnabled}]];</script>
|
||||
<!--[if lte IE 8]><script>window.location.href=ctx+'html/ie.html';</script><![endif]-->
|
||||
<!-- 全局js -->
|
||||
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
|
||||
<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.8}"></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/login.js" th:src="@{/ruoyi/login.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -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> <a href="https://jq.qq.com/?_wv=1027&k=7FplYUnR" target="_blank">175104288</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,60 @@
|
||||
<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="#v479">v4.7.9</a><code class="pull-right">2024.06.06</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v479" class="panel-collapse collapse in">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>通知公告新增详细显示</li>
|
||||
<li>新增数据脱敏过滤注解</li>
|
||||
<li>新增表格示例(虚拟滚动)</li>
|
||||
<li>新增表格示例(全文检索)</li>
|
||||
<li>新增表格示例(保存状态)</li>
|
||||
<li>代码生成支持表单布局选项</li>
|
||||
<li>限制用户操作数据权限范围</li>
|
||||
<li>用户密码新增非法字符验证</li>
|
||||
<li>默认加载layer扩展皮肤</li>
|
||||
<li>未修改初始密码弹框提醒</li>
|
||||
<li>定时任务白名单配置范围缩小</li>
|
||||
<li>操作日志列表重置回第一页</li>
|
||||
<li>定时任务日志默认按时间排序</li>
|
||||
<li>Excel注解ColumnType类型新增文本</li>
|
||||
<li>Excel注解新增属性comboReadDict</li>
|
||||
<li>新增Anonymous匿名访问不鉴权注解</li>
|
||||
<li>升级oshi到最新版本6.6.1</li>
|
||||
<li>升级druid到最新版本1.2.23</li>
|
||||
<li>升级commons.io到最新版本2.13.0</li>
|
||||
<li>升级spring-framework到安全版本</li>
|
||||
<li>升级bootstrap-table到最新版本1.22.6</li>
|
||||
<li>修复重置日期时出现的异常问题</li>
|
||||
<li>修复页签关闭后存在的跳转问题</li>
|
||||
<li>修复tooltip单击复制文本不生效的问题</li>
|
||||
<li>更新缓存管理键名排序方式</li>
|
||||
<li>更新HttpUtils中的User-Agent</li>
|
||||
<li>优化自定义XSS注解匹配方式</li>
|
||||
<li>优化登录注册页面验证码验证</li>
|
||||
<li>优化数据权限自定义匹配方式</li>
|
||||
<li>优化高频率定时任务不执行问题</li>
|
||||
<li>优化树表格align属性在标题生效</li>
|
||||
<li>优化代码生成主子表关联查询方式</li>
|
||||
<li>优化导入Excel时设置dictType属性重复查缓存问题</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="#v478">v4.7.8</a><code class="pull-right">2023.11.23</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v478" class="panel-collapse collapse in">
|
||||
<div id="v478" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>用户列表新增抽屉效果详细信息</li>
|
||||
|
@ -181,7 +181,7 @@
|
||||
resetDate();
|
||||
$("#operlog-form")[0].reset();
|
||||
$("#businessTypes").selectpicker('refresh');
|
||||
$.table.search('operlog-form', 'bootstrap-table');
|
||||
$.table.search('operlog-form', 'bootstrap-table', 1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
@ -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.8}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.7.9}" rel="stylesheet"/>
|
||||
<!-- 360浏览器急速模式 -->
|
||||
<meta name="renderer" content="webkit">
|
||||
<!-- 避免IE使用兼容模式 -->
|
||||
@ -64,17 +64,18 @@
|
||||
</div>
|
||||
<div class="signup-footer">
|
||||
<div class="pull-left">
|
||||
© 2018-2023 All Rights Reserved. RuoYi <br>
|
||||
© 2018-2024 All Rights Reserved. RuoYi <br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; var captchaEnabled = [[${captchaEnabled}]];</script>
|
||||
<!-- 全局js -->
|
||||
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
|
||||
<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/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.8}"></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/register.js" th:src="@{/ruoyi/register.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -140,7 +140,7 @@
|
||||
</ul>
|
||||
</body>
|
||||
<script th:src="@{/js/jquery.min.js}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.7.8}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.7.9}"></script>
|
||||
<script type="text/javascript">
|
||||
//皮肤样式列表
|
||||
var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];
|
||||
|
@ -59,6 +59,7 @@
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
viewUrl: prefix + "/view/{id}",
|
||||
createUrl: prefix + "/add",
|
||||
updateUrl: prefix + "/edit/{id}",
|
||||
removeUrl: prefix + "/remove",
|
||||
@ -71,9 +72,12 @@
|
||||
title : '序号'
|
||||
},
|
||||
{
|
||||
field : 'noticeTitle',
|
||||
title : '公告标题'
|
||||
},
|
||||
field: 'noticeTitle',
|
||||
title: '公告标题',
|
||||
formatter: function (value, row, index) {
|
||||
return '<a href="javascript:void(0)" onclick="$.operate.view(\'' + row.noticeId + '\')">' + value + '</a>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'noticeType',
|
||||
title: '公告类型',
|
||||
|
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('公告详细')" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-content">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="mail-box-header">
|
||||
<div class="mail-tools tooltip-demo m-t-md">
|
||||
<h3 style="text-align: center">[[${notice.noticeTitle}]]</h3>
|
||||
<h5>
|
||||
<span class="pull-right font-noraml">发送时间:[[${#dates.format(notice.createTime, 'yyyy-MM-dd HH:mm:ss')}]] </span>
|
||||
<span class="font-noraml">发件人: </span>[[${notice.createBy}]]
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mail-box">
|
||||
<div class="mail-body" th:utext="${notice.noticeContent}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
</body>
|
||||
</html>
|
@ -168,7 +168,8 @@
|
||||
},
|
||||
password:{
|
||||
minlength: 5,
|
||||
maxlength: 20
|
||||
maxlength: 20,
|
||||
specialSign: true
|
||||
},
|
||||
email:{
|
||||
email:true,
|
||||
|
@ -260,7 +260,8 @@
|
||||
newPassword: {
|
||||
required: true,
|
||||
minlength: 6,
|
||||
maxlength: 20
|
||||
maxlength: 20,
|
||||
specialSign: true
|
||||
},
|
||||
confirmPassword: {
|
||||
required: true,
|
||||
|
@ -65,7 +65,8 @@
|
||||
newPassword: {
|
||||
required: true,
|
||||
minlength: 5,
|
||||
maxlength: 20
|
||||
maxlength: 20,
|
||||
specialSign: true
|
||||
},
|
||||
confirmPassword: {
|
||||
required: true,
|
||||
|
@ -31,9 +31,10 @@
|
||||
$("#form-user-resetPwd").validate({
|
||||
rules:{
|
||||
password:{
|
||||
required:true,
|
||||
required: true,
|
||||
minlength: 5,
|
||||
maxlength: 20
|
||||
maxlength: 20,
|
||||
specialSign: true
|
||||
},
|
||||
},
|
||||
focusCleanup: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('用户详细')" />
|
||||
<th:block th:include="include :: header('用户详细')" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-content">
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.7.8</version>
|
||||
<version>4.7.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
@ -91,8 +92,8 @@
|
||||
|
||||
<!-- servlet包 -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.ruoyi.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 匿名访问不鉴权注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Anonymous
|
||||
{
|
||||
}
|
@ -88,6 +88,11 @@ public @interface Excel
|
||||
*/
|
||||
public String[] combo() default {};
|
||||
|
||||
/**
|
||||
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
|
||||
*/
|
||||
public boolean comboReadDict() default false;
|
||||
|
||||
/**
|
||||
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
|
||||
*/
|
||||
@ -171,7 +176,7 @@ public @interface Excel
|
||||
|
||||
public enum ColumnType
|
||||
{
|
||||
NUMERIC(0), STRING(1), IMAGE(2);
|
||||
NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
|
||||
private final int value;
|
||||
|
||||
ColumnType(int value)
|
||||
|
@ -0,0 +1,24 @@
|
||||
package com.ruoyi.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
|
||||
import com.ruoyi.common.enums.DesensitizedType;
|
||||
|
||||
/**
|
||||
* 数据脱敏注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@JacksonAnnotationsInside
|
||||
@JsonSerialize(using = SensitiveJsonSerializer.class)
|
||||
public @interface Sensitive
|
||||
{
|
||||
DesensitizedType desensitizedType();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.common.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.ruoyi.common.config.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import com.ruoyi.common.annotation.Sensitive;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.enums.DesensitizedType;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
|
||||
/**
|
||||
* 数据脱敏序列化过滤
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
|
||||
{
|
||||
private DesensitizedType desensitizedType;
|
||||
|
||||
@Override
|
||||
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
|
||||
{
|
||||
if (desensitization())
|
||||
{
|
||||
gen.writeString(desensitizedType.desensitizer().apply(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
gen.writeString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
|
||||
throws JsonMappingException
|
||||
{
|
||||
Sensitive annotation = property.getAnnotation(Sensitive.class);
|
||||
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
|
||||
{
|
||||
this.desensitizedType = annotation.desensitizedType();
|
||||
return this;
|
||||
}
|
||||
return prov.findValueSerializer(property.getType(), property);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要脱敏处理
|
||||
*/
|
||||
private boolean desensitization()
|
||||
{
|
||||
SysUser securityUser = ShiroUtils.getSysUser();
|
||||
if (securityUser == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 管理员不脱敏
|
||||
return !securityUser.isAdmin();
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.ruoyi.common.constant;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
@ -17,6 +19,11 @@ public class Constants
|
||||
*/
|
||||
public static final String GBK = "GBK";
|
||||
|
||||
/**
|
||||
* 系统语言
|
||||
*/
|
||||
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
|
||||
|
||||
/**
|
||||
* http请求
|
||||
*/
|
||||
@ -105,11 +112,11 @@ public class Constants
|
||||
/**
|
||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||
*/
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
|
||||
|
||||
/**
|
||||
* 定时任务违规的字符
|
||||
*/
|
||||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
|
||||
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
|
||||
}
|
@ -70,7 +70,7 @@ public class ShiroConstants
|
||||
/**
|
||||
* 登录记录缓存
|
||||
*/
|
||||
public static final String LOGINRECORDCACHE = "loginRecordCache";
|
||||
public static final String LOGIN_RECORD_CACHE = "loginRecordCache";
|
||||
|
||||
/**
|
||||
* 系统活跃用户缓存
|
||||
|
@ -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";
|
||||
|
||||
|
@ -3,9 +3,9 @@ package com.ruoyi.common.core.controller;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
@ -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;
|
||||
|
||||
/** 备注 */
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
|
@ -2,7 +2,7 @@ package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.validation.constraints.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.validation.constraints.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
|
@ -2,7 +2,7 @@ package com.ruoyi.common.core.domain.entity;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.validation.constraints.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@ -23,7 +23,7 @@ public class SysUser extends BaseEntity
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 用户ID */
|
||||
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||
private Long userId;
|
||||
|
||||
/** 部门ID */
|
||||
@ -52,7 +52,7 @@ public class SysUser extends BaseEntity
|
||||
private String email;
|
||||
|
||||
/** 手机号码 */
|
||||
@Excel(name = "手机号码")
|
||||
@Excel(name = "手机号码", cellType = ColumnType.TEXT)
|
||||
private String phonenumber;
|
||||
|
||||
/** 用户性别 */
|
||||
|
@ -365,6 +365,10 @@ public class Convert
|
||||
*/
|
||||
public static String[] toStrArray(String str)
|
||||
{
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return new String[] {};
|
||||
}
|
||||
return toStrArray(",", str);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,59 @@
|
||||
package com.ruoyi.common.enums;
|
||||
|
||||
import java.util.function.Function;
|
||||
import com.ruoyi.common.utils.DesensitizedUtil;
|
||||
|
||||
/**
|
||||
* 脱敏类型
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public enum DesensitizedType
|
||||
{
|
||||
/**
|
||||
* 姓名,第2位星号替换
|
||||
*/
|
||||
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
|
||||
|
||||
/**
|
||||
* 密码,全部字符都用*代替
|
||||
*/
|
||||
PASSWORD(DesensitizedUtil::password),
|
||||
|
||||
/**
|
||||
* 身份证,中间10位星号替换
|
||||
*/
|
||||
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
|
||||
|
||||
/**
|
||||
* 手机号,中间4位星号替换
|
||||
*/
|
||||
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
|
||||
*/
|
||||
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 银行卡号,保留最后4位,其他星号替换
|
||||
*/
|
||||
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
|
||||
|
||||
/**
|
||||
* 车牌号码,包含普通车辆、新能源车辆
|
||||
*/
|
||||
CAR_LICENSE(DesensitizedUtil::carLicense);
|
||||
|
||||
private final Function<String, String> desensitizer;
|
||||
|
||||
DesensitizedType(Function<String, String> desensitizer)
|
||||
{
|
||||
this.desensitizer = desensitizer;
|
||||
}
|
||||
|
||||
public Function<String, String> desensitizer()
|
||||
{
|
||||
return desensitizer;
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@ package com.ruoyi.common.utils;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Cookie工具类
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
/**
|
||||
* 脱敏工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class DesensitizedUtil
|
||||
{
|
||||
/**
|
||||
* 密码的全部字符都用*代替,比如:******
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 脱敏后的密码
|
||||
*/
|
||||
public static String password(String password)
|
||||
{
|
||||
if (StringUtils.isBlank(password))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return StringUtils.repeat('*', password.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 车牌中间用*代替,如果是错误的车牌,不处理
|
||||
*
|
||||
* @param carLicense 完整的车牌号
|
||||
* @return 脱敏后的车牌
|
||||
*/
|
||||
public static String carLicense(String carLicense)
|
||||
{
|
||||
if (StringUtils.isBlank(carLicense))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
// 普通车牌
|
||||
if (carLicense.length() == 7)
|
||||
{
|
||||
carLicense = StringUtils.hide(carLicense, 3, 6);
|
||||
}
|
||||
else if (carLicense.length() == 8)
|
||||
{
|
||||
// 新能源车牌
|
||||
carLicense = StringUtils.hide(carLicense, 3, 7);
|
||||
}
|
||||
return carLicense;
|
||||
}
|
||||
}
|
@ -54,6 +54,10 @@ public class DictUtils
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictValue))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||
}
|
||||
|
||||
@ -66,6 +70,10 @@ public class DictUtils
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictLabel))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||
}
|
||||
|
||||
@ -81,8 +89,11 @@ public class DictUtils
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.containsAny(dictValue, separator) && StringUtils.isNotEmpty(datas))
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(dictValue, separator))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
@ -121,8 +132,11 @@ public class DictUtils
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.containsAny(dictLabel, separator) && StringUtils.isNotEmpty(datas))
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(dictLabel, separator))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
@ -149,6 +163,48 @@ public class DictUtils
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValues(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictValue()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictLabels(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定字典缓存
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.ruoyi.common.utils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 获取IP方法
|
||||
|
@ -3,7 +3,7 @@ package com.ruoyi.common.utils;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -72,10 +72,10 @@ public class LogUtils
|
||||
{
|
||||
String username = getUsername();
|
||||
|
||||
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
|
||||
String message = (String) request.getAttribute("javax.servlet.error.message");
|
||||
String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
|
||||
Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
|
||||
Integer statusCode = (Integer) request.getAttribute("jakarta.servlet.error.status_code");
|
||||
String message = (String) request.getAttribute("jakarta.servlet.error.message");
|
||||
String uri = (String) request.getAttribute("jakarta.servlet.error.request_uri");
|
||||
Throwable t = (Throwable) request.getAttribute("jakarta.servlet.error.exception");
|
||||
|
||||
if (statusCode == null)
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Map通用处理方法
|
||||
|
@ -4,9 +4,9 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
@ -23,6 +23,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
/** 下划线 */
|
||||
private static final char SEPARATOR = '_';
|
||||
|
||||
/** 星号 */
|
||||
private static final char ASTERISK = '*';
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
@ -163,6 +166,49 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
return (str == null ? "" : str.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换指定字符串的指定区间内字符为"*"
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @return 替换后的字符串
|
||||
*/
|
||||
public static String hide(CharSequence str, int startInclude, int endExclude)
|
||||
{
|
||||
if (isEmpty(str))
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
final int strLength = str.length();
|
||||
if (startInclude > strLength)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
if (endExclude > strLength)
|
||||
{
|
||||
endExclude = strLength;
|
||||
}
|
||||
if (startInclude > endExclude)
|
||||
{
|
||||
// 如果起始位置大于结束位置,不替换
|
||||
return NULLSTR;
|
||||
}
|
||||
final char[] chars = new char[strLength];
|
||||
for (int i = 0; i < strLength; i++)
|
||||
{
|
||||
if (i >= startInclude && i < endExclude)
|
||||
{
|
||||
chars[i] = ASTERISK;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars[i] = str.charAt(i);
|
||||
}
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.ruoyi.common.utils.bean;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.Validator;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.Validator;
|
||||
|
||||
/**
|
||||
* bean对象属性验证
|
||||
|
@ -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
|
||||
|
@ -9,8 +9,8 @@ import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
@ -74,7 +74,7 @@ public class HttpUtils
|
||||
URLConnection connection = realUrl.openConnection();
|
||||
connection.setRequestProperty("accept", "*/*");
|
||||
connection.setRequestProperty("connection", "Keep-Alive");
|
||||
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
connection.connect();
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
||||
String line;
|
||||
@ -136,7 +136,7 @@ public class HttpUtils
|
||||
URLConnection conn = realUrl.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("contentType", "utf-8");
|
||||
conn.setDoOutput(true);
|
||||
@ -202,7 +202,7 @@ public class HttpUtils
|
||||
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("contentType", "utf-8");
|
||||
conn.setDoOutput(true);
|
||||
|
@ -23,7 +23,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
@ -39,6 +39,7 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.DataValidation;
|
||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||
@ -193,6 +194,11 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
public Class<T> clazz;
|
||||
|
||||
/**
|
||||
* 需要显示列属性
|
||||
*/
|
||||
public String[] includeFields;
|
||||
|
||||
/**
|
||||
* 需要排除列属性
|
||||
*/
|
||||
@ -203,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)
|
||||
{
|
||||
@ -396,7 +411,7 @@ public class ExcelUtil<T>
|
||||
Object val = this.getCellValue(row, entry.getKey());
|
||||
|
||||
// 如果不存在实例则新建.
|
||||
entity = (entity == null ? clazz.newInstance() : entity);
|
||||
entity = (entity == null ? clazz.getDeclaredConstructor().newInstance() : entity);
|
||||
// 从map中得到对应列的field.
|
||||
Field field = (Field) entry.getValue()[0];
|
||||
Excel attr = (Excel) entry.getValue()[1];
|
||||
@ -470,7 +485,12 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.dictType()))
|
||||
{
|
||||
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
|
||||
if (!sysDictMap.containsKey(attr.dictType() + val))
|
||||
{
|
||||
String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
|
||||
sysDictMap.put(attr.dictType() + val, dictValue);
|
||||
}
|
||||
val = sysDictMap.get(attr.dictType() + val);
|
||||
}
|
||||
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
|
||||
{
|
||||
@ -783,6 +803,8 @@ public class ExcelUtil<T>
|
||||
titleFont.setFontHeightInPoints((short) 16);
|
||||
titleFont.setBold(true);
|
||||
style.setFont(titleFont);
|
||||
DataFormat dataFormat = wb.createDataFormat();
|
||||
style.setDataFormat(dataFormat.getFormat("@"));
|
||||
styles.put("title", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
@ -845,6 +867,9 @@ public class ExcelUtil<T>
|
||||
headerFont.setBold(true);
|
||||
headerFont.setColor(excel.headerColor().index);
|
||||
style.setFont(headerFont);
|
||||
// 设置表格头单元格文本形式
|
||||
DataFormat dataFormat = wb.createDataFormat();
|
||||
style.setDataFormat(dataFormat.getFormat("@"));
|
||||
headerStyles.put(key, style);
|
||||
}
|
||||
}
|
||||
@ -862,34 +887,66 @@ public class ExcelUtil<T>
|
||||
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
|
||||
for (Object[] os : fields)
|
||||
{
|
||||
Field field = (Field) os[0];
|
||||
Excel excel = (Excel) os[1];
|
||||
String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
|
||||
if (!styles.containsKey(key))
|
||||
if (Collection.class.isAssignableFrom(field.getType()))
|
||||
{
|
||||
CellStyle style = wb.createCellStyle();
|
||||
style.setAlignment(excel.align());
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
style.setFillForegroundColor(excel.backgroundColor().getIndex());
|
||||
Font dataFont = wb.createFont();
|
||||
dataFont.setFontName("Arial");
|
||||
dataFont.setFontHeightInPoints((short) 10);
|
||||
dataFont.setColor(excel.color().index);
|
||||
style.setFont(dataFont);
|
||||
styles.put(key, style);
|
||||
ParameterizedType pt = (ParameterizedType) field.getGenericType();
|
||||
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
|
||||
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
|
||||
for (Field subField : subFields)
|
||||
{
|
||||
Excel subExcel = subField.getAnnotation(Excel.class);
|
||||
annotationDataStyles(styles, subField, subExcel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
annotationDataStyles(styles, field, excel);
|
||||
}
|
||||
}
|
||||
return styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Excel注解创建表格列样式
|
||||
*
|
||||
* @param styles 自定义样式列表
|
||||
* @param field 属性列信息
|
||||
* @param excel 注解信息
|
||||
*/
|
||||
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
|
||||
{
|
||||
String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
|
||||
if (!styles.containsKey(key))
|
||||
{
|
||||
CellStyle style = wb.createCellStyle();
|
||||
style.setAlignment(excel.align());
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
style.setFillForegroundColor(excel.backgroundColor().getIndex());
|
||||
Font dataFont = wb.createFont();
|
||||
dataFont.setFontName("Arial");
|
||||
dataFont.setFontHeightInPoints((short) 10);
|
||||
dataFont.setColor(excel.color().index);
|
||||
style.setFont(dataFont);
|
||||
if (ColumnType.TEXT == excel.cellType())
|
||||
{
|
||||
DataFormat dataFormat = wb.createDataFormat();
|
||||
style.setDataFormat(dataFormat.getFormat("@"));
|
||||
}
|
||||
styles.put(key, style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建单元格
|
||||
*/
|
||||
@ -904,7 +961,7 @@ public class ExcelUtil<T>
|
||||
if (isSubList())
|
||||
{
|
||||
// 填充默认样式,防止合并单元格样式失效
|
||||
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
|
||||
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
|
||||
if (attr.needMerge())
|
||||
{
|
||||
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
|
||||
@ -922,7 +979,7 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
public void setCellVo(Object value, Excel attr, Cell cell)
|
||||
{
|
||||
if (ColumnType.STRING == attr.cellType())
|
||||
if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
|
||||
{
|
||||
String cellValue = Convert.toStr(value);
|
||||
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
|
||||
@ -999,17 +1056,28 @@ public class ExcelUtil<T>
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
|
||||
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
|
||||
{
|
||||
if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
|
||||
String[] comboArray = attr.combo();
|
||||
if (attr.comboReadDict())
|
||||
{
|
||||
if (!sysDictMap.containsKey("combo_" + attr.dictType()))
|
||||
{
|
||||
String labels = DictUtils.getDictLabels(attr.dictType());
|
||||
sysDictMap.put("combo_" + attr.dictType(), labels);
|
||||
}
|
||||
String val = sysDictMap.get("combo_" + attr.dictType());
|
||||
comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
|
||||
}
|
||||
if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
|
||||
{
|
||||
// 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
|
||||
setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
|
||||
setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 提示信息或只能选择不能输入的列内容.
|
||||
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
|
||||
setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1034,7 +1102,7 @@ public class ExcelUtil<T>
|
||||
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
|
||||
sheet.addMergedRegion(cellAddress);
|
||||
}
|
||||
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
|
||||
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
|
||||
|
||||
// 用于读取对象中的属性
|
||||
Object value = getTargetValue(vo, field, attr);
|
||||
@ -1282,7 +1350,7 @@ public class ExcelUtil<T>
|
||||
{
|
||||
try
|
||||
{
|
||||
Object instance = excel.handler().newInstance();
|
||||
Object instance = excel.handler().getDeclaredConstructor().newInstance();
|
||||
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
|
||||
value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
|
||||
}
|
||||
@ -1434,46 +1502,86 @@ 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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
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 });
|
||||
}
|
||||
field.setAccessible(true);
|
||||
fields.add(new Object[] { field, attr });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
|
||||
|
||||
/**
|
||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.ruoyi.common.xss;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
@ -3,14 +3,14 @@ package com.ruoyi.common.xss;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
@ -31,10 +31,10 @@ public class XssFilter implements Filter
|
||||
String tempExcludes = filterConfig.getInitParameter("excludes");
|
||||
if (StringUtils.isNotEmpty(tempExcludes))
|
||||
{
|
||||
String[] url = tempExcludes.split(",");
|
||||
for (int i = 0; url != null && i < url.length; i++)
|
||||
String[] urls = tempExcludes.split(",");
|
||||
for (String url : urls)
|
||||
{
|
||||
excludes.add(url[i]);
|
||||
excludes.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.ruoyi.common.xss;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import com.ruoyi.common.utils.html.EscapeUtil;
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.ruoyi.common.xss;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
|
||||
|
||||
public static boolean containsHtml(String value)
|
||||
{
|
||||
StringBuilder sHtml = new StringBuilder();
|
||||
Pattern pattern = Pattern.compile(HTML_PATTERN);
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
return matcher.matches();
|
||||
while (matcher.find())
|
||||
{
|
||||
sHtml.append(matcher.group());
|
||||
}
|
||||
return pattern.matcher(sHtml).matches();
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.7.8</version>
|
||||
<version>4.7.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 验证码 -->
|
||||
@ -41,7 +41,7 @@
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
@ -51,6 +51,20 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro核心框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,16 +90,22 @@ public class DataScopeAspect
|
||||
{
|
||||
StringBuilder sqlString = new StringBuilder();
|
||||
List<String> conditions = new ArrayList<String>();
|
||||
List<String> scopeCustomIds = new ArrayList<String>();
|
||||
user.getRoles().forEach(role -> {
|
||||
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()));
|
||||
}
|
||||
});
|
||||
|
||||
for (SysRole role : user.getRoles())
|
||||
{
|
||||
String dataScope = role.getDataScope();
|
||||
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
|
||||
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
|
||||
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -111,9 +117,15 @@ public class DataScopeAspect
|
||||
}
|
||||
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
||||
role.getRoleId()));
|
||||
if (scopeCustomIds.size() > 1)
|
||||
{
|
||||
// 多个自定数据权限使用in查询,避免多次拼接。
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
|
||||
}
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT.equals(dataScope))
|
||||
{
|
||||
@ -121,9 +133,7 @@ public class DataScopeAspect
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
||||
deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
}
|
||||
else if (DATA_SCOPE_SELF.equals(dataScope))
|
||||
{
|
||||
@ -140,7 +150,7 @@ public class DataScopeAspect
|
||||
conditions.add(dataScope);
|
||||
}
|
||||
|
||||
// 多角色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
||||
// 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
||||
if (StringUtils.isEmpty(conditions))
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
||||
|
@ -2,8 +2,8 @@ package com.ruoyi.framework.aspectj;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
|
@ -3,11 +3,6 @@ package com.ruoyi.framework.config;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ -16,13 +11,18 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import com.ruoyi.common.enums.DataSourceType;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.framework.config.properties.DruidProperties;
|
||||
import com.ruoyi.framework.datasource.DynamicDataSource;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
|
||||
/**
|
||||
* druid 配置多数据源
|
||||
@ -96,7 +96,7 @@ public class DruidConfig
|
||||
Filter filter = new Filter()
|
||||
{
|
||||
@Override
|
||||
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
|
||||
public void init(jakarta.servlet.FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user