Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e36334c50a | ||
|
|
9f21f8816a | ||
|
|
7aedaf2085 | ||
|
|
895c290cbf | ||
|
|
346670b197 | ||
|
|
7ad0a35ba2 | ||
|
|
0d0a2ecc5a | ||
|
|
dc82712597 | ||
|
|
9ab3a297bd | ||
|
|
03174f1ead | ||
|
|
a4b0a7c0bb | ||
|
|
4b8d578f4d | ||
|
|
b369317800 | ||
|
|
d957acd899 | ||
|
|
e7d791ddf0 | ||
|
|
a0ada99856 | ||
|
|
cdbf0e2264 | ||
|
|
134e559704 | ||
|
|
dd9b2cd617 | ||
|
|
07e2d69ebf | ||
|
|
0d65960e86 | ||
|
|
e1191c56b2 | ||
|
|
cec1d3adcb | ||
|
|
a4c4f737a8 | ||
|
|
c0c62001a9 | ||
|
|
4a64a9269a | ||
|
|
30278a0451 | ||
|
|
f80a312b9b | ||
|
|
674d236007 | ||
|
|
4e211c4871 | ||
|
|
43788e0590 | ||
|
|
8bf5140a72 | ||
|
|
3d2d88287a | ||
|
|
6d5b261c7d | ||
|
|
2eb5752cc1 | ||
|
|
43ce484f36 | ||
|
|
277d42c12b | ||
|
|
2651383ab2 | ||
|
|
25022bfef2 | ||
|
|
98ee5e9772 | ||
|
|
acbf27bc26 | ||
|
|
aa62d63920 | ||
|
|
31c3d4021e | ||
|
|
3025017d0f | ||
|
|
514ccd2c75 | ||
|
|
7a8e047c6f | ||
|
|
be3adb875f | ||
|
|
18d80cc78e | ||
|
|
b1c60695e6 | ||
|
|
4a6e5a0fba | ||
|
|
a9775607e0 | ||
|
|
d7f7da596f | ||
|
|
6c8a389f9a | ||
|
|
0f3d67367a | ||
|
|
49e20200f1 | ||
|
|
f726bf25ce | ||
|
|
7fb5382c10 | ||
|
|
e75258a72b | ||
|
|
ffc16b032d | ||
|
|
f42b8c7a83 | ||
|
|
ddbb1aa170 | ||
|
|
c8b42c5b82 | ||
|
|
7d1b67a8b7 | ||
|
|
b09955f369 | ||
|
|
e7838317d0 | ||
|
|
1aa2d7a5cc | ||
|
|
8b4aef15cf | ||
|
|
d56d6ac5ac | ||
|
|
8d165f4919 | ||
|
|
44895c3d17 | ||
|
|
29a30a25c2 | ||
|
|
77c4a350d4 | ||
|
|
a1dba1ad1c | ||
|
|
ecaf13caa3 | ||
|
|
58bbf6c36d | ||
|
|
154b8d9db8 | ||
|
|
b7aa9f3f42 | ||
|
|
44df8c4c8b | ||
|
|
23b98a3ef8 | ||
|
|
18a7915079 | ||
|
|
68b5b80299 | ||
|
|
c426de4dee | ||
|
|
92911e840e | ||
|
|
781fd7dd1a | ||
|
|
f079622e11 | ||
|
|
c52ba00f4f | ||
|
|
7c48bc3184 | ||
|
|
91986f13f8 | ||
|
|
7728ad9eb4 | ||
|
|
868aed4079 | ||
|
|
9627ba9e1d | ||
|
|
e0e305c423 | ||
|
|
ed4280379d | ||
|
|
233089b3e6 | ||
|
|
bb0e7bd563 | ||
|
|
7bca4fcbc4 | ||
|
|
1b7a735f9c | ||
|
|
829dfafdaa | ||
|
|
5a59670124 | ||
|
|
2499685a31 | ||
|
|
a3bb603382 | ||
|
|
9ad3cc0b9a | ||
|
|
690a9a6281 |
Binary file not shown.
@@ -1,38 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>4.3.0</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<shiro.version>1.4.2</shiro.version>
|
||||
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
|
||||
<mybatis.boot.version>1.3.2</mybatis.boot.version>
|
||||
<druid.version>1.1.14</druid.version>
|
||||
<bitwalker.version>1.19</bitwalker.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.70</fastjson.version>
|
||||
<oshi.version>3.9.1</oshi.version>
|
||||
<commons.io.version>2.5</commons.io.version>
|
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
</properties>
|
||||
|
||||
<ruoyi.version>4.4.0</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<shiro.version>1.6.0</shiro.version>
|
||||
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
|
||||
<mybatis.boot.version>1.3.2</mybatis.boot.version>
|
||||
<druid.version>1.1.14</druid.version>
|
||||
<bitwalker.version>1.19</bitwalker.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.73</fastjson.version>
|
||||
<oshi.version>3.9.1</oshi.version>
|
||||
<commons.io.version>2.5</commons.io.version>
|
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -47,183 +46,181 @@
|
||||
</dependency>
|
||||
|
||||
<!--阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<version>${kaptcha.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Shiro核心框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用Srping框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-ehcache</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||
<dependency>
|
||||
<groupId>com.github.theborakompanioni</groupId>
|
||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||
<version>${thymeleaf.extras.shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
<version>${bitwalker.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>${pagehelper.boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>${oshi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<version>${kaptcha.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Shiro核心框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用Srping框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-ehcache</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||
<dependency>
|
||||
<groupId>com.github.theborakompanioni</groupId>
|
||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||
<version>${thymeleaf.extras.shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
<version>${bitwalker.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>${pagehelper.boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>${oshi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 定时任务-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-quartz</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-quartz</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-admin</module>
|
||||
<module>ruoyi-framework</module>
|
||||
<module>ruoyi-system</module>
|
||||
<module>ruoyi-quartz</module>
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-admin</module>
|
||||
<module>ruoyi-framework</module>
|
||||
<module>ruoyi-system</module>
|
||||
<module>ruoyi-quartz</module>
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -238,29 +235,29 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
+37
-37
@@ -5,18 +5,18 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>ruoyi-admin</artifactId>
|
||||
|
||||
<description>
|
||||
web服务入口
|
||||
</description>
|
||||
|
||||
<description>
|
||||
web服务入口
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- SpringBoot集成thymeleaf模板 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -24,61 +24,61 @@
|
||||
</dependency>
|
||||
|
||||
<!-- spring-boot-devtools -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
<!-- 核心模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 定时任务-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -86,10 +86,10 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
</configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@@ -106,9 +106,9 @@
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warName>${project.artifactId}</warName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -49,10 +50,9 @@ public class CommonController
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
String filePath = Global.getDownloadPath() + fileName;
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, realFileName);
|
||||
|
||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||
if (delete)
|
||||
{
|
||||
@@ -103,10 +103,10 @@ public class CommonController
|
||||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
|
||||
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
||||
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -232,6 +232,24 @@ public class DemoTableController extends BaseController
|
||||
return prefix + "/subdata";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格自动刷新
|
||||
*/
|
||||
@GetMapping("/refresh")
|
||||
public String refresh()
|
||||
{
|
||||
return prefix + "/refresh";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格打印配置
|
||||
*/
|
||||
@GetMapping("/print")
|
||||
public String print()
|
||||
{
|
||||
return prefix + "/print";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格其他操作
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.web.controller.demo.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
@@ -24,6 +25,11 @@ public class GoodsModel
|
||||
* 商品价格
|
||||
*/
|
||||
private Double price;
|
||||
|
||||
/**
|
||||
* 商品日期
|
||||
*/
|
||||
private Date date;
|
||||
|
||||
/**
|
||||
* 商品种类
|
||||
@@ -60,6 +66,16 @@ public class GoodsModel
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Date getDate()
|
||||
{
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date)
|
||||
{
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
@@ -76,6 +92,7 @@ public class GoodsModel
|
||||
.append("name", getName())
|
||||
.append("weight", getWeight())
|
||||
.append("price", getPrice())
|
||||
.append("date", getDate())
|
||||
.append("type", getType())
|
||||
.toString();
|
||||
}
|
||||
|
||||
+2
-2
@@ -78,10 +78,10 @@ public class SysUserOnlineController extends BaseController
|
||||
{
|
||||
return error("当前登陆用户无法强退");
|
||||
}
|
||||
onlineSession.setStatus(OnlineStatus.off_line);
|
||||
onlineSessionDAO.update(onlineSession);
|
||||
onlineSessionDAO.delete(onlineSession);
|
||||
online.setStatus(OnlineStatus.off_line);
|
||||
userOnlineService.saveOnline(online);
|
||||
userOnlineService.removeUserCache(online.getLoginName(), sessionId);
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysRole;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.domain.SysUserRole;
|
||||
import com.ruoyi.system.service.ISysPostService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
@@ -176,7 +175,6 @@ public class SysUserController extends BaseController
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:resetPwd")
|
||||
@Log(title = "重置密码", businessType = BusinessType.UPDATE)
|
||||
@GetMapping("/resetPwd/{userId}")
|
||||
public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||
{
|
||||
@@ -212,9 +210,9 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
SysUser user = userService.selectUserById(userId);
|
||||
// 获取用户所属的角色列表
|
||||
List<SysUserRole> userRoles = userService.selectUserRoleByUserId(userId);
|
||||
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||
mmap.put("user", user);
|
||||
mmap.put("userRoles", userRoles);
|
||||
mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
return prefix + "/authRole";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 4.3.0
|
||||
version: 4.4.0
|
||||
# 版权年份
|
||||
copyrightYear: 2019
|
||||
# 实例演示开关
|
||||
@@ -108,6 +108,8 @@ shiro:
|
||||
httpOnly: true
|
||||
# 设置Cookie的过期时间,天为单位
|
||||
maxAge: 30
|
||||
# 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)KeyGenerator keygen = KeyGenerator.getInstance("AES"); SecretKey deskey = keygen.generateKey(); System.out.println(Base64.encodeToString(deskey.getEncoded()));
|
||||
cipherKey: zSyK5Kp6PZAAjlT+eeNMlg==
|
||||
session:
|
||||
# Session超时时间,-1代表永不过期(默认30分钟)
|
||||
expireTime: 30
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+5
-3
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
+1516
-294
File diff suppressed because it is too large
Load Diff
+10
File diff suppressed because one or more lines are too long
+2437
-121
File diff suppressed because it is too large
Load Diff
+10
File diff suppressed because one or more lines are too long
+1224
-77
File diff suppressed because it is too large
Load Diff
+10
File diff suppressed because one or more lines are too long
-211
@@ -1,211 +0,0 @@
|
||||
/**
|
||||
* @author: aperez <aperez@datadec.es>
|
||||
* @version: v2.0.0
|
||||
*
|
||||
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
|
||||
*/
|
||||
|
||||
!function($) {
|
||||
'use strict';
|
||||
|
||||
var firstLoad = false;
|
||||
|
||||
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||
|
||||
var showAvdSearch = function(pColumns, searchTitle, searchText, that) {
|
||||
if (!$("#avdSearchModal" + "_" + that.options.idTable).hasClass("modal")) {
|
||||
var vModal = sprintf("<div id=\"avdSearchModal%s\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">", "_" + that.options.idTable);
|
||||
vModal += "<div class=\"modal-dialog modal-xs\">";
|
||||
vModal += " <div class=\"modal-content\">";
|
||||
vModal += " <div class=\"modal-header\">";
|
||||
vModal += " <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" >×</button>";
|
||||
vModal += sprintf(" <h4 class=\"modal-title\">%s</h4>", searchTitle);
|
||||
vModal += " </div>";
|
||||
vModal += " <div class=\"modal-body modal-body-custom\">";
|
||||
vModal += sprintf(" <div class=\"container-fluid\" id=\"avdSearchModalContent%s\" style=\"padding-right: 0px;padding-left: 0px;\" >", "_" + that.options.idTable);
|
||||
vModal += " </div>";
|
||||
vModal += " </div>";
|
||||
vModal += " </div>";
|
||||
vModal += " </div>";
|
||||
vModal += "</div>";
|
||||
|
||||
$("body").append($(vModal));
|
||||
|
||||
var vFormAvd = createFormAvd(pColumns, searchText, that),
|
||||
timeoutId = 0;;
|
||||
|
||||
$('#avdSearchModalContent' + "_" + that.options.idTable).append(vFormAvd.join(''));
|
||||
|
||||
$('#' + that.options.idForm).off('keyup blur', 'input').on('keyup blur', 'input', function (event) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(function () {
|
||||
that.onColumnAdvancedSearch(event);
|
||||
}, that.options.searchTimeOut);
|
||||
});
|
||||
|
||||
$("#btnCloseAvd" + "_" + that.options.idTable).click(function() {
|
||||
$("#avdSearchModal" + "_" + that.options.idTable).modal('hide');
|
||||
});
|
||||
|
||||
$("#avdSearchModal" + "_" + that.options.idTable).modal();
|
||||
} else {
|
||||
$("#avdSearchModal" + "_" + that.options.idTable).modal();
|
||||
}
|
||||
};
|
||||
|
||||
var createFormAvd = function(pColumns, searchText, that) {
|
||||
var htmlForm = [];
|
||||
htmlForm.push(sprintf('<form class="form-horizontal" id="%s" action="%s" >', that.options.idForm, that.options.actionForm));
|
||||
for (var i in pColumns) {
|
||||
var vObjCol = pColumns[i];
|
||||
if (!vObjCol.checkbox && vObjCol.visible && vObjCol.searchable) {
|
||||
htmlForm.push('<div class="form-group">');
|
||||
htmlForm.push(sprintf('<label class="col-sm-4 control-label">%s</label>', vObjCol.title));
|
||||
htmlForm.push('<div class="col-sm-6">');
|
||||
htmlForm.push(sprintf('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">', vObjCol.field, vObjCol.title, vObjCol.field));
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</div>');
|
||||
}
|
||||
}
|
||||
|
||||
htmlForm.push('<div class="form-group">');
|
||||
htmlForm.push('<div class="col-sm-offset-9 col-sm-3">');
|
||||
htmlForm.push(sprintf('<button type="button" id="btnCloseAvd%s" class="btn btn-default" >%s</button>', "_" + that.options.idTable, searchText));
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</form>');
|
||||
|
||||
return htmlForm;
|
||||
};
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
advancedSearch: false,
|
||||
idForm: 'advancedSearch',
|
||||
actionForm: '',
|
||||
idTable: undefined,
|
||||
onColumnAdvancedSearch: function (field, text) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
advancedSearchIcon: 'glyphicon-chevron-down'
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.locales, {
|
||||
formatAdvancedSearch: function() {
|
||||
return 'Advanced search';
|
||||
},
|
||||
formatAdvancedCloseButton: function() {
|
||||
return "Close";
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
||||
|
||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||
_initToolbar = BootstrapTable.prototype.initToolbar,
|
||||
_load = BootstrapTable.prototype.load,
|
||||
_initSearch = BootstrapTable.prototype.initSearch;
|
||||
|
||||
BootstrapTable.prototype.initToolbar = function() {
|
||||
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!this.options.search) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.advancedSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.idTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this,
|
||||
html = [];
|
||||
|
||||
html.push(sprintf('<div class="columns columns-%s btn-group pull-%s" role="group">', this.options.buttonsAlign, this.options.buttonsAlign));
|
||||
html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="advancedSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatAdvancedSearch()));
|
||||
html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.advancedSearchIcon))
|
||||
html.push('</button></div>');
|
||||
|
||||
that.$toolbar.prepend(html.join(''));
|
||||
|
||||
that.$toolbar.find('button[name="advancedSearch"]')
|
||||
.off('click').on('click', function() {
|
||||
showAvdSearch(that.columns, that.options.formatAdvancedSearch(), that.options.formatAdvancedCloseButton(), that);
|
||||
});
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.load = function(data) {
|
||||
_load.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!this.options.advancedSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.options.idTable === 'undefined') {
|
||||
return;
|
||||
} else {
|
||||
if (!firstLoad) {
|
||||
var height = parseInt($(".bootstrap-table").height());
|
||||
height += 10;
|
||||
$("#" + this.options.idTable).bootstrapTable("resetView", {height: height});
|
||||
firstLoad = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.initSearch = function () {
|
||||
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!this.options.advancedSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
|
||||
|
||||
this.data = fp ? $.grep(this.data, function (item, i) {
|
||||
for (var key in fp) {
|
||||
var fval = fp[key].toLowerCase();
|
||||
var value = item[key];
|
||||
value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
|
||||
that.header.formatters[$.inArray(key, that.header.fields)],
|
||||
[value, item, i], value);
|
||||
|
||||
if (!($.inArray(key, that.header.fields) !== -1 &&
|
||||
(typeof value === 'string' || typeof value === 'number') &&
|
||||
(value + '').toLowerCase().indexOf(fval) !== -1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}) : this.data;
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.onColumnAdvancedSearch = function (event) {
|
||||
var text = $.trim($(event.currentTarget).val());
|
||||
var $field = $(event.currentTarget)[0].id;
|
||||
|
||||
if ($.isEmptyObject(this.filterColumnsPartial)) {
|
||||
this.filterColumnsPartial = {};
|
||||
}
|
||||
if (text) {
|
||||
this.filterColumnsPartial[$field] = text;
|
||||
} else {
|
||||
delete this.filterColumnsPartial[$field];
|
||||
}
|
||||
|
||||
this.options.pageNumber = 1;
|
||||
this.onSearch(event);
|
||||
this.updatePagination();
|
||||
this.trigger('column-advanced-search', $field, text);
|
||||
};
|
||||
}(jQuery);
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
* bootstrap-table - v1.11.0 - 2016-07-02
|
||||
* https://github.com/wenzhixin/bootstrap-table
|
||||
* Copyright (c) 2016 zhixin wen
|
||||
* Licensed MIT License
|
||||
*/
|
||||
!function(a){"use strict";var b=!1,c=a.fn.bootstrapTable.utils.sprintf,d=function(b,d,f,g){if(a("#avdSearchModal_"+g.options.idTable).hasClass("modal"))a("#avdSearchModal_"+g.options.idTable).modal();else{var h=c('<div id="avdSearchModal%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">',"_"+g.options.idTable);h+='<div class="modal-dialog modal-xs">',h+=' <div class="modal-content">',h+=' <div class="modal-header">',h+=' <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >×</button>',h+=c(' <h4 class="modal-title">%s</h4>',d),h+=" </div>",h+=' <div class="modal-body modal-body-custom">',h+=c(' <div class="container-fluid" id="avdSearchModalContent%s" style="padding-right: 0px;padding-left: 0px;" >',"_"+g.options.idTable),h+=" </div>",h+=" </div>",h+=" </div>",h+=" </div>",h+="</div>",a("body").append(a(h));var i=e(b,f,g),j=0;a("#avdSearchModalContent_"+g.options.idTable).append(i.join("")),a("#"+g.options.idForm).off("keyup blur","input").on("keyup blur","input",function(a){clearTimeout(j),j=setTimeout(function(){g.onColumnAdvancedSearch(a)},g.options.searchTimeOut)}),a("#btnCloseAvd_"+g.options.idTable).click(function(){a("#avdSearchModal_"+g.options.idTable).modal("hide")}),a("#avdSearchModal_"+g.options.idTable).modal()}},e=function(a,b,d){var e=[];e.push(c('<form class="form-horizontal" id="%s" action="%s" >',d.options.idForm,d.options.actionForm));for(var f in a){var g=a[f];!g.checkbox&&g.visible&&g.searchable&&(e.push('<div class="form-group">'),e.push(c('<label class="col-sm-4 control-label">%s</label>',g.title)),e.push('<div class="col-sm-6">'),e.push(c('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">',g.field,g.title,g.field)),e.push("</div>"),e.push("</div>"))}return e.push('<div class="form-group">'),e.push('<div class="col-sm-offset-9 col-sm-3">'),e.push(c('<button type="button" id="btnCloseAvd%s" class="btn btn-default" >%s</button>',"_"+d.options.idTable,b)),e.push("</div>"),e.push("</div>"),e.push("</form>"),e};a.extend(a.fn.bootstrapTable.defaults,{advancedSearch:!1,idForm:"advancedSearch",actionForm:"",idTable:void 0,onColumnAdvancedSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{advancedSearchIcon:"glyphicon-chevron-down"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-advanced-search.bs.table":"onColumnAdvancedSearch"}),a.extend(a.fn.bootstrapTable.locales,{formatAdvancedSearch:function(){return"Advanced search"},formatAdvancedCloseButton:function(){return"Close"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var f=a.fn.bootstrapTable.Constructor,g=f.prototype.initToolbar,h=f.prototype.load,i=f.prototype.initSearch;f.prototype.initToolbar=function(){if(g.apply(this,Array.prototype.slice.apply(arguments)),this.options.search&&this.options.advancedSearch&&this.options.idTable){var a=this,b=[];b.push(c('<div class="columns columns-%s btn-group pull-%s" role="group">',this.options.buttonsAlign,this.options.buttonsAlign)),b.push(c('<button class="btn btn-default%s" type="button" name="advancedSearch" title="%s">',void 0===a.options.iconSize?"":" btn-"+a.options.iconSize,a.options.formatAdvancedSearch())),b.push(c('<i class="%s %s"></i>',a.options.iconsPrefix,a.options.icons.advancedSearchIcon)),b.push("</button></div>"),a.$toolbar.prepend(b.join("")),a.$toolbar.find('button[name="advancedSearch"]').off("click").on("click",function(){d(a.columns,a.options.formatAdvancedSearch(),a.options.formatAdvancedCloseButton(),a)})}},f.prototype.load=function(){if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.advancedSearch&&"undefined"!=typeof this.options.idTable&&!b){var c=parseInt(a(".bootstrap-table").height());c+=10,a("#"+this.options.idTable).bootstrapTable("resetView",{height:c}),b=!0}},f.prototype.initSearch=function(){if(i.apply(this,Array.prototype.slice.apply(arguments)),this.options.advancedSearch){var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(d,e){for(var f in c){var g=c[f].toLowerCase(),h=d[f];if(h=a.fn.bootstrapTable.utils.calculateObjectValue(b.header,b.header.formatters[a.inArray(f,b.header.fields)],[h,d,e],h),-1===a.inArray(f,b.header.fields)||"string"!=typeof h&&"number"!=typeof h||-1===(h+"").toLowerCase().indexOf(g))return!1}return!0}):this.data}},f.prototype.onColumnAdvancedSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget)[0].id;a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-advanced-search",d,c)}}(jQuery);
|
||||
Vendored
+768
-39
@@ -1,42 +1,771 @@
|
||||
(function ($) {
|
||||
'use strict';
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
|
||||
typeof define === 'function' && define.amd ? define(['jquery'], factory) :
|
||||
(global = global || self, factory(global.jQuery));
|
||||
}(this, (function ($) { 'use strict';
|
||||
|
||||
$.fn.bootstrapTable.locales['zh-CN'] = {
|
||||
formatLoadingMessage: function () {
|
||||
return '正在努力地加载数据中,请稍候……';
|
||||
},
|
||||
formatRecordsPerPage: function (pageNumber) {
|
||||
return pageNumber + ' 条记录每页';
|
||||
},
|
||||
formatShowingRows: function (pageFrom, pageTo, totalRows) {
|
||||
return '第 ' + pageFrom + ' 到 ' + pageTo + ' 条,共 ' + totalRows + ' 条记录。';
|
||||
},
|
||||
formatSearch: function () {
|
||||
return '搜索';
|
||||
},
|
||||
formatNoMatches: function () {
|
||||
return '没有找到匹配的记录';
|
||||
},
|
||||
formatPaginationSwitch: function () {
|
||||
return '隐藏/显示分页';
|
||||
},
|
||||
formatRefresh: function () {
|
||||
return '刷新';
|
||||
},
|
||||
formatToggle: function () {
|
||||
return '切换';
|
||||
},
|
||||
formatColumns: function () {
|
||||
return '列';
|
||||
},
|
||||
formatExport: function () {
|
||||
return '导出数据';
|
||||
},
|
||||
formatClearFilters: function () {
|
||||
return '清空过滤';
|
||||
}
|
||||
};
|
||||
$ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
|
||||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||
|
||||
})(jQuery);
|
||||
function createCommonjsModule(fn, module) {
|
||||
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
||||
}
|
||||
|
||||
var check = function (it) {
|
||||
return it && it.Math == Math && it;
|
||||
};
|
||||
|
||||
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
|
||||
var global_1 =
|
||||
// eslint-disable-next-line no-undef
|
||||
check(typeof globalThis == 'object' && globalThis) ||
|
||||
check(typeof window == 'object' && window) ||
|
||||
check(typeof self == 'object' && self) ||
|
||||
check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
|
||||
// eslint-disable-next-line no-new-func
|
||||
Function('return this')();
|
||||
|
||||
var fails = function (exec) {
|
||||
try {
|
||||
return !!exec();
|
||||
} catch (error) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Thank's IE8 for his funny defineProperty
|
||||
var descriptors = !fails(function () {
|
||||
return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;
|
||||
});
|
||||
|
||||
var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
|
||||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
||||
|
||||
// Nashorn ~ JDK8 bug
|
||||
var NASHORN_BUG = getOwnPropertyDescriptor && !nativePropertyIsEnumerable.call({ 1: 2 }, 1);
|
||||
|
||||
// `Object.prototype.propertyIsEnumerable` method implementation
|
||||
// https://tc39.github.io/ecma262/#sec-object.prototype.propertyisenumerable
|
||||
var f = NASHORN_BUG ? function propertyIsEnumerable(V) {
|
||||
var descriptor = getOwnPropertyDescriptor(this, V);
|
||||
return !!descriptor && descriptor.enumerable;
|
||||
} : nativePropertyIsEnumerable;
|
||||
|
||||
var objectPropertyIsEnumerable = {
|
||||
f: f
|
||||
};
|
||||
|
||||
var createPropertyDescriptor = function (bitmap, value) {
|
||||
return {
|
||||
enumerable: !(bitmap & 1),
|
||||
configurable: !(bitmap & 2),
|
||||
writable: !(bitmap & 4),
|
||||
value: value
|
||||
};
|
||||
};
|
||||
|
||||
var toString = {}.toString;
|
||||
|
||||
var classofRaw = function (it) {
|
||||
return toString.call(it).slice(8, -1);
|
||||
};
|
||||
|
||||
var split = ''.split;
|
||||
|
||||
// fallback for non-array-like ES3 and non-enumerable old V8 strings
|
||||
var indexedObject = fails(function () {
|
||||
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
return !Object('z').propertyIsEnumerable(0);
|
||||
}) ? function (it) {
|
||||
return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
|
||||
} : Object;
|
||||
|
||||
// `RequireObjectCoercible` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
|
||||
var requireObjectCoercible = function (it) {
|
||||
if (it == undefined) throw TypeError("Can't call method on " + it);
|
||||
return it;
|
||||
};
|
||||
|
||||
// toObject with fallback for non-array-like ES3 strings
|
||||
|
||||
|
||||
|
||||
var toIndexedObject = function (it) {
|
||||
return indexedObject(requireObjectCoercible(it));
|
||||
};
|
||||
|
||||
var isObject = function (it) {
|
||||
return typeof it === 'object' ? it !== null : typeof it === 'function';
|
||||
};
|
||||
|
||||
// `ToPrimitive` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-toprimitive
|
||||
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
|
||||
// and the second argument - flag - preferred type is a string
|
||||
var toPrimitive = function (input, PREFERRED_STRING) {
|
||||
if (!isObject(input)) return input;
|
||||
var fn, val;
|
||||
if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
|
||||
if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
|
||||
if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
|
||||
throw TypeError("Can't convert object to primitive value");
|
||||
};
|
||||
|
||||
var hasOwnProperty = {}.hasOwnProperty;
|
||||
|
||||
var has = function (it, key) {
|
||||
return hasOwnProperty.call(it, key);
|
||||
};
|
||||
|
||||
var document = global_1.document;
|
||||
// typeof document.createElement is 'object' in old IE
|
||||
var EXISTS = isObject(document) && isObject(document.createElement);
|
||||
|
||||
var documentCreateElement = function (it) {
|
||||
return EXISTS ? document.createElement(it) : {};
|
||||
};
|
||||
|
||||
// Thank's IE8 for his funny defineProperty
|
||||
var ie8DomDefine = !descriptors && !fails(function () {
|
||||
return Object.defineProperty(documentCreateElement('div'), 'a', {
|
||||
get: function () { return 7; }
|
||||
}).a != 7;
|
||||
});
|
||||
|
||||
var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
||||
|
||||
// `Object.getOwnPropertyDescriptor` method
|
||||
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor
|
||||
var f$1 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
|
||||
O = toIndexedObject(O);
|
||||
P = toPrimitive(P, true);
|
||||
if (ie8DomDefine) try {
|
||||
return nativeGetOwnPropertyDescriptor(O, P);
|
||||
} catch (error) { /* empty */ }
|
||||
if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
|
||||
};
|
||||
|
||||
var objectGetOwnPropertyDescriptor = {
|
||||
f: f$1
|
||||
};
|
||||
|
||||
var anObject = function (it) {
|
||||
if (!isObject(it)) {
|
||||
throw TypeError(String(it) + ' is not an object');
|
||||
} return it;
|
||||
};
|
||||
|
||||
var nativeDefineProperty = Object.defineProperty;
|
||||
|
||||
// `Object.defineProperty` method
|
||||
// https://tc39.github.io/ecma262/#sec-object.defineproperty
|
||||
var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
|
||||
anObject(O);
|
||||
P = toPrimitive(P, true);
|
||||
anObject(Attributes);
|
||||
if (ie8DomDefine) try {
|
||||
return nativeDefineProperty(O, P, Attributes);
|
||||
} catch (error) { /* empty */ }
|
||||
if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
|
||||
if ('value' in Attributes) O[P] = Attributes.value;
|
||||
return O;
|
||||
};
|
||||
|
||||
var objectDefineProperty = {
|
||||
f: f$2
|
||||
};
|
||||
|
||||
var createNonEnumerableProperty = descriptors ? function (object, key, value) {
|
||||
return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
|
||||
} : function (object, key, value) {
|
||||
object[key] = value;
|
||||
return object;
|
||||
};
|
||||
|
||||
var setGlobal = function (key, value) {
|
||||
try {
|
||||
createNonEnumerableProperty(global_1, key, value);
|
||||
} catch (error) {
|
||||
global_1[key] = value;
|
||||
} return value;
|
||||
};
|
||||
|
||||
var SHARED = '__core-js_shared__';
|
||||
var store = global_1[SHARED] || setGlobal(SHARED, {});
|
||||
|
||||
var sharedStore = store;
|
||||
|
||||
var functionToString = Function.toString;
|
||||
|
||||
// this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
|
||||
if (typeof sharedStore.inspectSource != 'function') {
|
||||
sharedStore.inspectSource = function (it) {
|
||||
return functionToString.call(it);
|
||||
};
|
||||
}
|
||||
|
||||
var inspectSource = sharedStore.inspectSource;
|
||||
|
||||
var WeakMap = global_1.WeakMap;
|
||||
|
||||
var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap));
|
||||
|
||||
var shared = createCommonjsModule(function (module) {
|
||||
(module.exports = function (key, value) {
|
||||
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
|
||||
})('versions', []).push({
|
||||
version: '3.6.0',
|
||||
mode: 'global',
|
||||
copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
|
||||
});
|
||||
});
|
||||
|
||||
var id = 0;
|
||||
var postfix = Math.random();
|
||||
|
||||
var uid = function (key) {
|
||||
return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
|
||||
};
|
||||
|
||||
var keys = shared('keys');
|
||||
|
||||
var sharedKey = function (key) {
|
||||
return keys[key] || (keys[key] = uid(key));
|
||||
};
|
||||
|
||||
var hiddenKeys = {};
|
||||
|
||||
var WeakMap$1 = global_1.WeakMap;
|
||||
var set, get, has$1;
|
||||
|
||||
var enforce = function (it) {
|
||||
return has$1(it) ? get(it) : set(it, {});
|
||||
};
|
||||
|
||||
var getterFor = function (TYPE) {
|
||||
return function (it) {
|
||||
var state;
|
||||
if (!isObject(it) || (state = get(it)).type !== TYPE) {
|
||||
throw TypeError('Incompatible receiver, ' + TYPE + ' required');
|
||||
} return state;
|
||||
};
|
||||
};
|
||||
|
||||
if (nativeWeakMap) {
|
||||
var store$1 = new WeakMap$1();
|
||||
var wmget = store$1.get;
|
||||
var wmhas = store$1.has;
|
||||
var wmset = store$1.set;
|
||||
set = function (it, metadata) {
|
||||
wmset.call(store$1, it, metadata);
|
||||
return metadata;
|
||||
};
|
||||
get = function (it) {
|
||||
return wmget.call(store$1, it) || {};
|
||||
};
|
||||
has$1 = function (it) {
|
||||
return wmhas.call(store$1, it);
|
||||
};
|
||||
} else {
|
||||
var STATE = sharedKey('state');
|
||||
hiddenKeys[STATE] = true;
|
||||
set = function (it, metadata) {
|
||||
createNonEnumerableProperty(it, STATE, metadata);
|
||||
return metadata;
|
||||
};
|
||||
get = function (it) {
|
||||
return has(it, STATE) ? it[STATE] : {};
|
||||
};
|
||||
has$1 = function (it) {
|
||||
return has(it, STATE);
|
||||
};
|
||||
}
|
||||
|
||||
var internalState = {
|
||||
set: set,
|
||||
get: get,
|
||||
has: has$1,
|
||||
enforce: enforce,
|
||||
getterFor: getterFor
|
||||
};
|
||||
|
||||
var redefine = createCommonjsModule(function (module) {
|
||||
var getInternalState = internalState.get;
|
||||
var enforceInternalState = internalState.enforce;
|
||||
var TEMPLATE = String(String).split('String');
|
||||
|
||||
(module.exports = function (O, key, value, options) {
|
||||
var unsafe = options ? !!options.unsafe : false;
|
||||
var simple = options ? !!options.enumerable : false;
|
||||
var noTargetGet = options ? !!options.noTargetGet : false;
|
||||
if (typeof value == 'function') {
|
||||
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
|
||||
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
|
||||
}
|
||||
if (O === global_1) {
|
||||
if (simple) O[key] = value;
|
||||
else setGlobal(key, value);
|
||||
return;
|
||||
} else if (!unsafe) {
|
||||
delete O[key];
|
||||
} else if (!noTargetGet && O[key]) {
|
||||
simple = true;
|
||||
}
|
||||
if (simple) O[key] = value;
|
||||
else createNonEnumerableProperty(O, key, value);
|
||||
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
|
||||
})(Function.prototype, 'toString', function toString() {
|
||||
return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
|
||||
});
|
||||
});
|
||||
|
||||
var path = global_1;
|
||||
|
||||
var aFunction = function (variable) {
|
||||
return typeof variable == 'function' ? variable : undefined;
|
||||
};
|
||||
|
||||
var getBuiltIn = function (namespace, method) {
|
||||
return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace])
|
||||
: path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
|
||||
};
|
||||
|
||||
var ceil = Math.ceil;
|
||||
var floor = Math.floor;
|
||||
|
||||
// `ToInteger` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-tointeger
|
||||
var toInteger = function (argument) {
|
||||
return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument);
|
||||
};
|
||||
|
||||
var min = Math.min;
|
||||
|
||||
// `ToLength` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-tolength
|
||||
var toLength = function (argument) {
|
||||
return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
|
||||
};
|
||||
|
||||
var max = Math.max;
|
||||
var min$1 = Math.min;
|
||||
|
||||
// Helper for a popular repeating case of the spec:
|
||||
// Let integer be ? ToInteger(index).
|
||||
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
|
||||
var toAbsoluteIndex = function (index, length) {
|
||||
var integer = toInteger(index);
|
||||
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
|
||||
};
|
||||
|
||||
// `Array.prototype.{ indexOf, includes }` methods implementation
|
||||
var createMethod = function (IS_INCLUDES) {
|
||||
return function ($this, el, fromIndex) {
|
||||
var O = toIndexedObject($this);
|
||||
var length = toLength(O.length);
|
||||
var index = toAbsoluteIndex(fromIndex, length);
|
||||
var value;
|
||||
// Array#includes uses SameValueZero equality algorithm
|
||||
// eslint-disable-next-line no-self-compare
|
||||
if (IS_INCLUDES && el != el) while (length > index) {
|
||||
value = O[index++];
|
||||
// eslint-disable-next-line no-self-compare
|
||||
if (value != value) return true;
|
||||
// Array#indexOf ignores holes, Array#includes - not
|
||||
} else for (;length > index; index++) {
|
||||
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
|
||||
} return !IS_INCLUDES && -1;
|
||||
};
|
||||
};
|
||||
|
||||
var arrayIncludes = {
|
||||
// `Array.prototype.includes` method
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
|
||||
includes: createMethod(true),
|
||||
// `Array.prototype.indexOf` method
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
|
||||
indexOf: createMethod(false)
|
||||
};
|
||||
|
||||
var indexOf = arrayIncludes.indexOf;
|
||||
|
||||
|
||||
var objectKeysInternal = function (object, names) {
|
||||
var O = toIndexedObject(object);
|
||||
var i = 0;
|
||||
var result = [];
|
||||
var key;
|
||||
for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key);
|
||||
// Don't enum bug & hidden keys
|
||||
while (names.length > i) if (has(O, key = names[i++])) {
|
||||
~indexOf(result, key) || result.push(key);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// IE8- don't enum bug keys
|
||||
var enumBugKeys = [
|
||||
'constructor',
|
||||
'hasOwnProperty',
|
||||
'isPrototypeOf',
|
||||
'propertyIsEnumerable',
|
||||
'toLocaleString',
|
||||
'toString',
|
||||
'valueOf'
|
||||
];
|
||||
|
||||
var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype');
|
||||
|
||||
// `Object.getOwnPropertyNames` method
|
||||
// https://tc39.github.io/ecma262/#sec-object.getownpropertynames
|
||||
var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
|
||||
return objectKeysInternal(O, hiddenKeys$1);
|
||||
};
|
||||
|
||||
var objectGetOwnPropertyNames = {
|
||||
f: f$3
|
||||
};
|
||||
|
||||
var f$4 = Object.getOwnPropertySymbols;
|
||||
|
||||
var objectGetOwnPropertySymbols = {
|
||||
f: f$4
|
||||
};
|
||||
|
||||
// all object keys, includes non-enumerable and symbols
|
||||
var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
|
||||
var keys = objectGetOwnPropertyNames.f(anObject(it));
|
||||
var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
|
||||
return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
|
||||
};
|
||||
|
||||
var copyConstructorProperties = function (target, source) {
|
||||
var keys = ownKeys(source);
|
||||
var defineProperty = objectDefineProperty.f;
|
||||
var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
|
||||
}
|
||||
};
|
||||
|
||||
var replacement = /#|\.prototype\./;
|
||||
|
||||
var isForced = function (feature, detection) {
|
||||
var value = data[normalize(feature)];
|
||||
return value == POLYFILL ? true
|
||||
: value == NATIVE ? false
|
||||
: typeof detection == 'function' ? fails(detection)
|
||||
: !!detection;
|
||||
};
|
||||
|
||||
var normalize = isForced.normalize = function (string) {
|
||||
return String(string).replace(replacement, '.').toLowerCase();
|
||||
};
|
||||
|
||||
var data = isForced.data = {};
|
||||
var NATIVE = isForced.NATIVE = 'N';
|
||||
var POLYFILL = isForced.POLYFILL = 'P';
|
||||
|
||||
var isForced_1 = isForced;
|
||||
|
||||
var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
options.target - name of the target object
|
||||
options.global - target is the global object
|
||||
options.stat - export as static methods of target
|
||||
options.proto - export as prototype methods of target
|
||||
options.real - real prototype method for the `pure` version
|
||||
options.forced - export even if the native feature is available
|
||||
options.bind - bind methods to the target, required for the `pure` version
|
||||
options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
|
||||
options.unsafe - use the simple assignment of property instead of delete + defineProperty
|
||||
options.sham - add a flag to not completely full polyfills
|
||||
options.enumerable - export as enumerable property
|
||||
options.noTargetGet - prevent calling a getter on target
|
||||
*/
|
||||
var _export = function (options, source) {
|
||||
var TARGET = options.target;
|
||||
var GLOBAL = options.global;
|
||||
var STATIC = options.stat;
|
||||
var FORCED, target, key, targetProperty, sourceProperty, descriptor;
|
||||
if (GLOBAL) {
|
||||
target = global_1;
|
||||
} else if (STATIC) {
|
||||
target = global_1[TARGET] || setGlobal(TARGET, {});
|
||||
} else {
|
||||
target = (global_1[TARGET] || {}).prototype;
|
||||
}
|
||||
if (target) for (key in source) {
|
||||
sourceProperty = source[key];
|
||||
if (options.noTargetGet) {
|
||||
descriptor = getOwnPropertyDescriptor$1(target, key);
|
||||
targetProperty = descriptor && descriptor.value;
|
||||
} else targetProperty = target[key];
|
||||
FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
|
||||
// contained in target
|
||||
if (!FORCED && targetProperty !== undefined) {
|
||||
if (typeof sourceProperty === typeof targetProperty) continue;
|
||||
copyConstructorProperties(sourceProperty, targetProperty);
|
||||
}
|
||||
// add a flag to not completely full polyfills
|
||||
if (options.sham || (targetProperty && targetProperty.sham)) {
|
||||
createNonEnumerableProperty(sourceProperty, 'sham', true);
|
||||
}
|
||||
// extend global
|
||||
redefine(target, key, sourceProperty, options);
|
||||
}
|
||||
};
|
||||
|
||||
// `IsArray` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-isarray
|
||||
var isArray = Array.isArray || function isArray(arg) {
|
||||
return classofRaw(arg) == 'Array';
|
||||
};
|
||||
|
||||
// `ToObject` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-toobject
|
||||
var toObject = function (argument) {
|
||||
return Object(requireObjectCoercible(argument));
|
||||
};
|
||||
|
||||
var createProperty = function (object, key, value) {
|
||||
var propertyKey = toPrimitive(key);
|
||||
if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));
|
||||
else object[propertyKey] = value;
|
||||
};
|
||||
|
||||
var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () {
|
||||
// Chrome 38 Symbol has incorrect toString conversion
|
||||
// eslint-disable-next-line no-undef
|
||||
return !String(Symbol());
|
||||
});
|
||||
|
||||
var useSymbolAsUid = nativeSymbol
|
||||
// eslint-disable-next-line no-undef
|
||||
&& !Symbol.sham
|
||||
// eslint-disable-next-line no-undef
|
||||
&& typeof Symbol() == 'symbol';
|
||||
|
||||
var WellKnownSymbolsStore = shared('wks');
|
||||
var Symbol$1 = global_1.Symbol;
|
||||
var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : uid;
|
||||
|
||||
var wellKnownSymbol = function (name) {
|
||||
if (!has(WellKnownSymbolsStore, name)) {
|
||||
if (nativeSymbol && has(Symbol$1, name)) WellKnownSymbolsStore[name] = Symbol$1[name];
|
||||
else WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name);
|
||||
} return WellKnownSymbolsStore[name];
|
||||
};
|
||||
|
||||
var SPECIES = wellKnownSymbol('species');
|
||||
|
||||
// `ArraySpeciesCreate` abstract operation
|
||||
// https://tc39.github.io/ecma262/#sec-arrayspeciescreate
|
||||
var arraySpeciesCreate = function (originalArray, length) {
|
||||
var C;
|
||||
if (isArray(originalArray)) {
|
||||
C = originalArray.constructor;
|
||||
// cross-realm fallback
|
||||
if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
|
||||
else if (isObject(C)) {
|
||||
C = C[SPECIES];
|
||||
if (C === null) C = undefined;
|
||||
}
|
||||
} return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
|
||||
};
|
||||
|
||||
var userAgent = getBuiltIn('navigator', 'userAgent') || '';
|
||||
|
||||
var process = global_1.process;
|
||||
var versions = process && process.versions;
|
||||
var v8 = versions && versions.v8;
|
||||
var match, version;
|
||||
|
||||
if (v8) {
|
||||
match = v8.split('.');
|
||||
version = match[0] + match[1];
|
||||
} else if (userAgent) {
|
||||
match = userAgent.match(/Edge\/(\d+)/);
|
||||
if (!match || match[1] >= 74) {
|
||||
match = userAgent.match(/Chrome\/(\d+)/);
|
||||
if (match) version = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
var v8Version = version && +version;
|
||||
|
||||
var SPECIES$1 = wellKnownSymbol('species');
|
||||
|
||||
var arrayMethodHasSpeciesSupport = function (METHOD_NAME) {
|
||||
// We can't use this feature detection in V8 since it causes
|
||||
// deoptimization and serious performance degradation
|
||||
// https://github.com/zloirock/core-js/issues/677
|
||||
return v8Version >= 51 || !fails(function () {
|
||||
var array = [];
|
||||
var constructor = array.constructor = {};
|
||||
constructor[SPECIES$1] = function () {
|
||||
return { foo: 1 };
|
||||
};
|
||||
return array[METHOD_NAME](Boolean).foo !== 1;
|
||||
});
|
||||
};
|
||||
|
||||
var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable');
|
||||
var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
|
||||
var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';
|
||||
|
||||
// We can't use this feature detection in V8 since it causes
|
||||
// deoptimization and serious performance degradation
|
||||
// https://github.com/zloirock/core-js/issues/679
|
||||
var IS_CONCAT_SPREADABLE_SUPPORT = v8Version >= 51 || !fails(function () {
|
||||
var array = [];
|
||||
array[IS_CONCAT_SPREADABLE] = false;
|
||||
return array.concat()[0] !== array;
|
||||
});
|
||||
|
||||
var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat');
|
||||
|
||||
var isConcatSpreadable = function (O) {
|
||||
if (!isObject(O)) return false;
|
||||
var spreadable = O[IS_CONCAT_SPREADABLE];
|
||||
return spreadable !== undefined ? !!spreadable : isArray(O);
|
||||
};
|
||||
|
||||
var FORCED = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;
|
||||
|
||||
// `Array.prototype.concat` method
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.concat
|
||||
// with adding support of @@isConcatSpreadable and @@species
|
||||
_export({ target: 'Array', proto: true, forced: FORCED }, {
|
||||
concat: function concat(arg) { // eslint-disable-line no-unused-vars
|
||||
var O = toObject(this);
|
||||
var A = arraySpeciesCreate(O, 0);
|
||||
var n = 0;
|
||||
var i, k, length, len, E;
|
||||
for (i = -1, length = arguments.length; i < length; i++) {
|
||||
E = i === -1 ? O : arguments[i];
|
||||
if (isConcatSpreadable(E)) {
|
||||
len = toLength(E.length);
|
||||
if (n + len > MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
|
||||
for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]);
|
||||
} else {
|
||||
if (n >= MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
|
||||
createProperty(A, n++, E);
|
||||
}
|
||||
}
|
||||
A.length = n;
|
||||
return A;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Bootstrap Table Chinese translation
|
||||
* Author: Zhixin Wen<wenzhixin2010@gmail.com>
|
||||
*/
|
||||
|
||||
$.fn.bootstrapTable.locales['zh-CN'] = {
|
||||
formatLoadingMessage: function formatLoadingMessage() {
|
||||
return '正在努力地加载数据中,请稍候';
|
||||
},
|
||||
formatRecordsPerPage: function formatRecordsPerPage(pageNumber) {
|
||||
return "\u6BCF\u9875\u663E\u793A ".concat(pageNumber, " \u6761\u8BB0\u5F55");
|
||||
},
|
||||
formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
|
||||
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
|
||||
return "\u663E\u793A\u7B2C ".concat(pageFrom, " \u5230\u7B2C ").concat(pageTo, " \u6761\u8BB0\u5F55\uFF0C\u603B\u5171 ").concat(totalRows, " \u6761\u8BB0\u5F55\uFF08\u4ECE ").concat(totalNotFiltered, " \u603B\u8BB0\u5F55\u4E2D\u8FC7\u6EE4\uFF09");
|
||||
}
|
||||
|
||||
return "\u663E\u793A\u7B2C ".concat(pageFrom, " \u5230\u7B2C ").concat(pageTo, " \u6761\u8BB0\u5F55\uFF0C\u603B\u5171 ").concat(totalRows, " \u6761\u8BB0\u5F55");
|
||||
},
|
||||
formatSRPaginationPreText: function formatSRPaginationPreText() {
|
||||
return '上一页';
|
||||
},
|
||||
formatSRPaginationPageText: function formatSRPaginationPageText(page) {
|
||||
return "\u7B2C".concat(page, "\u9875");
|
||||
},
|
||||
formatSRPaginationNextText: function formatSRPaginationNextText() {
|
||||
return '下一页';
|
||||
},
|
||||
formatDetailPagination: function formatDetailPagination(totalRows) {
|
||||
return "\u603B\u5171 ".concat(totalRows, " \u6761\u8BB0\u5F55");
|
||||
},
|
||||
formatClearSearch: function formatClearSearch() {
|
||||
return '清空过滤';
|
||||
},
|
||||
formatSearch: function formatSearch() {
|
||||
return '搜索';
|
||||
},
|
||||
formatNoMatches: function formatNoMatches() {
|
||||
return '没有找到匹配的记录';
|
||||
},
|
||||
formatPaginationSwitch: function formatPaginationSwitch() {
|
||||
return '隐藏/显示分页';
|
||||
},
|
||||
formatPaginationSwitchDown: function formatPaginationSwitchDown() {
|
||||
return '显示分页';
|
||||
},
|
||||
formatPaginationSwitchUp: function formatPaginationSwitchUp() {
|
||||
return '隐藏分页';
|
||||
},
|
||||
formatRefresh: function formatRefresh() {
|
||||
return '刷新';
|
||||
},
|
||||
formatToggle: function formatToggle() {
|
||||
return '切换';
|
||||
},
|
||||
formatToggleOn: function formatToggleOn() {
|
||||
return '显示卡片视图';
|
||||
},
|
||||
formatToggleOff: function formatToggleOff() {
|
||||
return '隐藏卡片视图';
|
||||
},
|
||||
formatColumns: function formatColumns() {
|
||||
return '列';
|
||||
},
|
||||
formatColumnsToggleAll: function formatColumnsToggleAll() {
|
||||
return '切换所有';
|
||||
},
|
||||
formatFullscreen: function formatFullscreen() {
|
||||
return '全屏';
|
||||
},
|
||||
formatAllRows: function formatAllRows() {
|
||||
return '所有';
|
||||
},
|
||||
formatAutoRefresh: function formatAutoRefresh() {
|
||||
return '自动刷新';
|
||||
},
|
||||
formatExport: function formatExport() {
|
||||
return '导出数据';
|
||||
},
|
||||
formatJumpTo: function formatJumpTo() {
|
||||
return '跳转';
|
||||
},
|
||||
formatAdvancedSearch: function formatAdvancedSearch() {
|
||||
return '高级搜索';
|
||||
},
|
||||
formatAdvancedCloseButton: function formatAdvancedCloseButton() {
|
||||
return '关闭';
|
||||
},
|
||||
formatFilterControlSwitch: function formatFilterControlSwitch() {
|
||||
return '隐藏/显示过滤控制';
|
||||
},
|
||||
formatFilterControlSwitchHide: function formatFilterControlSwitchHide() {
|
||||
return '隐藏过滤控制';
|
||||
},
|
||||
formatFilterControlSwitchShow: function formatFilterControlSwitchShow() {
|
||||
return '显示过滤控制';
|
||||
}
|
||||
};
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
|
||||
|
||||
})));
|
||||
|
||||
Vendored
+10
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -133,7 +133,7 @@
|
||||
if((!target.isFixWidth)&& column.width){
|
||||
target.isFixWidth = column.width.indexOf("px")>-1?true:false;
|
||||
}
|
||||
$th.text(column.title);
|
||||
$th.html(column.title);
|
||||
$thr.append($th);
|
||||
});
|
||||
var $thead = $('<thead class="treetable-thead"></thead>');
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
@charset "utf-8";
|
||||
.container {
|
||||
margin: 10px auto 0 auto;
|
||||
position: relative;
|
||||
font-family: 微软雅黑;
|
||||
font-size: 12px;
|
||||
}
|
||||
.container p {
|
||||
line-height: 12px;
|
||||
line-height: 0px;
|
||||
height: 0px;
|
||||
margin: 10px;
|
||||
color: #bbb
|
||||
}
|
||||
.action {
|
||||
width: 400px;
|
||||
height: 30px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.cropped {
|
||||
position: absolute;
|
||||
left: 500px;
|
||||
top: 0;
|
||||
width: 200px;
|
||||
border: 1px #ddd solid;
|
||||
height: 450px;
|
||||
padding: 4px;
|
||||
box-shadow: 0px 0px 12px #ddd;
|
||||
text-align: center;
|
||||
}
|
||||
.imageBox {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
border: 1px solid #aaa;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
cursor: move;
|
||||
box-shadow: 4px 4px 12px #B0B0B0;
|
||||
}
|
||||
.imageBox .thumbBox {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin-top: -100px;
|
||||
margin-left: -100px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgb(102, 102, 102);
|
||||
box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5);
|
||||
background: none repeat scroll 0% 0% transparent;
|
||||
}
|
||||
.imageBox .spinner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
line-height: 400px;
|
||||
background: rgba(0,0,0,0.7);
|
||||
}
|
||||
.Btnsty_peyton{ float: right;
|
||||
width: 46px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
margin:0px 2px;
|
||||
background-color: #f38e81;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 0px 5px #B0B0B0;
|
||||
border: 0px #fff solid;}
|
||||
/*选择文件上传*/
|
||||
.new-contentarea {
|
||||
width: 165px;
|
||||
overflow:hidden;
|
||||
margin: 0 auto;
|
||||
position:relative;float:left;
|
||||
}
|
||||
.new-contentarea label {
|
||||
width:100%;
|
||||
height:100%;
|
||||
display:block;
|
||||
}
|
||||
.new-contentarea input[type=file] {
|
||||
width:188px;
|
||||
height:60px;
|
||||
background:#333;
|
||||
margin: 0 auto;
|
||||
position:absolute;
|
||||
right:50%;
|
||||
margin-right:-94px;
|
||||
top:0;
|
||||
right/*\**/:0px\9;
|
||||
margin-right/*\**/:0px\9;
|
||||
width/*\**/:10px\9;
|
||||
opacity:0;
|
||||
filter:alpha(opacity=0);
|
||||
z-index:2;
|
||||
}
|
||||
a.upload-img{
|
||||
width:165px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
height:37px;
|
||||
line-height: 37px;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
background-color: #f38e81;
|
||||
border-radius: 3px;
|
||||
text-decoration:none;
|
||||
cursor:pointer;
|
||||
border: 0px #fff solid;
|
||||
box-shadow: 0px 0px 5px #B0B0B0;
|
||||
}
|
||||
a.upload-img:hover{
|
||||
background-color: #ec7e70;
|
||||
}
|
||||
|
||||
.tc{text-align:center;}
|
||||
@@ -1,136 +0,0 @@
|
||||
"use strict";
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else {
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
var cropbox = function(options, el){
|
||||
var el = el || $(options.imageBox),
|
||||
obj =
|
||||
{
|
||||
state : {},
|
||||
ratio : 1,
|
||||
options : options,
|
||||
imageBox : el,
|
||||
thumbBox : el.find(options.thumbBox),
|
||||
spinner : el.find(options.spinner),
|
||||
image : new Image(),
|
||||
getDataURL: function ()
|
||||
{
|
||||
var width = this.thumbBox.width(),
|
||||
height = this.thumbBox.height(),
|
||||
canvas = document.createElement("canvas"),
|
||||
dim = el.css('background-position').split(' '),
|
||||
size = el.css('background-size').split(' '),
|
||||
dx = parseInt(dim[0]) - el.width()/2 + width/2,
|
||||
dy = parseInt(dim[1]) - el.height()/2 + height/2,
|
||||
dw = parseInt(size[0]),
|
||||
dh = parseInt(size[1]),
|
||||
sh = parseInt(this.image.height),
|
||||
sw = parseInt(this.image.width);
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
var context = canvas.getContext("2d");
|
||||
context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
|
||||
var imageData = canvas.toDataURL('image/png');
|
||||
return imageData;
|
||||
},
|
||||
getBlob: function()
|
||||
{
|
||||
var imageData = this.getDataURL();
|
||||
var b64 = imageData.replace('data:image/png;base64,','');
|
||||
var binary = atob(b64);
|
||||
var array = [];
|
||||
for (var i = 0; i < binary.length; i++) {
|
||||
array.push(binary.charCodeAt(i));
|
||||
}
|
||||
return new Blob([new Uint8Array(array)], {type: 'image/png'});
|
||||
},
|
||||
zoomIn: function ()
|
||||
{
|
||||
this.ratio*=1.1;
|
||||
setBackground();
|
||||
},
|
||||
zoomOut: function ()
|
||||
{
|
||||
this.ratio*=0.9;
|
||||
setBackground();
|
||||
}
|
||||
},
|
||||
setBackground = function()
|
||||
{
|
||||
var w = parseInt(obj.image.width)*obj.ratio;
|
||||
var h = parseInt(obj.image.height)*obj.ratio;
|
||||
|
||||
var pw = (el.width() - w) / 2;
|
||||
var ph = (el.height() - h) / 2;
|
||||
|
||||
el.css({
|
||||
'background-image': 'url(' + obj.image.src + ')',
|
||||
'background-size': w +'px ' + h + 'px',
|
||||
'background-position': pw + 'px ' + ph + 'px',
|
||||
'background-repeat': 'no-repeat'});
|
||||
},
|
||||
imgMouseDown = function(e)
|
||||
{
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
obj.state.dragable = true;
|
||||
obj.state.mouseX = e.clientX;
|
||||
obj.state.mouseY = e.clientY;
|
||||
},
|
||||
imgMouseMove = function(e)
|
||||
{
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
if (obj.state.dragable)
|
||||
{
|
||||
var x = e.clientX - obj.state.mouseX;
|
||||
var y = e.clientY - obj.state.mouseY;
|
||||
|
||||
var bg = el.css('background-position').split(' ');
|
||||
|
||||
var bgX = x + parseInt(bg[0]);
|
||||
var bgY = y + parseInt(bg[1]);
|
||||
|
||||
el.css('background-position', bgX +'px ' + bgY + 'px');
|
||||
|
||||
obj.state.mouseX = e.clientX;
|
||||
obj.state.mouseY = e.clientY;
|
||||
}
|
||||
},
|
||||
imgMouseUp = function(e)
|
||||
{
|
||||
e.stopImmediatePropagation();
|
||||
obj.state.dragable = false;
|
||||
},
|
||||
zoomImage = function(e)
|
||||
{
|
||||
e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0 ? obj.ratio*=1.1 : obj.ratio*=0.9;
|
||||
setBackground();
|
||||
}
|
||||
|
||||
obj.spinner.show();
|
||||
obj.image.onload = function() {
|
||||
obj.spinner.hide();
|
||||
setBackground();
|
||||
|
||||
el.bind('mousedown', imgMouseDown);
|
||||
el.bind('mousemove', imgMouseMove);
|
||||
$(window).bind('mouseup', imgMouseUp);
|
||||
el.bind('mousewheel DOMMouseScroll', zoomImage);
|
||||
};
|
||||
obj.image.crossOrigin = 'Anonymous';
|
||||
obj.image.src = options.imgSrc;
|
||||
el.on('remove', function(){$(window).unbind('mouseup', imgMouseUp)});
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
jQuery.fn.cropbox = function(options){
|
||||
return new cropbox(options, this);
|
||||
};
|
||||
}));
|
||||
@@ -0,0 +1,304 @@
|
||||
/*!
|
||||
* Cropper.js v1.5.7
|
||||
* https://fengyuanchen.github.io/cropperjs
|
||||
*
|
||||
* Copyright 2015-present Chen Fengyuan
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Date: 2020-05-23T05:22:57.283Z
|
||||
*/
|
||||
|
||||
.cropper-container {
|
||||
direction: ltr;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.cropper-container img {
|
||||
display: block;
|
||||
height: 100%;
|
||||
image-orientation: 0deg;
|
||||
max-height: none !important;
|
||||
max-width: none !important;
|
||||
min-height: 0 !important;
|
||||
min-width: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cropper-wrap-box,
|
||||
.cropper-canvas,
|
||||
.cropper-drag-box,
|
||||
.cropper-crop-box,
|
||||
.cropper-modal {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.cropper-wrap-box,
|
||||
.cropper-canvas {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cropper-drag-box {
|
||||
background-color: #fff;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.cropper-modal {
|
||||
background-color: #000;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cropper-view-box {
|
||||
display: block;
|
||||
height: 100%;
|
||||
outline: 1px solid #39f;
|
||||
outline-color: rgba(51, 153, 255, 0.75);
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cropper-dashed {
|
||||
border: 0 dashed #eee;
|
||||
display: block;
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cropper-dashed.dashed-h {
|
||||
border-bottom-width: 1px;
|
||||
border-top-width: 1px;
|
||||
height: calc(100% / 3);
|
||||
left: 0;
|
||||
top: calc(100% / 3);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cropper-dashed.dashed-v {
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
height: 100%;
|
||||
left: calc(100% / 3);
|
||||
top: 0;
|
||||
width: calc(100% / 3);
|
||||
}
|
||||
|
||||
.cropper-center {
|
||||
display: block;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
opacity: 0.75;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.cropper-center::before,
|
||||
.cropper-center::after {
|
||||
background-color: #eee;
|
||||
content: ' ';
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cropper-center::before {
|
||||
height: 1px;
|
||||
left: -3px;
|
||||
top: 0;
|
||||
width: 7px;
|
||||
}
|
||||
|
||||
.cropper-center::after {
|
||||
height: 7px;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.cropper-face,
|
||||
.cropper-line,
|
||||
.cropper-point {
|
||||
display: block;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cropper-face {
|
||||
background-color: #fff;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.cropper-line {
|
||||
background-color: #39f;
|
||||
}
|
||||
|
||||
.cropper-line.line-e {
|
||||
cursor: ew-resize;
|
||||
right: -3px;
|
||||
top: 0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.cropper-line.line-n {
|
||||
cursor: ns-resize;
|
||||
height: 5px;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.cropper-line.line-w {
|
||||
cursor: ew-resize;
|
||||
left: -3px;
|
||||
top: 0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.cropper-line.line-s {
|
||||
bottom: -3px;
|
||||
cursor: ns-resize;
|
||||
height: 5px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.cropper-point {
|
||||
background-color: #39f;
|
||||
height: 5px;
|
||||
opacity: 0.75;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.cropper-point.point-e {
|
||||
cursor: ew-resize;
|
||||
margin-top: -3px;
|
||||
right: -3px;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.cropper-point.point-n {
|
||||
cursor: ns-resize;
|
||||
left: 50%;
|
||||
margin-left: -3px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.cropper-point.point-w {
|
||||
cursor: ew-resize;
|
||||
left: -3px;
|
||||
margin-top: -3px;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.cropper-point.point-s {
|
||||
bottom: -3px;
|
||||
cursor: s-resize;
|
||||
left: 50%;
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
.cropper-point.point-ne {
|
||||
cursor: nesw-resize;
|
||||
right: -3px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.cropper-point.point-nw {
|
||||
cursor: nwse-resize;
|
||||
left: -3px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.cropper-point.point-sw {
|
||||
bottom: -3px;
|
||||
cursor: nesw-resize;
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
.cropper-point.point-se {
|
||||
bottom: -3px;
|
||||
cursor: nwse-resize;
|
||||
height: 20px;
|
||||
opacity: 1;
|
||||
right: -3px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.cropper-point.point-se {
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.cropper-point.point-se {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.cropper-point.point-se {
|
||||
height: 5px;
|
||||
opacity: 0.75;
|
||||
width: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.cropper-point.point-se::before {
|
||||
background-color: #39f;
|
||||
bottom: -50%;
|
||||
content: ' ';
|
||||
display: block;
|
||||
height: 200%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: -50%;
|
||||
width: 200%;
|
||||
}
|
||||
|
||||
.cropper-invisible {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.cropper-bg {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
.cropper-hide {
|
||||
display: block;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.cropper-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.cropper-move {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.cropper-crop {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.cropper-disabled .cropper-drag-box,
|
||||
.cropper-disabled .cropper-face,
|
||||
.cropper-disabled .cropper-line,
|
||||
.cropper-disabled .cropper-point {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Cropper.js v1.5.7
|
||||
* https://fengyuanchen.github.io/cropperjs
|
||||
*
|
||||
* Copyright 2015-present Chen Fengyuan
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Date: 2020-05-23T05:22:57.283Z
|
||||
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
|
||||
File diff suppressed because one or more lines are too long
@@ -927,6 +927,7 @@
|
||||
.theme-blue.skin-blue .navbar-default .nav>li.selected>a,
|
||||
.theme-blue.skin-blue .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #1890ff;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.theme-blue.skin-green .navbar-default .nav>li.active>a {
|
||||
|
||||
@@ -1829,6 +1829,10 @@ table.dataTable thead .sorting:after {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-control.kv-fileinput-caption {
|
||||
height: 34px!important;
|
||||
}
|
||||
|
||||
.form-control:focus, .single-line:focus {
|
||||
border-color: #3c8dbc !important;
|
||||
}
|
||||
@@ -4917,13 +4921,14 @@ dd.project-people {
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Chat view */
|
||||
.message-input {
|
||||
height: 90px !important;
|
||||
}
|
||||
|
||||
.chat-avatar {
|
||||
white: 36px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
@@ -4950,9 +4955,10 @@ dd.project-people {
|
||||
margin-left: -30px;
|
||||
}
|
||||
|
||||
@media ( max-width : 992px) {
|
||||
.chat-users, .chat-statistic {
|
||||
margin-left: 0px;
|
||||
@media (max-width: 992px) {
|
||||
.chat-users,
|
||||
.chat-statistic {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4972,12 +4978,12 @@ dd.project-people {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n+1) .message-avatar {
|
||||
.chat-discussion .chat-message.left .message-avatar {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n) .message-avatar {
|
||||
.chat-discussion .chat-message.right .message-avatar {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
@@ -4992,20 +4998,20 @@ dd.project-people {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n+1) .message-date {
|
||||
.chat-discussion .chat-message.left .message-date {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n) .message-date {
|
||||
.chat-discussion .chat-message.right .message-date {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n+1) .message {
|
||||
.chat-discussion .chat-message.left .message {
|
||||
text-align: left;
|
||||
margin-left: 55px;
|
||||
}
|
||||
|
||||
.chat-discussion .chat-message:nth-child(2n) .message {
|
||||
.chat-discussion .chat-message.right .message {
|
||||
text-align: right;
|
||||
margin-right: 55px;
|
||||
}
|
||||
@@ -5034,6 +5040,7 @@ dd.project-people {
|
||||
.chat-message-form .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* jsTree */
|
||||
.jstree-open>.jstree-anchor>.fa-folder:before {
|
||||
content: "\f07c";
|
||||
|
||||
@@ -346,7 +346,7 @@ label.error {
|
||||
right: 3px
|
||||
}
|
||||
|
||||
.Validform_error,input.error,select.error {
|
||||
.Validform_error,input.error,textarea.error,select.error {
|
||||
background-color: #fbe2e2;
|
||||
border-color: #c66161;
|
||||
color: #c00
|
||||
@@ -813,17 +813,21 @@ label {
|
||||
min-height: 75%;
|
||||
}
|
||||
|
||||
.table-striped .bootstrap-table {
|
||||
.table-striped .bootstrap-table, .table-striped .table-bordered {
|
||||
border: 0px!important;
|
||||
}
|
||||
|
||||
.table-bordered .table>thead>tr>th, .table-bordered .table>tbody>tr>th {
|
||||
font-weight: normal;
|
||||
font-size: 13px
|
||||
}
|
||||
|
||||
.table-striped table>thead>tr>th, .table-striped table>tbody>tr>th, .table-striped table>tfoot>tr>th, .table-striped table>thead>tr>td, .table-striped table>tbody>tr>td, .table-striped table>tfoot>tr>td {
|
||||
border-bottom: 1px solid #e7eaec!important;
|
||||
background-color: transparent;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
|
||||
.table-bordered table>thead>tr>th:first-child, .table-bordered table>tbody>tr>td:first-child {
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
@@ -848,12 +852,10 @@ label {
|
||||
.table-striped .table>thead>tr>th, .table-striped .table>tbody>tr>th {
|
||||
border-bottom: 1px solid #ccc!important;
|
||||
border-top: 0px!important;
|
||||
}
|
||||
|
||||
.table-striped .table>thead:first-child>tr:first-child>th {
|
||||
font-weight: normal;
|
||||
font-size: 13px
|
||||
}
|
||||
|
||||
.table-striped table thead {
|
||||
background-color: #eff3f8;
|
||||
}
|
||||
@@ -867,49 +869,35 @@ label {
|
||||
}
|
||||
|
||||
/** 表格冻结列样式 **/
|
||||
.left-fixed-table-columns, .left-fixed-body-columns {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
.fixed-columns, .fixed-columns-right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.left-fixed-table-columns .table, .left-fixed-body-columns .table {
|
||||
border-right: 1px solid #ddd;
|
||||
.fixed-columns {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.left-fixed-table-columns .table.table-no-bordered, .left-fixed-body-columns .table.table-no-bordered {
|
||||
border-right: 1px solid transparent;
|
||||
.fixed-columns .fixed-table-body {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.left-fixed-body-columns table {
|
||||
position: absolute;
|
||||
animation: none;
|
||||
.fixed-columns-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.fixed-columns-right .fixed-table-body {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.bootstrap-table .table-hover > tbody > tr.hover > td {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.right-fixed-table-columns{
|
||||
position: absolute;
|
||||
right:63px;
|
||||
border-left:1px solid #ddd;
|
||||
display: none;
|
||||
z-index:100;
|
||||
}
|
||||
|
||||
/** 表格全屏样式 **/
|
||||
.bootstrap-table.fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1050;
|
||||
width: 100%!important;
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
/** 表格树样式 **/
|
||||
.bootstrap-tree-table .treetable-indent {width:16px; height: 16px; display: inline-block; position: relative;}
|
||||
.bootstrap-tree-table .treetable-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
|
||||
@@ -1014,7 +1002,7 @@ label {
|
||||
}
|
||||
|
||||
/** 表格选中样式 **/
|
||||
.fixed-table-container .selected {
|
||||
.bootstrap-table .fixed-table-container .table tbody tr.selected td {
|
||||
background-color: #E8F7FD;
|
||||
color: #1890ff;
|
||||
}
|
||||
@@ -1070,14 +1058,20 @@ label {
|
||||
|
||||
/* 设置滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
background-color: #F5F5F5;
|
||||
width:10px!important;
|
||||
height:10px!important;
|
||||
-webkit-appearance:none;
|
||||
background:#f1f1f1
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background-color: #999;
|
||||
height:5px;
|
||||
border:1px solid transparent;
|
||||
border-top:0;
|
||||
border-bottom:0;
|
||||
border-radius:6px;
|
||||
background-color:#ccc;
|
||||
background-clip:padding-box
|
||||
}
|
||||
|
||||
/* 设置placeholder样式 */
|
||||
|
||||
@@ -30,12 +30,12 @@ $(function() {
|
||||
}
|
||||
SmoothlyMenu();
|
||||
});
|
||||
|
||||
|
||||
$('#side-menu>li').click(function() {
|
||||
if ($('body').hasClass('canvas-menu mini-navbar')) {
|
||||
NavToggle();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
$('#side-menu>li li a:not(:has(span))').click(function() {
|
||||
if ($(window).width() < 769) {
|
||||
@@ -72,6 +72,19 @@ $(window).bind("load resize", function() {
|
||||
}
|
||||
});
|
||||
|
||||
function syncMenuTab(dataId) {
|
||||
if(isLinkage) {
|
||||
var $dataObj = $('a[href$="' + decodeURI(dataId) + '"]');
|
||||
if ($dataObj.attr("class") != null && !$dataObj.hasClass("noactive")) {
|
||||
$('.nav ul').removeClass("in");
|
||||
$dataObj.parents("ul").addClass("in")
|
||||
$dataObj.parents("li").addClass("active").siblings().removeClass("active").find('li').removeClass("active");
|
||||
$dataObj.parents("ul").css('height', 'auto').height();
|
||||
$dataObj.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function NavToggle() {
|
||||
$('.navbar-minimalize').trigger('click');
|
||||
}
|
||||
@@ -114,11 +127,12 @@ $(function() {
|
||||
});
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
// 激活指定选项卡
|
||||
function setActiveTab(element) {
|
||||
if (!$(element).hasClass('active')) {
|
||||
var currentId = $(element).data('id');
|
||||
syncMenuTab(currentId);
|
||||
// 显示tab对应的内容区
|
||||
$('.RuoYi_iframe').each(function() {
|
||||
if ($(this).data('id') == currentId) {
|
||||
@@ -239,9 +253,17 @@ $(function() {
|
||||
dataIndex = $(this).data('index'),
|
||||
menuName = $.trim($(this).text()),
|
||||
flag = true;
|
||||
$(".nav ul li, .nav li").removeClass("selected");
|
||||
$(this).parent("li").addClass("selected");
|
||||
setIframeUrl($(this).attr("href"));
|
||||
|
||||
var $dataObj = $('a[href$="' + decodeURI(dataUrl) + '"]');
|
||||
if (!$dataObj.hasClass("noactive")) {
|
||||
$('.nav ul').removeClass("in");
|
||||
$dataObj.parents("ul").addClass("in")
|
||||
$dataObj.parents("li").addClass("active").siblings().removeClass("active").find('li').removeClass("active");
|
||||
$dataObj.parents("ul").css('height', 'auto').height();
|
||||
$(".nav ul li, .nav li").removeClass("selected");
|
||||
$(this).parent("li").addClass("selected");
|
||||
}
|
||||
setIframeUrl(dataUrl);
|
||||
if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false;
|
||||
|
||||
// 选项卡菜单已存在
|
||||
@@ -270,20 +292,20 @@ $(function() {
|
||||
// 添加选项卡对应的iframe
|
||||
var str1 = '<iframe class="RuoYi_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" seamless></iframe>';
|
||||
$('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1);
|
||||
|
||||
|
||||
$.modal.loading("数据加载中,请稍后...");
|
||||
|
||||
|
||||
$('.mainContent iframe:visible').load(function () {
|
||||
$.modal.closeLoading();
|
||||
});
|
||||
|
||||
|
||||
// 添加选项卡
|
||||
$('.menuTabs .page-tabs-content').append(str);
|
||||
scrollToTab($('.menuTab.active'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function menuBlank() {
|
||||
// 新窗口打开外网以http://开头,如http://ruoyi.vip
|
||||
var dataUrl = $(this).attr('href');
|
||||
@@ -292,7 +314,7 @@ $(function() {
|
||||
}
|
||||
|
||||
$('.menuItem').on('click', menuItem);
|
||||
|
||||
|
||||
$('.menuBlank').on('click', menuBlank);
|
||||
|
||||
// 关闭选项卡菜单
|
||||
@@ -357,7 +379,7 @@ $(function() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if($.common.isNotEmpty(panelUrl)){
|
||||
$('.menuTab[data-id="' + panelUrl + '"]').addClass('active').siblings('.menuTab').removeClass('active');
|
||||
$('.mainContent .RuoYi_iframe').each(function() {
|
||||
@@ -383,10 +405,10 @@ $(function() {
|
||||
});
|
||||
}
|
||||
scrollToTab($('.menuTab.active'));
|
||||
setIframeUrl($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
syncMenuTab($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$('.menuTabs').on('click', '.menuTab i', closeTab);
|
||||
|
||||
//滚动到已激活的选项卡
|
||||
@@ -399,6 +421,7 @@ $(function() {
|
||||
function activeTab() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
var currentId = $(this).data('id');
|
||||
syncMenuTab(currentId);
|
||||
// 显示tab对应的内容区
|
||||
$('.mainContent .RuoYi_iframe').each(function() {
|
||||
if ($(this).data('id') == currentId) {
|
||||
@@ -421,19 +444,19 @@ $(function() {
|
||||
var url = target.attr('src');
|
||||
target.attr('src', url).ready();
|
||||
}
|
||||
|
||||
|
||||
// 页签全屏
|
||||
function fullScreenTab() {
|
||||
var currentId = $('.page-tabs-content').find('.active').attr('data-id');
|
||||
var target = $('.RuoYi_iframe[data-id="' + currentId + '"]');
|
||||
target.fullScreen(true);
|
||||
}
|
||||
|
||||
|
||||
// 关闭当前选项卡
|
||||
function tabCloseCurrent() {
|
||||
$('.page-tabs-content').find('.active i').trigger("click");
|
||||
}
|
||||
|
||||
|
||||
//关闭其他选项卡
|
||||
function tabCloseOther() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() {
|
||||
@@ -441,9 +464,8 @@ $(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
setIframeUrl($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
}
|
||||
|
||||
|
||||
// 关闭全部选项卡
|
||||
function tabCloseAll() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").each(function() {
|
||||
@@ -455,18 +477,18 @@ $(function() {
|
||||
$(this).addClass("active");
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
setIframeUrl($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
syncMenuTab($('.page-tabs-content').find('.active').attr('data-id'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 全屏显示
|
||||
$('#fullScreen').on('click', function () {
|
||||
$(document).toggleFullScreen();
|
||||
});
|
||||
|
||||
|
||||
// 页签刷新按钮
|
||||
$('.tabReload').on('click', refreshTab);
|
||||
|
||||
|
||||
// 页签全屏按钮
|
||||
$('.tabFullScreen').on('click', fullScreenTab);
|
||||
|
||||
@@ -478,33 +500,33 @@ $(function() {
|
||||
|
||||
// 右移按扭
|
||||
$('.tabRight').on('click', scrollTabRight);
|
||||
|
||||
|
||||
// 关闭当前
|
||||
$('.tabCloseCurrent').on('click', tabCloseCurrent);
|
||||
|
||||
|
||||
// 关闭其他
|
||||
$('.tabCloseOther').on('click', tabCloseOther);
|
||||
|
||||
// 关闭全部
|
||||
$('.tabCloseAll').on('click', tabCloseAll);
|
||||
|
||||
|
||||
// tab全屏显示
|
||||
$('.tabMaxCurrent').on('click', function () {
|
||||
$('.page-tabs-content').find('.active').trigger("dblclick");
|
||||
});
|
||||
|
||||
|
||||
// 关闭全屏
|
||||
$('#ax_close_max').click(function(){
|
||||
$('#content-main').toggleClass('max');
|
||||
$('#ax_close_max').hide();
|
||||
})
|
||||
|
||||
|
||||
// 双击选项卡全屏显示
|
||||
function activeTabMax() {
|
||||
$('#content-main').toggleClass('max');
|
||||
$('#ax_close_max').show();
|
||||
}
|
||||
|
||||
|
||||
// 设置锚点
|
||||
function setIframeUrl(href) {
|
||||
if($.common.equals("history", mode)) {
|
||||
@@ -515,20 +537,20 @@ $(function() {
|
||||
window.location.href = newUrl + "#" + href;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(window).keydown(function(event) {
|
||||
if (event.keyCode == 27) {
|
||||
$('#content-main').removeClass('max');
|
||||
$('#ax_close_max').hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
window.onhashchange = function() {
|
||||
var hash = location.hash;
|
||||
var url = hash.substring(1, hash.length);
|
||||
$('a[href$="' + url + '"]').click();
|
||||
};
|
||||
|
||||
|
||||
// 右键菜单实现
|
||||
$.contextMenu({
|
||||
selector: ".menuTab",
|
||||
|
||||
@@ -266,7 +266,7 @@ var closeItem = function(dataId){
|
||||
/** 创建选项卡 */
|
||||
function createMenuItem(dataUrl, menuName) {
|
||||
var panelUrl = window.frameElement.getAttribute('data-id');
|
||||
dataIndex = $.common.random(1,100),
|
||||
dataIndex = $.common.random(1, 100),
|
||||
flag = true;
|
||||
if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false;
|
||||
var topWindow = $(window.parent.document);
|
||||
@@ -275,6 +275,7 @@ function createMenuItem(dataUrl, menuName) {
|
||||
if ($(this).data('id') == dataUrl) {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$(this).addClass('active').siblings('.menuTab').removeClass('active');
|
||||
scrollToTab(this);
|
||||
$('.page-tabs-content').animate({ marginLeft: ""}, "fast");
|
||||
// 显示tab对应的内容区
|
||||
$('.mainContent .RuoYi_iframe', topWindow).each(function() {
|
||||
@@ -290,7 +291,7 @@ function createMenuItem(dataUrl, menuName) {
|
||||
});
|
||||
// 选项卡菜单不存在
|
||||
if (flag) {
|
||||
var str = '<a href="javascript:;" class="active menuTab" data-id="' + dataUrl + '" data-panel="' + panelUrl + '">' + menuName + ' <i class="fa fa-times-circle"></i></a>';
|
||||
var str = '<a href="javascript:;" class="active menuTab noactive" data-id="' + dataUrl + '" data-panel="' + panelUrl + '">' + menuName + ' <i class="fa fa-times-circle"></i></a>';
|
||||
$('.menuTab', topWindow).removeClass('active');
|
||||
|
||||
// 添加选项卡对应的iframe
|
||||
@@ -304,10 +305,74 @@ function createMenuItem(dataUrl, menuName) {
|
||||
|
||||
// 添加选项卡
|
||||
$('.menuTabs .page-tabs-content', topWindow).append(str);
|
||||
scrollToTab($('.menuTab.active', topWindow));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 滚动到指定选项卡
|
||||
function scrollToTab(element) {
|
||||
var topWindow = $(window.parent.document);
|
||||
var marginLeftVal = calSumWidth($(element).prevAll()),
|
||||
marginRightVal = calSumWidth($(element).nextAll());
|
||||
// 可视区域非tab宽度
|
||||
var tabOuterWidth = calSumWidth($(".content-tabs", topWindow).children().not(".menuTabs"));
|
||||
//可视区域tab宽度
|
||||
var visibleWidth = $(".content-tabs", topWindow).outerWidth(true) - tabOuterWidth;
|
||||
//实际滚动宽度
|
||||
var scrollVal = 0;
|
||||
if ($(".page-tabs-content", topWindow).outerWidth() < visibleWidth) {
|
||||
scrollVal = 0;
|
||||
} else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {
|
||||
if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {
|
||||
scrollVal = marginLeftVal;
|
||||
var tabElement = element;
|
||||
while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content", topWindow).outerWidth() - visibleWidth)) {
|
||||
scrollVal -= $(tabElement).prev().outerWidth();
|
||||
tabElement = $(tabElement).prev();
|
||||
}
|
||||
}
|
||||
} else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {
|
||||
scrollVal = marginLeftVal - $(element).prev().outerWidth(true);
|
||||
}
|
||||
$('.page-tabs-content', topWindow).animate({ marginLeft: 0 - scrollVal + 'px' }, "fast");
|
||||
}
|
||||
|
||||
//计算元素集合的总宽度
|
||||
function calSumWidth(elements) {
|
||||
var width = 0;
|
||||
$(elements).each(function() {
|
||||
width += $(this).outerWidth(true);
|
||||
});
|
||||
return width;
|
||||
}
|
||||
|
||||
/** 密码规则范围验证 */
|
||||
function checkpwd(chrtype, password) {
|
||||
if (chrtype == 1) {
|
||||
if(!$.common.numValid(password)){
|
||||
$.modal.alertWarning("密码只能为0-9数字");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 2) {
|
||||
if(!$.common.enValid(password)){
|
||||
$.modal.alertWarning("密码只能为a-z和A-Z字母");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 3) {
|
||||
if(!$.common.enNumValid(password)){
|
||||
$.modal.alertWarning("密码必须包含字母以及数字");
|
||||
return false;
|
||||
}
|
||||
} else if (chrtype == 4) {
|
||||
if(!$.common.charValid(password)){
|
||||
$.modal.alertWarning("密码必须包含字母、数字、以及特殊符号-、_");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 日志打印封装处理
|
||||
var log = {
|
||||
log: function(msg) {
|
||||
|
||||
@@ -11,7 +11,7 @@ var table = {
|
||||
// 设置实例配置
|
||||
set: function(id) {
|
||||
if($.common.getLength(table.config) > 1) {
|
||||
var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find(".table").attr("id") : id;
|
||||
var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") : id;
|
||||
if ($.common.isNotEmpty(tableId)) {
|
||||
table.options = table.get(tableId);
|
||||
}
|
||||
@@ -38,6 +38,7 @@ var table = {
|
||||
var defaults = {
|
||||
id: "bootstrap-table",
|
||||
type: 0, // 0 代表bootstrapTable 1代表bootstrapTreeTable
|
||||
method: 'post',
|
||||
height: undefined,
|
||||
sidePagination: "server",
|
||||
sortName: "",
|
||||
@@ -48,6 +49,7 @@ var table = {
|
||||
pageNumber: 1,
|
||||
pageList: [10, 25, 50],
|
||||
toolbar: "toolbar",
|
||||
loadingFontSize: 13,
|
||||
striped: false,
|
||||
escape: false,
|
||||
firstLoad: true,
|
||||
@@ -62,11 +64,11 @@ var table = {
|
||||
clickToSelect: false,
|
||||
singleSelect: false,
|
||||
mobileResponsive: true,
|
||||
maintainSelected: false,
|
||||
rememberSelected: false,
|
||||
fixedColumns: false,
|
||||
fixedNumber: 0,
|
||||
rightFixedColumns: false,
|
||||
rightFixedNumber: 0,
|
||||
fixedRightNumber: 0,
|
||||
queryParams: $.table.queryParams,
|
||||
rowStyle: {},
|
||||
};
|
||||
@@ -78,7 +80,7 @@ var table = {
|
||||
id: options.id,
|
||||
url: options.url, // 请求后台的URL(*)
|
||||
contentType: "application/x-www-form-urlencoded", // 编码类型
|
||||
method: 'post', // 请求方式(*)
|
||||
method: options.method, // 请求方式(*)
|
||||
cache: false, // 是否使用缓存
|
||||
height: options.height, // 表格的高度
|
||||
striped: options.striped, // 是否显示行间隔色
|
||||
@@ -96,6 +98,7 @@ var table = {
|
||||
showFooter: options.showFooter, // 是否显示表尾
|
||||
iconSize: 'outline', // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
|
||||
toolbar: '#' + options.toolbar, // 指定工作栏
|
||||
loadingFontSize: options.loadingFontSize, // 自定义加载文本的字体大小
|
||||
sidePagination: options.sidePagination, // server启用服务端分页client客户端分页
|
||||
search: options.search, // 是否显示搜索框功能
|
||||
searchText: options.searchText, // 搜索框初始显示的内容,默认为空
|
||||
@@ -119,11 +122,11 @@ var table = {
|
||||
onDblClickCell: options.onDblClickCell, // 双击某格触发的事件
|
||||
onEditableSave: options.onEditableSave, // 行内编辑保存的事件
|
||||
onExpandRow: options.onExpandRow, // 点击详细视图的事件
|
||||
maintainSelected: options.maintainSelected, // 前端翻页时保留所选行
|
||||
rememberSelected: options.rememberSelected, // 启用翻页记住前面的选择
|
||||
fixedColumns: options.fixedColumns, // 是否启用冻结列(左侧)
|
||||
fixedNumber: options.fixedNumber, // 列冻结的个数(左侧)
|
||||
rightFixedColumns: options.rightFixedColumns, // 是否启用冻结列(右侧)
|
||||
rightFixedNumber: options.rightFixedNumber, // 列冻结的个数(右侧)
|
||||
fixedRightNumber: options.fixedRightNumber, // 列冻结的个数(右侧)
|
||||
onReorderRow: options.onReorderRow, // 当拖拽结束后处理函数
|
||||
queryParams: options.queryParams, // 传递参数(*)
|
||||
rowStyle: options.rowStyle, // 通过自定义函数设置行样式
|
||||
@@ -159,8 +162,8 @@ var table = {
|
||||
},
|
||||
// 请求获取数据后处理回调函数
|
||||
responseHandler: function(res) {
|
||||
if (typeof table.options.responseHandler == "function") {
|
||||
table.options.responseHandler(res);
|
||||
if (typeof table.get(this.id).responseHandler == "function") {
|
||||
table.get(this.id).responseHandler(res);
|
||||
}
|
||||
if (res.code == 0) {
|
||||
if ($.common.isNotEmpty(table.options.sidePagination) && table.options.sidePagination == 'client') {
|
||||
@@ -188,8 +191,9 @@ var table = {
|
||||
table.set($(this).attr("id"));
|
||||
});
|
||||
// 选中、取消、全部选中、全部取消(事件)
|
||||
$(optionsIds).on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rows) {
|
||||
$(optionsIds).on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rowsAfter, rowsBefore) {
|
||||
// 复选框分页保留保存选中数组
|
||||
var rows = $.common.equals("uncheck-all", e.type) ? rowsBefore : rowsAfter;
|
||||
var rowIds = $.table.affectedRowIds(rows);
|
||||
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
|
||||
func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
|
||||
@@ -291,7 +295,7 @@ var table = {
|
||||
_value = _value.replace(/\'/g,"'");
|
||||
_value = _value.replace(/\"/g,""");
|
||||
var actions = [];
|
||||
actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;z-index:-1" type="text" value="%s"/>', _value));
|
||||
actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;width:5px;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 {
|
||||
@@ -328,24 +332,10 @@ var table = {
|
||||
}
|
||||
},
|
||||
// 搜索-默认第一个form
|
||||
search: function(formId, tableId, data) {
|
||||
search: function(formId, tableId) {
|
||||
table.set(tableId);
|
||||
var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
|
||||
var params = $.common.isEmpty(tableId) ? $("#" + table.options.id).bootstrapTable('getOptions') : $("#" + tableId).bootstrapTable('getOptions');
|
||||
params.queryParams = function(params) {
|
||||
var search = $.common.formToJSON(currentId);
|
||||
if($.common.isNotEmpty(data)){
|
||||
$.each(data, function(key) {
|
||||
search[key] = data[key];
|
||||
});
|
||||
}
|
||||
search.pageSize = params.limit;
|
||||
search.pageNum = params.offset / params.limit + 1;
|
||||
search.searchValue = params.search;
|
||||
search.orderByColumn = params.sort;
|
||||
search.isAsc = params.order;
|
||||
return search;
|
||||
}
|
||||
if($.common.isNotEmpty(tableId)){
|
||||
$("#" + tableId).bootstrapTable('refresh', params);
|
||||
} else{
|
||||
@@ -801,22 +791,34 @@ var table = {
|
||||
options.callBack(index, layero);
|
||||
}
|
||||
}
|
||||
layer.open({
|
||||
type: 2,
|
||||
maxmin: true,
|
||||
shade: 0.3,
|
||||
title: _title,
|
||||
fix: false,
|
||||
area: [_width + 'px', _height + 'px'],
|
||||
content: _url,
|
||||
shadeClose: $.common.isEmpty(options.shadeClose) ? true : options.shadeClose,
|
||||
skin: options.skin,
|
||||
btn: $.common.isEmpty(options.btn) ? _btn : options.btn,
|
||||
yes: options.yes,
|
||||
cancel: function () {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
var btnCallback = {};
|
||||
if(options.btn instanceof Array){
|
||||
for (var i = 1, len = options.btn.length; i < len; i++) {
|
||||
var btn = options["btn" + (i + 1)];
|
||||
if (btn) {
|
||||
btnCallback["btn" + (i + 1)] = btn;
|
||||
}
|
||||
}
|
||||
}
|
||||
var index = layer.open($.extend({
|
||||
type: 2,
|
||||
maxmin: $.common.isEmpty(options.maxmin) ? true : options.maxmin,
|
||||
shade: 0.3,
|
||||
title: _title,
|
||||
fix: false,
|
||||
area: [_width + 'px', _height + 'px'],
|
||||
content: _url,
|
||||
shadeClose: $.common.isEmpty(options.shadeClose) ? true : options.shadeClose,
|
||||
skin: options.skin,
|
||||
btn: $.common.isEmpty(options.btn) ? _btn : options.btn,
|
||||
yes: options.yes,
|
||||
cancel: function () {
|
||||
return true;
|
||||
}
|
||||
}, btnCallback));
|
||||
if ($.common.isNotEmpty(options.full) && options.full === true) {
|
||||
layer.full(index);
|
||||
}
|
||||
},
|
||||
// 弹出层全屏
|
||||
openFull: function (title, url, width, height) {
|
||||
@@ -1567,6 +1569,26 @@ var table = {
|
||||
isMobile: function () {
|
||||
return navigator.userAgent.match(/(Android|iPhone|SymbianOS|Windows Phone|iPad|iPod)/i);
|
||||
},
|
||||
// 数字正则表达式,只能为0-9数字
|
||||
numValid : function(text){
|
||||
var patten = new RegExp(/^[0-9]+$/);
|
||||
return patten.test(text);
|
||||
},
|
||||
// 英文正则表达式,只能为a-z和A-Z字母
|
||||
enValid : function(text){
|
||||
var patten = new RegExp(/^[a-zA-Z]+$/);
|
||||
return patten.test(text);
|
||||
},
|
||||
// 英文、数字正则表达式,必须包含(字母,数字)
|
||||
enNumValid : function(text){
|
||||
var patten = new RegExp(/^(?=.*[a-zA-Z]+)(?=.*[0-9]+)[a-zA-Z0-9]+$/);
|
||||
return patten.test(text);
|
||||
},
|
||||
// 英文、数字、特殊字符正则表达式,必须包含(字母,数字,特殊字符-_)
|
||||
charValid : function(text){
|
||||
var patten = new RegExp(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[-_])[A-Za-z\d-_]{6,}$/);
|
||||
return patten.test(text);
|
||||
},
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<h2>若依后台管理系统</h2>
|
||||
<p>ruoyi是一个完全响应式,基于Bootstrap3.3.6最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了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.3.0
|
||||
<b>当前版本:</b>v4.4.0
|
||||
</p>
|
||||
<p>
|
||||
<span class="label label-warning">免费开源</span>
|
||||
@@ -56,7 +56,7 @@
|
||||
<h3>你好,若依 </h3>
|
||||
<p>H+是一个完全响应式,基于Bootstrap3.3.6最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了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.3.0
|
||||
<b>当前版本:</b>v4.4.0
|
||||
</p>
|
||||
<p>
|
||||
<span class="label label-warning">开源免费</span>
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
function onEditableSave (field, row, oldValue, $el) {
|
||||
function onEditableSave (field, row, rowIndex, oldValue, $el) {
|
||||
alert("字段名:" + field + ",当前值:" + row[field] + ",旧值:" + oldValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-export-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
var datas = [[${@dict.getType('sys_normal_disable')}]];
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-fixed-columns-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
var datas = [[${@dict.getType('sys_normal_disable')}]];
|
||||
@@ -36,6 +37,7 @@
|
||||
showColumns: false,
|
||||
fixedColumns: true,
|
||||
fixedNumber: 3,
|
||||
fixedRightNumber: 3,
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<!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">
|
||||
<!-- data-show-print设置为true为显示工具栏上的“打印”按钮。
|
||||
data-print-as-filtered-and-sorted-on-ui为true时-在用户界面上按排序和过滤条件打印表格。请注意,如果设置为true以及用于过滤和排序的显式预定义打印选项(printFilter,printSortOrder,printSortColumn),则它们将应用于已由UI控件过滤和排序的数据。对于在UI上按过滤和排序方式打印数据-请勿设置以下3个选项:printFilter,printSortOrder,printSortColumn
|
||||
data-print-page-builder 接收html <table>元素作为字符串参数,返回html字符串进行打印。用于样式和添加页眉或页脚。
|
||||
data-print-sort-column 设置列字段名称以对打印表进行排序
|
||||
data-print-sort-order 有效值:“ asc”,“ desc”。仅当设置了printSortColumn时相关
|
||||
data-print-filter 设置值以按此列过滤打印的数据。
|
||||
data-print-formatter 函数(值,行,索引)-返回字符串。格式化打印表中此列的单元格值。函数行为类似于“ formatter”列选项
|
||||
printIgnore 设置为true可以在打印页面中隐藏此列。 -->
|
||||
<table id="bootstrap-table" data-show-print="true"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-print-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
showSearch: false,
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field : 'userId',
|
||||
title : '用户ID'
|
||||
},
|
||||
{
|
||||
field : 'userCode',
|
||||
title : '用户编号'
|
||||
},
|
||||
{
|
||||
field : 'userName',
|
||||
title : '用户姓名'
|
||||
},
|
||||
{
|
||||
field : 'userPhone',
|
||||
title : '用户手机'
|
||||
},
|
||||
{
|
||||
field : 'userEmail',
|
||||
title : '用户邮箱'
|
||||
},
|
||||
{
|
||||
field : 'userBalance',
|
||||
title : '用户余额'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
var actions = [];
|
||||
actions.push('<a class="btn btn-danger btn-xs" href="javascript:;" onclick="remove(this)"><i class="fa fa-remove"></i>删除</a>');
|
||||
return actions.join('');
|
||||
}
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
// 假删除操作
|
||||
function remove(obj) {
|
||||
$.modal.confirm("确认要删除吗?", function() {
|
||||
$(obj).parents("tr").remove();
|
||||
$.modal.msgSuccess('已删除!');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!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">
|
||||
<!-- data-auto-refresh设置true为启用自动刷新插件
|
||||
data-auto-refresh-interval为每次自动刷新发生的时间(以秒为单位)默认60。
|
||||
data-auto-refresh-silent设置为true可以自动无提示刷新。默认: true
|
||||
data-auto-refresh-status 设置true为启用自动刷新。这是表加载时自动刷新的状态。单击按钮切换此属性。这只是自动刷新的默认状态,因为用户始终可以通过单击按钮来更改它。 默认: true -->
|
||||
<table id="bootstrap-table" data-auto-refresh="true" data-auto-refresh-interval="30"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="include :: footer"></div>
|
||||
<th:block th:include="include :: bootstrap-table-auto-refresh-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "demo/table";
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
showSearch: false,
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field : 'userId',
|
||||
title : '用户ID'
|
||||
},
|
||||
{
|
||||
field : 'userCode',
|
||||
title : '用户编号'
|
||||
},
|
||||
{
|
||||
field : 'userName',
|
||||
title : '用户姓名'
|
||||
},
|
||||
{
|
||||
field : 'userPhone',
|
||||
title : '用户手机'
|
||||
},
|
||||
{
|
||||
field : 'userEmail',
|
||||
title : '用户邮箱'
|
||||
},
|
||||
{
|
||||
field : 'userBalance',
|
||||
title : '用户余额'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
var actions = [];
|
||||
actions.push('<a class="btn btn-danger btn-xs" href="javascript:;" onclick="remove(this)"><i class="fa fa-remove"></i>删除</a>');
|
||||
return actions.join('');
|
||||
}
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
// 假删除操作
|
||||
function remove(obj) {
|
||||
$.modal.confirm("确认要删除吗?", function() {
|
||||
$(obj).parents("tr").remove();
|
||||
$.modal.msgSuccess('已删除!');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<p class="select-title">时间条件查询</p>
|
||||
<form id="time-form">
|
||||
@@ -61,10 +61,10 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<p class="select-title">多级联动下拉查询</p>
|
||||
<form id="select-form">
|
||||
<form id="cxselect-form">
|
||||
<div class="select-list">
|
||||
<ul id="element">
|
||||
<li>
|
||||
@@ -78,13 +78,13 @@
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i> 搜索</a>
|
||||
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('select-form')"><i class="fa fa-refresh"></i> 重置</a>
|
||||
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('cxselect-form')"><i class="fa fa-refresh"></i> 重置</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<p class="select-title">下拉多选条件查询</p>
|
||||
<form id="select-form">
|
||||
@@ -113,7 +113,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<p class="select-title">复杂条件查询</p>
|
||||
<form id="complex-form">
|
||||
@@ -174,7 +174,7 @@
|
||||
<span>-</span>
|
||||
<input type="text" class="time-input" placeholder="结束时间"/>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a class="btn btn-primary btn-rounded btn-sm m50" onclick="$.table.search()"><i class="fa fa-search"></i> 搜索</a>
|
||||
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('complex-form')"><i class="fa fa-refresh"></i> 重置</a>
|
||||
@@ -188,7 +188,7 @@
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: bootstrap-select-js" />
|
||||
<th:block th:include="include :: jquery-cxselect-js" />
|
||||
|
||||
|
||||
<script th:inline="javascript">
|
||||
// 直接返回获取
|
||||
var data = [{"v":"taobao","n":"淘宝","s":[{"v":"tm","n":"天猫"},{"v":"jhs","n":"聚划算"}]},{"v":"jd","n":"京东","s":[{"v":"jdcs","n":"京东超市"},{"v":"jdsx","n":"京东生鲜"}]}];
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
sidePagination: "client",
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
@@ -118,6 +119,15 @@
|
||||
formatter: function(value, row, index) {
|
||||
var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].weight' value='%s'>", index, value);
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'date',
|
||||
align: 'center',
|
||||
title: '商品日期',
|
||||
formatter: function(value, row, index) {
|
||||
var html = $.common.sprintf("<input class='form-control' type='text' name='goods[%s].date' value='%s' placeholder='yyyy-MM-dd'>", index, value);
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -154,6 +164,15 @@
|
||||
autoclose: true
|
||||
});
|
||||
|
||||
function bindDatetimepicker() {
|
||||
$("input[name$='date']").datetimepicker({
|
||||
format: "yyyy-mm-dd",
|
||||
minView: "month",
|
||||
autoclose: true,
|
||||
pickerPosition:'top-right'
|
||||
});
|
||||
}
|
||||
|
||||
function addColumn() {
|
||||
var count = $("#" + table.options.id).bootstrapTable('getData').length;
|
||||
sub.editColumn();
|
||||
@@ -165,9 +184,12 @@
|
||||
name: "",
|
||||
weight: "",
|
||||
price: "",
|
||||
date: "",
|
||||
type: "",
|
||||
}
|
||||
});
|
||||
|
||||
bindDatetimepicker();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
|
||||
<!-- bootstrap-table 表格插件样式 -->
|
||||
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=20200727}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/style.css?v=20200318}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/style.css?v=20200727}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.4.0}" rel="stylesheet"/>
|
||||
</head>
|
||||
|
||||
<!-- 通用JS -->
|
||||
@@ -22,27 +22,22 @@
|
||||
<script th:src="@{/js/jquery.min.js}"></script>
|
||||
<script th:src="@{/js/bootstrap.min.js}"></script>
|
||||
<!-- bootstrap-table 表格插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=20200529}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/toolbar/bootstrap-table-toolbar.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=20200727}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=20200727}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js?v=20200727}"></script>
|
||||
<!-- jquery-validate 表单验证插件 -->
|
||||
<script th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/validate/messages_zh.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js}"></script>
|
||||
<!-- jquery-validate 表单树插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-treetable/bootstrap-treetable.js}"></script>
|
||||
<!-- jquery-export 表格导出插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/tableExport.js}"></script>
|
||||
<!-- 遮罩层 -->
|
||||
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
|
||||
<script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/layui/layui.js}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.3.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.3.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.4.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.4.0}"></script>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; </script>
|
||||
</div>
|
||||
|
||||
@@ -97,12 +92,12 @@
|
||||
<script th:src="@{/ajax/libs/summernote/summernote-zh-CN.js}"></script>
|
||||
</div>
|
||||
|
||||
<!-- cropbox图像裁剪插件 -->
|
||||
<div th:fragment="cropbox-css">
|
||||
<link th:href="@{/ajax/libs/cropbox/cropbox.css}" rel="stylesheet"/>
|
||||
<!-- cropper图像裁剪插件 -->
|
||||
<div th:fragment="cropper-css">
|
||||
<link th:href="@{/ajax/libs/cropper/cropper.min.css}" rel="stylesheet"/>
|
||||
</div>
|
||||
<div th:fragment="cropbox-js">
|
||||
<script th:src="@{/ajax/libs/cropbox/cropbox.js}"></script>
|
||||
<div th:fragment="cropper-js">
|
||||
<script th:src="@{/ajax/libs/cropper/cropper.min.js}"></script>
|
||||
</div>
|
||||
|
||||
<!-- jasny功能扩展插件 -->
|
||||
@@ -187,5 +182,26 @@
|
||||
</div>
|
||||
<div th:fragment="bootstrap-table-editable-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-editable.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.js}"></script>
|
||||
</div>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/editable/bootstrap-table-editable.min.js?v=20200727}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格导出插件 -->
|
||||
<div th:fragment="bootstrap-table-export-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/bootstrap-table-export.js}"></script>
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/export/tableExport.js}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格冻结列插件 -->
|
||||
<div th:fragment="bootstrap-table-fixed-columns-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/columns/bootstrap-table-fixed-columns.min.js?v=20200727}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格自动刷新插件 -->
|
||||
<div th:fragment="bootstrap-table-auto-refresh-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js?v=20200729}"></script>
|
||||
</div>
|
||||
|
||||
<!-- 表格打印插件 -->
|
||||
<div th:fragment="bootstrap-table-print-js">
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/extensions/print/bootstrap-table-print.min.js?v=20200729}"></script>
|
||||
</div>
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
<title>若依系统首页</title>
|
||||
<!-- 避免IE使用兼容模式 -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link th:href="@{favicon.ico}" rel="stylesheet"/>
|
||||
<link th:href="@{favicon.ico}" rel="shortcut icon"/>
|
||||
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/style.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.3.0}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.4.0}" rel="stylesheet"/>
|
||||
</head>
|
||||
<body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden">
|
||||
<div id="wrapper">
|
||||
@@ -26,17 +26,17 @@
|
||||
</div>
|
||||
<a th:href="@{/index}">
|
||||
<li class="logo hidden-xs">
|
||||
<span class="logo-lg">RuoYi</span>
|
||||
<span class="logo-lg">RuoYi</span>
|
||||
</li>
|
||||
</a>
|
||||
<div class="sidebar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li>
|
||||
<div class="user-panel">
|
||||
<a class="menuItem noactive" title="个人中心" th:href="@{/system/user/profile}">
|
||||
<a class="menuItem noactive" title="个人中心" th:href="@{/system/user/profile}">
|
||||
<div class="hide" th:text="个人中心"></div>
|
||||
<div class="pull-left image">
|
||||
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{${user.avatar}}" class="img-circle" alt="User Image">
|
||||
<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="img-circle" alt="User Image">
|
||||
</div>
|
||||
</a>
|
||||
<div class="pull-left info">
|
||||
@@ -50,21 +50,21 @@
|
||||
<a class="menuItem" th:href="@{/system/main}"><i class="fa fa-home"></i> <span class="nav-label">首页</span> </a>
|
||||
</li>
|
||||
<li th:each="menu : ${menus}">
|
||||
<a th:class="@{${menu.url != '' && menu.url != '#'} ? ${menu.target}}" th:href="@{${menu.url == ''} ? |#| : ${menu.url}}">
|
||||
<a th:class="@{${!#strings.isEmpty(menu.url) && menu.url != '#'} ? ${menu.target}}" th:href="@{${#strings.isEmpty(menu.url)} ? |#| : ${menu.url}}">
|
||||
<i class="fa fa-bar-chart-o" th:class="${menu.icon}"></i>
|
||||
<span class="nav-label" th:text="${menu.menuName}">一级菜单</span>
|
||||
<span th:class="${menu.url == '' || menu.url == '#'} ? |fa arrow|"></span>
|
||||
<span class="nav-label" th:text="${menu.menuName}">一级菜单</span>
|
||||
<span th:class="${#strings.isEmpty(menu.url) || menu.url == '#'} ? |fa arrow|"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level collapse">
|
||||
<li th:each="cmenu : ${menu.children}">
|
||||
<a th:if="${#lists.isEmpty(cmenu.children)}" th:class="${cmenu.target == ''} ? |menuItem| : ${cmenu.target}" th:utext="${cmenu.menuName}" th:href="@{${cmenu.url}}">二级菜单</a>
|
||||
<a th:if="${#lists.isEmpty(cmenu.children)}" th:class="${#strings.isEmpty(cmenu.target)} ? |menuItem| : ${cmenu.target}" th:utext="${cmenu.menuName}" th:href="@{${cmenu.url}}">二级菜单</a>
|
||||
<a th:if="${not #lists.isEmpty(cmenu.children)}" href="#">[[${cmenu.menuName}]]<span class="fa arrow"></span></a>
|
||||
<ul th:if="${not #lists.isEmpty(cmenu.children)}" class="nav nav-third-level">
|
||||
<li th:each="emenu : ${cmenu.children}">
|
||||
<a th:if="${#lists.isEmpty(emenu.children)}" th:class="${emenu.target == ''} ? |menuItem| : ${emenu.target}" th:text="${emenu.menuName}" th:href="@{${emenu.url}}">三级菜单</a>
|
||||
<a th:if="${#lists.isEmpty(emenu.children)}" th:class="${#strings.isEmpty(emenu.target)} ? |menuItem| : ${emenu.target}" th:text="${emenu.menuName}" th:href="@{${emenu.url}}">三级菜单</a>
|
||||
<a th:if="${not #lists.isEmpty(emenu.children)}" href="#">[[${emenu.menuName}]]<span class="fa arrow"></span></a>
|
||||
<ul th:if="${not #lists.isEmpty(emenu.children)}" class="nav nav-four-level">
|
||||
<li th:each="fmenu : ${emenu.children}"><a th:if="${#lists.isEmpty(fmenu.children)}" th:class="${fmenu.target == ''} ? |menuItem| : ${fmenu.target}" th:text="${fmenu.menuName}" th:href="@{${fmenu.url}}">四级菜单</a></li>
|
||||
<li th:each="fmenu : ${emenu.children}"><a th:if="${#lists.isEmpty(fmenu.children)}" th:class="${#strings.isEmpty(fmenu.target)} ? |menuItem| : ${fmenu.target}" th:text="${fmenu.menuName}" th:href="@{${fmenu.url}}">四级菜单</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -116,6 +116,8 @@
|
||||
<li><a class="menuItem" th:href="@{/demo/table/reorder}">表格拖拽操作</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/editable}">表格行内编辑</a></li>
|
||||
<li><a class="menuItem" th:href="@{/demo/table/subdata}">主子表提交</a></li>
|
||||
<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/other}">表格其他操作</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -169,7 +171,7 @@
|
||||
</div>
|
||||
</nav>
|
||||
<!--左侧导航结束-->
|
||||
|
||||
|
||||
<!--右侧部分开始-->
|
||||
<div id="page-wrapper" class="gray-bg dashbard-1">
|
||||
<div class="row border-bottom">
|
||||
@@ -185,7 +187,7 @@
|
||||
<li><a title="全屏显示" href="javascript:void(0)" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏显示</a></li>
|
||||
<li class="dropdown user-menu">
|
||||
<a href="javascript:void(0)" class="dropdown-toggle" data-hover="dropdown">
|
||||
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{${user.avatar}}" class="user-image">
|
||||
<img th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" th:onerror="this.src='img/profile.jpg'" class="user-image">
|
||||
<span class="hidden-xs">[[${#strings.defaultString(user.userName, '-')}]]</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
@@ -217,7 +219,7 @@
|
||||
</button>
|
||||
<nav class="page-tabs menuTabs">
|
||||
<div class="page-tabs-content">
|
||||
<a href="javascript:;" class="active menuTab" data-id="/system/main">首页</a>
|
||||
<a href="javascript:;" class="active menuTab" th:data-id="@{/system/main}">首页</a>
|
||||
</div>
|
||||
</nav>
|
||||
<button class="roll-nav roll-right tabRight">
|
||||
@@ -225,11 +227,11 @@
|
||||
</button>
|
||||
<a href="javascript:void(0);" class="roll-nav roll-right tabReload"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
</div>
|
||||
|
||||
|
||||
<a id="ax_close_max" class="ax_close_max" href="#" title="关闭全屏"> <i class="fa fa-times-circle-o"></i> </a>
|
||||
|
||||
|
||||
<div class="row mainContent" id="content-main">
|
||||
<iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" data-id="/system/main"
|
||||
<iframe class="RuoYi_iframe" name="iframe0" width="100%" height="100%" th:data-id="@{/system/main}"
|
||||
th:src="@{/system/main}" frameborder="0" seamless></iframe>
|
||||
</div>
|
||||
<div class="footer">
|
||||
@@ -246,8 +248,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.3.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.3.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.4.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.4.0}"></script>
|
||||
<script th:src="@{/ruoyi/index.js}"></script>
|
||||
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
|
||||
<script th:inline="javascript">
|
||||
@@ -258,6 +260,8 @@ var skin = storage.get("skin");
|
||||
var mode = "history";
|
||||
// 历史访问路径缓存
|
||||
var historyPath = storage.get("historyPath");
|
||||
// 是否页签与菜单联动
|
||||
var isLinkage = true;
|
||||
|
||||
// 本地主题优先,未设置取系统配置
|
||||
if($.common.isNotEmpty(skin)){
|
||||
|
||||
@@ -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.css" th:href="@{/css/style.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.3.0}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.4.0}" rel="stylesheet"/>
|
||||
<!-- 360浏览器急速模式 -->
|
||||
<meta name="renderer" content="webkit">
|
||||
<!-- 避免IE使用兼容模式 -->
|
||||
@@ -78,7 +78,7 @@
|
||||
<script src="../static/ajax/libs/validate/messages_zh.min.js" th:src="@{/ajax/libs/validate/messages_zh.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.3.0}"></script>
|
||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.4.0}"></script>
|
||||
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -96,13 +96,92 @@
|
||||
<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="#v44">v4.4.0</a><code class="pull-right">2020.08.24</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v44" class="panel-collapse collapse in">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>升级bootstrapTable到最新版本1.17.1</li>
|
||||
<li>升级shiro到最新版1.6.0 阻止权限绕过漏洞</li>
|
||||
<li>升级fastjson到最新版1.2.73</li>
|
||||
<li>代码生成支持同步数据库</li>
|
||||
<li>代码生成支持富文本控件</li>
|
||||
<li>用户密码支持自定义配置规则</li>
|
||||
<li>新增表格自动刷新插件</li>
|
||||
<li>新增表格打印配置插件</li>
|
||||
<li>更换图片裁剪工具为cropper</li>
|
||||
<li>Excel支持sort导出排序</li>
|
||||
<li>代码生成支持自定义路径</li>
|
||||
<li>代码生成支持选择上级菜单</li>
|
||||
<li>代码生成支持上传控件</li>
|
||||
<li>新增表格参数(自定义加载文本的字体大小loadingFontSize)</li>
|
||||
<li>Excel注解支持设置BigDecimal精度&舍入规则</li>
|
||||
<li>操作日志记录排除敏感属性字段</li>
|
||||
<li>修复不同浏览器附件下载中文名乱码的问题</li>
|
||||
<li>用户分配角色不允许选择超级管理员角色</li>
|
||||
<li>更换表格冻结列插件</li>
|
||||
<li>添加右侧冻结列示例</li>
|
||||
<li>升级表格行编辑&移动端适应插件</li>
|
||||
<li>修复更新表格插件后无法设置实例配置问题</li>
|
||||
<li>修复更新表格插件后导致的主子表错误</li>
|
||||
<li>修复页面存在多表格,回调函数res数据不正确问题</li>
|
||||
<li>强退&过期清理登录帐号缓存会话</li>
|
||||
<li>表格树标题内容支持html语义化标签</li>
|
||||
<li>修复配置应用的访问路径首页页签重复问题</li>
|
||||
<li>优化openTab打开时滚动到当前页签</li>
|
||||
<li>表格请求方式method支持自定义配置</li>
|
||||
<li>菜单页签联动优化</li>
|
||||
<li>用户邮箱长度限制修改为50</li>
|
||||
<li>主子表示例添加日期格式案例</li>
|
||||
<li>修改表格行内编辑示例旧值参数</li>
|
||||
<li>操作日志查询方式调整</li>
|
||||
<li>唯一限制条件只返回单条数据</li>
|
||||
<li>修改Excel设置STRING单元格类型</li>
|
||||
<li>添加获取当前的环境配置方法</li>
|
||||
<li>截取返回参数长度,防止超出异常</li>
|
||||
<li>定时任务cron表达式验证</li>
|
||||
<li>拆分表格插件,按需引入</li>
|
||||
<li>多行文本框补齐必填错误提示背景</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="#v431">v4.3.1</a><code class="pull-right">2020.07.05</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v431" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>国家信息安全漏洞(请务必保持cipherKey密钥唯一性)</li>
|
||||
<li>升级shiro到最新版1.5.3 阻止权限绕过漏洞</li>
|
||||
<li>修改验证码在使用后清除,防止多次使用</li>
|
||||
<li>检查字符支持小数点&降级改成异常提醒</li>
|
||||
<li>openOptions函数中加入自定义maxmin属性</li>
|
||||
<li>支持openOptions方法最大化</li>
|
||||
<li>支持openOptions方法多个按钮回调</li>
|
||||
<li>新增isLinkage支持页签与菜单联动</li>
|
||||
<li>修改代码生成导入表结构出现异常页面不提醒问题</li>
|
||||
<li>优化用户头像发生错误,则显示一个默认头像</li>
|
||||
<li>Excel导出支持字典类型</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="#v43">v4.3.0</a><code class="pull-right">2020.06.22</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v43" class="panel-collapse collapse in">
|
||||
<div id="v43" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>代码生成模板支持主子表</li>
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: bootstrap-table-export-js" />
|
||||
<script th:inline="javascript">
|
||||
var forceFlag = [[${@permission.hasPermi('monitor:online:forceLogout')}]];
|
||||
var prefix = ctx + "monitor/online";
|
||||
@@ -61,7 +62,10 @@
|
||||
},
|
||||
{
|
||||
field: 'sessionId',
|
||||
title: '会话编号'
|
||||
title: '会话编号',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'loginName',
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
detailUrl: prefix + "/detail/{id}",
|
||||
removeUrl: prefix + "/remove",
|
||||
exportUrl: prefix + "/export",
|
||||
queryParams: queryParams,
|
||||
sortName: "operTime",
|
||||
sortOrder: "desc",
|
||||
modalName: "操作日志",
|
||||
@@ -148,10 +149,14 @@
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
function queryParams(params) {
|
||||
var search = $.table.queryParams(params);
|
||||
search.businessTypes = $.common.join($('#businessTypes').selectpicker('val'));
|
||||
return search;
|
||||
}
|
||||
|
||||
function searchPre() {
|
||||
var data = {};
|
||||
data.businessTypes = $.common.join($('#businessTypes').selectpicker('val'));
|
||||
$.table.search('operlog-form', 'bootstrap-table', data);
|
||||
$.table.search('operlog-form', 'bootstrap-table');
|
||||
}
|
||||
|
||||
function resetPre() {
|
||||
|
||||
@@ -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.css" th:href="@{/css/style.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.3.0}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.4.0}" rel="stylesheet"/>
|
||||
<!-- 360浏览器急速模式 -->
|
||||
<meta name="renderer" content="webkit">
|
||||
<!-- 避免IE使用兼容模式 -->
|
||||
@@ -77,7 +77,7 @@
|
||||
<script src="../static/ajax/libs/validate/messages_zh.min.js" th:src="@{/ajax/libs/validate/messages_zh.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.3.0}"></script>
|
||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.4.0}"></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.3.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=4.4.0}"></script>
|
||||
<script type="text/javascript">
|
||||
//皮肤样式列表
|
||||
var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<label class="col-sm-4 control-label is-required">邮箱:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="email" name="email" class="form-control email" type="text" maxlength="20" placeholder="请输入邮箱" required>
|
||||
<input id="email" name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱" required>
|
||||
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,7 +221,9 @@
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
|
||||
var password = $("#password").val();
|
||||
if ($.validate.form() && checkpwd(chrtype, password)) {
|
||||
var data = $("#form-user-add").serializeArray();
|
||||
var status = $("input[id='status']").is(':checked') == true ? 0 : 1;
|
||||
var roleIds = $.form.selectCheckeds("role");
|
||||
@@ -233,7 +235,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*用户管理-新增-选择部门树*/
|
||||
/* 用户管理-新增-选择部门树 */
|
||||
function selectDeptTree() {
|
||||
var treeId = $("#treeId").val();
|
||||
var deptId = $.common.isEmpty(treeId) ? "100" : $("#treeId").val();
|
||||
|
||||
@@ -47,36 +47,42 @@
|
||||
<th:block th:include="include :: footer" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "system/user/authRole";
|
||||
var userRoles = [[${userRoles}]]
|
||||
var roles = [[${roles}]]
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: ctx + "system/role/list",
|
||||
data: roles,
|
||||
sidePagination: "client",
|
||||
sortName: "roleSort",
|
||||
showSearch: false,
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
clickToSelect: true,
|
||||
maintainSelected: true,
|
||||
columns: [{
|
||||
checkbox: true,
|
||||
formatter:function (value, row, index) {
|
||||
for (var i = 0; i < userRoles.length; i++) {
|
||||
if (userRoles[i].roleId == row.roleId) {
|
||||
return { checked: true };
|
||||
}
|
||||
if($.common.isEmpty(value)) {
|
||||
return { checked: row.flag };
|
||||
} else {
|
||||
return { checked: value }
|
||||
}
|
||||
return { checked: false };
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'roleId',
|
||||
title: '角色编号'
|
||||
},
|
||||
{
|
||||
field: 'roleSort',
|
||||
title: '排序',
|
||||
sortable: true,
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'roleName',
|
||||
title: '角色名称',
|
||||
sortable: true
|
||||
title: '角色名称'
|
||||
},
|
||||
{
|
||||
field: 'roleKey',
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<label class="col-sm-4 control-label is-required">邮箱:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<input name="email" class="form-control email" type="text" maxlength="20" placeholder="请输入邮箱" th:field="*{email}" required>
|
||||
<input name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱" th:field="*{email}" required>
|
||||
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -200,7 +200,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*用户管理-修改-选择部门树*/
|
||||
/* 用户管理-修改-选择部门树 */
|
||||
function selectDeptTree() {
|
||||
var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
|
||||
var url = ctx + "system/dept/selectDeptTree/" + deptId;
|
||||
|
||||
@@ -2,82 +2,259 @@
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('修改用户头像')" />
|
||||
<th:block th:include="include :: cropbox-css" />
|
||||
<th:block th:include="include :: cropper-css" />
|
||||
<style type='text/css'>
|
||||
/* avator css start */
|
||||
.container {
|
||||
margin: 10px 5px 5px 5px;
|
||||
}
|
||||
|
||||
.action {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
|
||||
.cropped {
|
||||
width: 200px;
|
||||
border: 1px #ddd solid;
|
||||
box-shadow: 0px 0px 12px #ddd;
|
||||
}
|
||||
|
||||
.img-preview {
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 12px #7e7e7e;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.preview-box {
|
||||
text-align: center;
|
||||
margin: 0px auto;
|
||||
margin-top: 10px;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.preview-md {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
.preview-sm {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.preview-xs {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.imageBox {
|
||||
border: 1px solid #aaa;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
box-shadow: 4px 4px 12px #B0B0B0;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
.btn-custom {
|
||||
float: right;
|
||||
width: 46px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
margin: 0px 2px;
|
||||
background-color: #f38e81;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 0px 5px #B0B0B0;
|
||||
border: 0px #fff solid;
|
||||
}
|
||||
/*选择文件上传*/
|
||||
.new-contentarea {
|
||||
width: 165px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.new-contentarea label {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.new-contentarea input[type=file] {
|
||||
width: 188px;
|
||||
height: 60px;
|
||||
background: #333;
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
right: 50%;
|
||||
margin-right: -94px;
|
||||
top: 0;
|
||||
right/*\**/: 0px\9;
|
||||
margin-right/*\**/: 0px\9;
|
||||
width/*\**/: 10px\9;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
a.upload-img {
|
||||
width: 165px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
background-color: #f38e81;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
border: 0px #fff solid;
|
||||
box-shadow: 0px 0px 5px #B0B0B0;
|
||||
}
|
||||
|
||||
a.upload-img:hover {
|
||||
background-color: #ec7e70;
|
||||
}
|
||||
|
||||
.tc {
|
||||
text-align: center;
|
||||
}
|
||||
/* avator css end */
|
||||
</style>
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="container">
|
||||
<div class="imageBox">
|
||||
<div class="thumbBox"></div>
|
||||
<div class="spinner" style="display: none">Loading...</div>
|
||||
</div>
|
||||
<div class="action">
|
||||
<div class="new-contentarea tc">
|
||||
<a href="javascript:void(0)" class="upload-img"> <label for="avatar">上传图像</label> </a>
|
||||
<input type="file" class="" name="avatar" id="avatar" accept="image/*"/>
|
||||
</div>
|
||||
<input type="button" id="btnCrop" class="Btnsty_peyton" value="裁切" />
|
||||
<input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+" />
|
||||
<input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-" />
|
||||
</div>
|
||||
<div class="cropped"></div>
|
||||
</div>
|
||||
<div class="row container">
|
||||
<div class="col-md-10">
|
||||
<div class="imageBox">
|
||||
<img id="avatar" th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}" >
|
||||
</div>
|
||||
<div class="action">
|
||||
<div class="new-contentarea tc">
|
||||
<a href="javascript:void(0)" class="upload-img"><label for="inputImage">上传图像</label> </a>
|
||||
<input type="file" name="avatar" id="inputImage" accept="image/*"/>
|
||||
</div>
|
||||
<button type="button" class="btn-custom" data-method="zoom" data-option="0.1"><i class="fa fa-search-plus"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="zoom" data-option="-0.1"><i class="fa fa-search-minus"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="rotate" data-option="-45"><i class="fa fa-rotate-left"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="rotate" data-option="45"><i class="fa fa-rotate-right"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="scaleX" data-option="-1"><i class="fa fa-arrows-h"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="scaleY" data-option="-1"><i class="fa fa-arrows-v"></i></button>
|
||||
<button type="button" class="btn-custom" data-method="reset"><i class="fa fa-refresh"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="cropped">
|
||||
<div class="preview-box">
|
||||
<div class="img-preview preview-xs"></div>
|
||||
</div>
|
||||
<div class="preview-box">
|
||||
<div class="img-preview preview-sm"></div>
|
||||
</div>
|
||||
<div class="preview-box">
|
||||
<div class="img-preview preview-md"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: cropbox-js" />
|
||||
<th:block th:include="include :: cropper-js" />
|
||||
<script type="text/javascript">
|
||||
var cropper;
|
||||
var croppable = false;
|
||||
$(window).load(function() {
|
||||
var avatar = '[[${user.avatar}]]';
|
||||
var options = {
|
||||
thumbBox: '.thumbBox',
|
||||
spinner: '.spinner',
|
||||
imgSrc: $.common.isEmpty(avatar) ? ctx + 'img/profile.jpg' : ctx + avatar.substr(1)
|
||||
}
|
||||
cropper = $('.imageBox').cropbox(options);
|
||||
$('#avatar').on('change', function() {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
options.imgSrc = e.target.result;
|
||||
//根据MIME判断上传的文件是不是图片类型
|
||||
if((options.imgSrc).indexOf("image/")==-1){
|
||||
$.modal.alertWarning("文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。");
|
||||
} else {
|
||||
cropper = $('.imageBox').cropbox(options);
|
||||
}
|
||||
}
|
||||
reader.readAsDataURL(this.files[0]);
|
||||
})
|
||||
|
||||
$('#btnCrop').on('click', function(){
|
||||
var img = cropper.getDataURL();
|
||||
$('.cropped').html('');
|
||||
$('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:64px;margin-top:4px;border-radius:64px;box-shadow:0px 0px 12px #7E7E7E;" ><p>64px*64px</p>');
|
||||
$('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;"><p>128px*128px</p>');
|
||||
$('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:180px;margin-top:4px;border-radius:180px;box-shadow:0px 0px 12px #7E7E7E;"><p>180px*180px</p>');
|
||||
var image = document.getElementById('avatar');
|
||||
cropper = new Cropper(image, {
|
||||
aspectRatio: 1,
|
||||
viewMode: 1,
|
||||
autoCropArea: 0.9,
|
||||
preview: '.img-preview',
|
||||
ready: function () {
|
||||
croppable = true;
|
||||
}
|
||||
})
|
||||
|
||||
$('#btnZoomIn').on('click', function(){
|
||||
cropper.zoomIn();
|
||||
})
|
||||
|
||||
$('#btnZoomOut').on('click', function(){
|
||||
cropper.zoomOut();
|
||||
|
||||
$('#inputImage').on('change', function() {
|
||||
var reader = new FileReader();
|
||||
var file = $('#inputImage')[0].files[0];
|
||||
if (/^image\/\w+$/.test(file.type)) {
|
||||
reader.onload = function(e) {
|
||||
if(croppable){
|
||||
cropper.replace(e.target.result)
|
||||
}
|
||||
}
|
||||
reader.readAsDataURL(this.files[0]);
|
||||
} else {
|
||||
$.modal.alertWarning('请选择一个图片文件。');
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-custom').on('click',function (e) {
|
||||
if (!croppable) {
|
||||
$.modal.alertWarning("裁剪框加载中,请稍后...");
|
||||
return;
|
||||
}
|
||||
var data = {
|
||||
method: $(this).data('method'),
|
||||
option: $(this).data('option') || undefined,
|
||||
};
|
||||
var result = cropper[data.method](data.option, data.secondOption);
|
||||
if(['scaleX','scaleY'].indexOf(data.method) !== -1){
|
||||
$(this).data('option', -data.option)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
var img = cropper.getBlob();
|
||||
var formdata = new FormData();
|
||||
formdata.append("avatarfile", img);
|
||||
$.ajax({
|
||||
url: ctx + "system/user/profile/updateAvatar",
|
||||
data: formdata,
|
||||
type: "post",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(result) {
|
||||
$.operate.saveSuccess(result);
|
||||
if (!croppable) {
|
||||
$.modal.alertWarning("裁剪框加载中,请稍后...");
|
||||
return
|
||||
}
|
||||
cropper.getCroppedCanvas().toBlob(function(img) {
|
||||
var formdata = new FormData();
|
||||
formdata.append("avatarfile", img);
|
||||
$.ajax({
|
||||
url: ctx + "system/user/profile/updateAvatar",
|
||||
data: formdata,
|
||||
type: "post",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(result) {
|
||||
$.operate.saveSuccess(result);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
$(window).resize(function() {
|
||||
$('.imageBox').height($(window).height() - 80);
|
||||
$('.cropped').height($(window).height() - 40);
|
||||
}).resize();
|
||||
|
||||
if (!HTMLCanvasElement.prototype.toBlob) {
|
||||
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
|
||||
value: function(callback, type, quality) {
|
||||
var canvas = this;
|
||||
setTimeout(function() {
|
||||
var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]);
|
||||
var len = binStr.length;
|
||||
var arr = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = binStr.charCodeAt(i);
|
||||
}
|
||||
callback(new Blob([arr], {
|
||||
type: type || 'image/png'
|
||||
}));
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('用户个人信息')" />
|
||||
<style type="text/css">.user-info-head{position:relative;display:inline-block;}.user-info-head:hover:after{content:'\f030';position:absolute;left:0;right:0;top:0;bottom:0;color:#eee;background:rgba(0,0,0,0.5);font-family:FontAwesome;font-size:24px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;cursor:pointer;line-height:110px;border-radius:50%;}</style>
|
||||
</head>
|
||||
|
||||
<body class="gray-bg" style="font: 14px Helvetica Neue, Helvetica, PingFang SC, 微软雅黑, Tahoma, Arial, sans-serif !important;">
|
||||
@@ -15,7 +16,7 @@
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div class="text-center">
|
||||
<p><img class="img-circle img-lg" th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{${user.avatar}}"></p>
|
||||
<p class="user-info-head" onclick="avatar()"><img class="img-circle img-lg" th:src="(${#strings.isEmpty(user.avatar)}) ? @{/img/profile.jpg} : @{${user.avatar}}"></p>
|
||||
<p><a href="javascript:avatar()">修改头像</a></p>
|
||||
</div>
|
||||
<ul class="list-group list-group-striped">
|
||||
@@ -76,7 +77,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">邮箱:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="email" th:field="*{email}" placeholder="请输入邮箱">
|
||||
<input type="text" maxlength="50" class="form-control" name="email" th:field="*{email}" placeholder="请输入邮箱">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -143,9 +144,28 @@
|
||||
/*用户管理-头像*/
|
||||
function avatar() {
|
||||
var url = ctx + 'system/user/profile/avatar';
|
||||
$.modal.open("修改头像", url);
|
||||
top.layer.open({
|
||||
type: 2,
|
||||
area: [$(window).width() + 'px', $(window).height() + 'px'],
|
||||
fix: false,
|
||||
//不固定
|
||||
maxmin: true,
|
||||
shade: 0.3,
|
||||
title: "修改头像",
|
||||
content: url,
|
||||
btn: ['确定', '关闭'],
|
||||
// 弹层外区域关闭
|
||||
shadeClose: true,
|
||||
yes: function(index, layero) {
|
||||
var iframeWin = layero.find('iframe')[0];
|
||||
iframeWin.contentWindow.submitHandler(index, layero);
|
||||
},
|
||||
cancel: function(index) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*用户信息-修改*/
|
||||
$("#form-user-edit").validate({
|
||||
onkeyup: false,
|
||||
@@ -263,7 +283,9 @@
|
||||
});
|
||||
|
||||
function submitChangPassword () {
|
||||
if ($.validate.form("form-user-resetPwd")) {
|
||||
var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
|
||||
var password = $("#newPassword").val();
|
||||
if ($.validate.form("form-user-resetPwd") && checkpwd(chrtype, password)) {
|
||||
$.operate.saveModal(ctx + "system/user/profile/resetPwd", $('#form-user-resetPwd').serialize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">再次确认:</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="password" name="confirm" id="confirm">
|
||||
<input class="form-control" type="password" name="confirmPassword" id="confirmPassword">
|
||||
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 请再次输入您的密码</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,7 +57,7 @@
|
||||
minlength: 5,
|
||||
maxlength: 20
|
||||
},
|
||||
confirm: {
|
||||
confirmPassword: {
|
||||
required: true,
|
||||
equalTo: "#newPassword"
|
||||
}
|
||||
@@ -72,7 +72,7 @@
|
||||
minlength: "密码不能小于6个字符",
|
||||
maxlength: "密码不能大于20个字符"
|
||||
},
|
||||
confirm: {
|
||||
confirmPassword: {
|
||||
required: "请再次输入新密码",
|
||||
equalTo: "两次密码输入不一致"
|
||||
}
|
||||
@@ -82,7 +82,9 @@
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
var chrtype = [[${#strings.defaultString(@config.getKey('sys.account.chrtype'), 0)}]];
|
||||
var password = $("#newPassword").val();
|
||||
if ($.validate.form() && checkpwd(chrtype, password)) {
|
||||
$.operate.save(ctx + "system/user/profile/resetPwd", $('#form-user-resetPwd').serialize());
|
||||
}
|
||||
}
|
||||
|
||||
+85
-79
@@ -5,96 +5,102 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
|
||||
<description>
|
||||
common通用工具
|
||||
</description>
|
||||
|
||||
<description>
|
||||
common通用工具
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring框架基本的核心工具 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringWeb模块 -->
|
||||
<dependency>
|
||||
|
||||
<!-- Spring框架基本的核心工具 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringWeb模块 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--Shiro核心框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 自定义验证注解 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON工具类 -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- yml解析器 -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- servlet包 -->
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-ehcache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 自定义验证注解 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON工具类 -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- yml解析器 -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- servlet包 -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 自定义导出Excel数据注解
|
||||
@@ -14,6 +15,11 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Excel
|
||||
{
|
||||
/**
|
||||
* 导出时在excel中排序
|
||||
*/
|
||||
public int sort() default Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* 导出到Excel中的名字.
|
||||
*/
|
||||
@@ -24,6 +30,11 @@ public @interface Excel
|
||||
*/
|
||||
public String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
|
||||
*/
|
||||
public String dictType() default "";
|
||||
|
||||
/**
|
||||
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
|
||||
*/
|
||||
@@ -33,7 +44,17 @@ public @interface Excel
|
||||
* 分隔符,读取字符串组内容
|
||||
*/
|
||||
public String separator() default ",";
|
||||
|
||||
|
||||
/**
|
||||
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
|
||||
*/
|
||||
public int scale() default -1;
|
||||
|
||||
/**
|
||||
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
|
||||
*/
|
||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||
|
||||
/**
|
||||
* 导出类型(0数字 1字符串)
|
||||
*/
|
||||
|
||||
@@ -25,6 +25,12 @@ public class GenConstants
|
||||
/** 树名称字段 */
|
||||
public static final String TREE_NAME = "treeName";
|
||||
|
||||
/** 上级菜单ID字段 */
|
||||
public static final String PARENT_MENU_ID = "parentMenuId";
|
||||
|
||||
/** 上级菜单名称字段 */
|
||||
public static final String PARENT_MENU_NAME = "parentMenuName";
|
||||
|
||||
/** 数据库字符串类型 */
|
||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
|
||||
"mediumtext", "longtext" };
|
||||
@@ -71,6 +77,12 @@ public class GenConstants
|
||||
/** 日期控件 */
|
||||
public static final String HTML_DATETIME = "datetime";
|
||||
|
||||
/** 上传控件 */
|
||||
public static final String HTML_UPLOAD = "upload";
|
||||
|
||||
/** 富文本控件 */
|
||||
public static final String HTML_SUMMERNOTE = "summernote";
|
||||
|
||||
/** 字符串类型 */
|
||||
public static final String TYPE_STRING = "String";
|
||||
|
||||
|
||||
@@ -11,12 +11,15 @@ public class PageDomain
|
||||
{
|
||||
/** 当前记录起始索引 */
|
||||
private Integer pageNum;
|
||||
|
||||
/** 每页显示记录数 */
|
||||
private Integer pageSize;
|
||||
|
||||
/** 排序列 */
|
||||
private String orderByColumn;
|
||||
/** 排序的方向 "desc" 或者 "asc". */
|
||||
private String isAsc;
|
||||
|
||||
/** 排序的方向desc或者asc */
|
||||
private String isAsc = "asc";
|
||||
|
||||
public String getOrderBy()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.common.exception;
|
||||
|
||||
/**
|
||||
* 工具类异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UtilException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 8247610319171014183L;
|
||||
|
||||
public UtilException(Throwable e)
|
||||
{
|
||||
super(e.getMessage(), e);
|
||||
}
|
||||
|
||||
public UtilException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UtilException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
@@ -301,7 +301,6 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -364,7 +363,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式命名法 例如:user_name->userName
|
||||
* 驼峰式命名法
|
||||
* 例如:user_name->userName
|
||||
*/
|
||||
public static String toCamelCase(String s)
|
||||
{
|
||||
@@ -372,6 +372,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (s.indexOf(SEPARATOR) == -1)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
s = s.toLowerCase();
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
boolean upperCase = false;
|
||||
@@ -401,4 +405,4 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
{
|
||||
return (T) obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
|
||||
import com.ruoyi.common.exception.file.InvalidExtensionException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.security.Md5Utils;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
|
||||
/**
|
||||
* 文件上传工具类
|
||||
@@ -35,8 +35,6 @@ public class FileUploadUtils
|
||||
*/
|
||||
private static String defaultBaseDir = Global.getProfile();
|
||||
|
||||
private static int counter = 0;
|
||||
|
||||
public static void setDefaultBaseDir(String defaultBaseDir)
|
||||
{
|
||||
FileUploadUtils.defaultBaseDir = defaultBaseDir;
|
||||
@@ -125,7 +123,7 @@ public class FileUploadUtils
|
||||
{
|
||||
String fileName = file.getOriginalFilename();
|
||||
String extension = getExtension(file);
|
||||
fileName = DateUtils.datePath() + "/" + encodingFilename(fileName) + "." + extension;
|
||||
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@@ -152,16 +150,6 @@ public class FileUploadUtils
|
||||
return pathFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名
|
||||
*/
|
||||
private static final String encodingFilename(String fileName)
|
||||
{
|
||||
fileName = fileName.replace("_", " ");
|
||||
fileName = Md5Utils.hash(fileName + System.nanoTime() + counter++);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件大小校验
|
||||
*
|
||||
|
||||
@@ -7,14 +7,16 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 文件处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileUtils
|
||||
public class FileUtils extends org.apache.commons.io.FileUtils
|
||||
{
|
||||
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
|
||||
|
||||
@@ -139,4 +141,38 @@ public class FileUtils
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
* @param response 响应对象
|
||||
* @param realFileName 真实文件名
|
||||
* @return
|
||||
*/
|
||||
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
|
||||
{
|
||||
String percentEncodedFileName = percentEncode(realFileName);
|
||||
|
||||
StringBuilder contentDispositionValue = new StringBuilder();
|
||||
contentDispositionValue.append("attachment; filename=")
|
||||
.append(percentEncodedFileName)
|
||||
.append(";")
|
||||
.append("filename*=")
|
||||
.append("utf-8''")
|
||||
.append(percentEncodedFileName);
|
||||
|
||||
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 百分号编码工具方法
|
||||
*
|
||||
* @param s 需要百分号编码的字符串
|
||||
* @return 百分号编码后的字符串
|
||||
*/
|
||||
public static String percentEncode(String s) throws UnsupportedEncodingException
|
||||
{
|
||||
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
|
||||
return encode.replaceAll("\\+", "%20");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ public class EscapeUtil
|
||||
String html = "<script>alert(1);</script>";
|
||||
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
|
||||
// String html = "<123";
|
||||
// String html = "123>";
|
||||
System.out.println(EscapeUtil.clean(html));
|
||||
System.out.println(EscapeUtil.escape(html));
|
||||
System.out.println(EscapeUtil.unescape(html));
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class HTMLFilter
|
||||
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
|
||||
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
|
||||
private static final Pattern P_END_ARROW = Pattern.compile("^>");
|
||||
// private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
@@ -131,7 +131,7 @@ public final class HTMLFilter
|
||||
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
|
||||
stripComment = true;
|
||||
encodeQuotes = true;
|
||||
alwaysMakeTags = true;
|
||||
alwaysMakeTags = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,7 +246,7 @@ public final class HTMLFilter
|
||||
//
|
||||
s = regexReplace(P_END_ARROW, "", s);
|
||||
// 不追加结束标签
|
||||
// s = regexReplace(P_BODY_TO_END, "<$1>", s);
|
||||
s = regexReplace(P_BODY_TO_END, "<$1>", s);
|
||||
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ import java.math.BigDecimal;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
@@ -50,6 +52,7 @@ import com.ruoyi.common.exception.BusinessException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
|
||||
/**
|
||||
* Excel相关处理
|
||||
@@ -276,7 +279,11 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
||||
{
|
||||
val = reverseByExp(String.valueOf(val), attr.readConverterExp(), attr.separator());
|
||||
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.dictType()))
|
||||
{
|
||||
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
|
||||
}
|
||||
ReflectUtils.invokeSetter(entity, propertyName, val);
|
||||
}
|
||||
@@ -475,7 +482,7 @@ public class ExcelUtil<T>
|
||||
{
|
||||
if (ColumnType.STRING == attr.cellType())
|
||||
{
|
||||
cell.setCellType(CellType.NUMERIC);
|
||||
cell.setCellType(CellType.STRING);
|
||||
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
|
||||
}
|
||||
else if (ColumnType.NUMERIC == attr.cellType())
|
||||
@@ -536,13 +543,22 @@ public class ExcelUtil<T>
|
||||
String dateFormat = attr.dateFormat();
|
||||
String readConverterExp = attr.readConverterExp();
|
||||
String separator = attr.separator();
|
||||
String dictType = attr.dictType();
|
||||
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp, separator));
|
||||
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
|
||||
{
|
||||
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
|
||||
}
|
||||
else if (value instanceof BigDecimal && -1 != attr.scale())
|
||||
{
|
||||
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -672,39 +688,64 @@ public class ExcelUtil<T>
|
||||
public static String reverseByExp(String propertyValue, String converterExp, String separator) throws Exception
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
try
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
String[] itemArray = item.split("=");
|
||||
if (StringUtils.containsAny(separator, propertyValue))
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (StringUtils.containsAny(separator, propertyValue))
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
if (itemArray[1].equals(value))
|
||||
{
|
||||
if (itemArray[1].equals(value))
|
||||
{
|
||||
propertyString.append(itemArray[0] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itemArray[1].equals(propertyValue))
|
||||
{
|
||||
return itemArray[0];
|
||||
propertyString.append(itemArray[0] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
else
|
||||
{
|
||||
if (itemArray[1].equals(propertyValue))
|
||||
{
|
||||
return itemArray[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析字典值
|
||||
*
|
||||
* @param dictValue 字典值
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
public static String convertDictByExp(String dictValue, String dictType, String separator) throws Exception
|
||||
{
|
||||
Object bean = SpringUtils.getBean("dictUtils");
|
||||
String methodName = "getDictLabel";
|
||||
Method method = bean.getClass().getDeclaredMethod(methodName, String.class, String.class, String.class);
|
||||
return Convert.toStr(method.invoke(bean, dictType, dictValue, separator));
|
||||
}
|
||||
|
||||
/**
|
||||
* 反向解析值字典值
|
||||
*
|
||||
* @param dictLabel 字典标签
|
||||
* @param dictType 字典类型
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String reverseDictByExp(String dictLabel, String dictType, String separator) throws Exception
|
||||
{
|
||||
Object bean = SpringUtils.getBean("dictUtils");
|
||||
String methodName = "getDictValue";
|
||||
Method method = bean.getClass().getDeclaredMethod(methodName, String.class, String.class, String.class);
|
||||
return Convert.toStr(method.invoke(bean, dictType, dictLabel, separator));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名
|
||||
*/
|
||||
@@ -809,6 +850,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -881,7 +923,7 @@ public class ExcelUtil<T>
|
||||
{
|
||||
if ((Double) val % 1 > 0)
|
||||
{
|
||||
val = new DecimalFormat("0.00").format(val);
|
||||
val = new BigDecimal(val.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,7 +5,10 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* spring工具类 方便在非spring管理环境中获取bean
|
||||
@@ -13,17 +16,25 @@ import org.springframework.stereotype.Component;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
|
||||
{
|
||||
/** Spring应用上下文环境 */
|
||||
private static ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
{
|
||||
SpringUtils.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
SpringUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
*
|
||||
@@ -111,4 +122,25 @@ public final class SpringUtils implements BeanFactoryPostProcessor
|
||||
{
|
||||
return (T) AopContext.currentProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的环境配置,无配置返回null
|
||||
*
|
||||
* @return 当前的环境配置
|
||||
*/
|
||||
public static String[] getActiveProfiles()
|
||||
{
|
||||
return applicationContext.getEnvironment().getActiveProfiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
|
||||
*
|
||||
* @return 当前的环境配置
|
||||
*/
|
||||
public static String getActiveProfile()
|
||||
{
|
||||
final String[] activeProfiles = getActiveProfiles();
|
||||
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.common.utils.sql;
|
||||
|
||||
import com.ruoyi.common.exception.base.BaseException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -10,9 +11,9 @@ import com.ruoyi.common.utils.StringUtils;
|
||||
public class SqlUtil
|
||||
{
|
||||
/**
|
||||
* 仅支持字母、数字、下划线、空格、逗号(支持多个字段排序)
|
||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||
*/
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,]+";
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
||||
|
||||
/**
|
||||
* 检查字符,防止注入绕过
|
||||
@@ -21,7 +22,7 @@ public class SqlUtil
|
||||
{
|
||||
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
throw new BaseException("参数不符合规范,不能进行查询");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.ruoyi.common.utils.uuid;
|
||||
|
||||
/**
|
||||
* ID生成器工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class IdUtils
|
||||
{
|
||||
/**
|
||||
* 获取随机UUID
|
||||
*
|
||||
* @return 随机UUID
|
||||
*/
|
||||
public static String randomUUID()
|
||||
{
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的UUID,去掉了横线
|
||||
*
|
||||
* @return 简化的UUID,去掉了横线
|
||||
*/
|
||||
public static String simpleUUID()
|
||||
{
|
||||
return UUID.randomUUID().toString(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
|
||||
*
|
||||
* @return 随机UUID
|
||||
*/
|
||||
public static String fastUUID()
|
||||
{
|
||||
return UUID.fastUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
|
||||
*
|
||||
* @return 简化的UUID,去掉了横线
|
||||
*/
|
||||
public static String fastSimpleUUID()
|
||||
{
|
||||
return UUID.fastUUID().toString(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
package com.ruoyi.common.utils.uuid;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import com.ruoyi.common.exception.UtilException;
|
||||
|
||||
/**
|
||||
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public final class UUID implements java.io.Serializable, Comparable<UUID>
|
||||
{
|
||||
private static final long serialVersionUID = -1185015143654744140L;
|
||||
|
||||
/**
|
||||
* SecureRandom 的单例
|
||||
*
|
||||
*/
|
||||
private static class Holder
|
||||
{
|
||||
static final SecureRandom numberGenerator = getSecureRandom();
|
||||
}
|
||||
|
||||
/** 此UUID的最高64有效位 */
|
||||
private final long mostSigBits;
|
||||
|
||||
/** 此UUID的最低64有效位 */
|
||||
private final long leastSigBits;
|
||||
|
||||
/**
|
||||
* 私有构造
|
||||
*
|
||||
* @param data 数据
|
||||
*/
|
||||
private UUID(byte[] data)
|
||||
{
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
assert data.length == 16 : "data must be 16 bytes in length";
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
msb = (msb << 8) | (data[i] & 0xff);
|
||||
}
|
||||
for (int i = 8; i < 16; i++)
|
||||
{
|
||||
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||
}
|
||||
this.mostSigBits = msb;
|
||||
this.leastSigBits = lsb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用指定的数据构造新的 UUID。
|
||||
*
|
||||
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
|
||||
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
|
||||
*/
|
||||
public UUID(long mostSigBits, long leastSigBits)
|
||||
{
|
||||
this.mostSigBits = mostSigBits;
|
||||
this.leastSigBits = leastSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
public static UUID fastUUID()
|
||||
{
|
||||
return randomUUID(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
public static UUID randomUUID()
|
||||
{
|
||||
return randomUUID(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||
*
|
||||
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
public static UUID randomUUID(boolean isSecure)
|
||||
{
|
||||
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
|
||||
|
||||
byte[] randomBytes = new byte[16];
|
||||
ng.nextBytes(randomBytes);
|
||||
randomBytes[6] &= 0x0f; /* clear version */
|
||||
randomBytes[6] |= 0x40; /* set to version 4 */
|
||||
randomBytes[8] &= 0x3f; /* clear variant */
|
||||
randomBytes[8] |= 0x80; /* set to IETF variant */
|
||||
return new UUID(randomBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
|
||||
*
|
||||
* @param name 用于构造 UUID 的字节数组。
|
||||
*
|
||||
* @return 根据指定数组生成的 {@code UUID}
|
||||
*/
|
||||
public static UUID nameUUIDFromBytes(byte[] name)
|
||||
{
|
||||
MessageDigest md;
|
||||
try
|
||||
{
|
||||
md = MessageDigest.getInstance("MD5");
|
||||
}
|
||||
catch (NoSuchAlgorithmException nsae)
|
||||
{
|
||||
throw new InternalError("MD5 not supported");
|
||||
}
|
||||
byte[] md5Bytes = md.digest(name);
|
||||
md5Bytes[6] &= 0x0f; /* clear version */
|
||||
md5Bytes[6] |= 0x30; /* set to version 3 */
|
||||
md5Bytes[8] &= 0x3f; /* clear variant */
|
||||
md5Bytes[8] |= 0x80; /* set to IETF variant */
|
||||
return new UUID(md5Bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
|
||||
*
|
||||
* @param name 指定 {@code UUID} 字符串
|
||||
* @return 具有指定值的 {@code UUID}
|
||||
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
|
||||
*
|
||||
*/
|
||||
public static UUID fromString(String name)
|
||||
{
|
||||
String[] components = name.split("-");
|
||||
if (components.length != 5)
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid UUID string: " + name);
|
||||
}
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
components[i] = "0x" + components[i];
|
||||
}
|
||||
|
||||
long mostSigBits = Long.decode(components[0]).longValue();
|
||||
mostSigBits <<= 16;
|
||||
mostSigBits |= Long.decode(components[1]).longValue();
|
||||
mostSigBits <<= 16;
|
||||
mostSigBits |= Long.decode(components[2]).longValue();
|
||||
|
||||
long leastSigBits = Long.decode(components[3]).longValue();
|
||||
leastSigBits <<= 48;
|
||||
leastSigBits |= Long.decode(components[4]).longValue();
|
||||
|
||||
return new UUID(mostSigBits, leastSigBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的 128 位值中的最低有效 64 位。
|
||||
*
|
||||
* @return 此 UUID 的 128 位值中的最低有效 64 位。
|
||||
*/
|
||||
public long getLeastSignificantBits()
|
||||
{
|
||||
return leastSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的 128 位值中的最高有效 64 位。
|
||||
*
|
||||
* @return 此 UUID 的 128 位值中最高有效 64 位。
|
||||
*/
|
||||
public long getMostSignificantBits()
|
||||
{
|
||||
return mostSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
|
||||
* <p>
|
||||
* 版本号具有以下含意:
|
||||
* <ul>
|
||||
* <li>1 基于时间的 UUID
|
||||
* <li>2 DCE 安全 UUID
|
||||
* <li>3 基于名称的 UUID
|
||||
* <li>4 随机生成的 UUID
|
||||
* </ul>
|
||||
*
|
||||
* @return 此 {@code UUID} 的版本号
|
||||
*/
|
||||
public int version()
|
||||
{
|
||||
// Version is bits masked by 0x000000000000F000 in MS long
|
||||
return (int) ((mostSigBits >> 12) & 0x0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
|
||||
* <p>
|
||||
* 变体号具有以下含意:
|
||||
* <ul>
|
||||
* <li>0 为 NCS 向后兼容保留
|
||||
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
|
||||
* <li>6 保留,微软向后兼容
|
||||
* <li>7 保留供以后定义使用
|
||||
* </ul>
|
||||
*
|
||||
* @return 此 {@code UUID} 相关联的变体号
|
||||
*/
|
||||
public int variant()
|
||||
{
|
||||
// This field is composed of a varying number of bits.
|
||||
// 0 - - Reserved for NCS backward compatibility
|
||||
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
|
||||
// 1 1 0 Reserved, Microsoft backward compatibility
|
||||
// 1 1 1 Reserved for future definition.
|
||||
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关联的时间戳值。
|
||||
*
|
||||
* <p>
|
||||
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
|
||||
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
|
||||
*
|
||||
* <p>
|
||||
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
|
||||
*/
|
||||
public long timestamp() throws UnsupportedOperationException
|
||||
{
|
||||
checkTimeBase();
|
||||
return (mostSigBits & 0x0FFFL) << 48//
|
||||
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
|
||||
| mostSigBits >>> 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关联的时钟序列值。
|
||||
*
|
||||
* <p>
|
||||
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
|
||||
* <p>
|
||||
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
|
||||
* UnsupportedOperationException。
|
||||
*
|
||||
* @return 此 {@code UUID} 的时钟序列
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||
*/
|
||||
public int clockSequence() throws UnsupportedOperationException
|
||||
{
|
||||
checkTimeBase();
|
||||
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关的节点值。
|
||||
*
|
||||
* <p>
|
||||
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
|
||||
* <p>
|
||||
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||
*
|
||||
* @return 此 {@code UUID} 的节点值
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||
*/
|
||||
public long node() throws UnsupportedOperationException
|
||||
{
|
||||
checkTimeBase();
|
||||
return leastSigBits & 0x0000FFFFFFFFFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此{@code UUID} 的字符串表现形式。
|
||||
*
|
||||
* <p>
|
||||
* UUID 的字符串表示形式由此 BNF 描述:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||
* time_low = 4*<hexOctet>
|
||||
* time_mid = 2*<hexOctet>
|
||||
* time_high_and_version = 2*<hexOctet>
|
||||
* variant_and_sequence = 2*<hexOctet>
|
||||
* node = 6*<hexOctet>
|
||||
* hexOctet = <hexDigit><hexDigit>
|
||||
* hexDigit = [0-9a-fA-F]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @return 此{@code UUID} 的字符串表现形式
|
||||
* @see #toString(boolean)
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return toString(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此{@code UUID} 的字符串表现形式。
|
||||
*
|
||||
* <p>
|
||||
* UUID 的字符串表示形式由此 BNF 描述:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||
* time_low = 4*<hexOctet>
|
||||
* time_mid = 2*<hexOctet>
|
||||
* time_high_and_version = 2*<hexOctet>
|
||||
* variant_and_sequence = 2*<hexOctet>
|
||||
* node = 6*<hexOctet>
|
||||
* hexOctet = <hexDigit><hexDigit>
|
||||
* hexDigit = [0-9a-fA-F]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
|
||||
* @return 此{@code UUID} 的字符串表现形式
|
||||
*/
|
||||
public String toString(boolean isSimple)
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
|
||||
// time_low
|
||||
builder.append(digits(mostSigBits >> 32, 8));
|
||||
if (false == isSimple)
|
||||
{
|
||||
builder.append('-');
|
||||
}
|
||||
// time_mid
|
||||
builder.append(digits(mostSigBits >> 16, 4));
|
||||
if (false == isSimple)
|
||||
{
|
||||
builder.append('-');
|
||||
}
|
||||
// time_high_and_version
|
||||
builder.append(digits(mostSigBits, 4));
|
||||
if (false == isSimple)
|
||||
{
|
||||
builder.append('-');
|
||||
}
|
||||
// variant_and_sequence
|
||||
builder.append(digits(leastSigBits >> 48, 4));
|
||||
if (false == isSimple)
|
||||
{
|
||||
builder.append('-');
|
||||
}
|
||||
// node
|
||||
builder.append(digits(leastSigBits, 12));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的哈希码。
|
||||
*
|
||||
* @return UUID 的哈希码值。
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
long hilo = mostSigBits ^ leastSigBits;
|
||||
return ((int) (hilo >> 32)) ^ (int) hilo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此对象与指定对象比较。
|
||||
* <p>
|
||||
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
|
||||
*
|
||||
* @param obj 要与之比较的对象
|
||||
*
|
||||
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if ((null == obj) || (obj.getClass() != UUID.class))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UUID id = (UUID) obj;
|
||||
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
|
||||
}
|
||||
|
||||
// Comparison Operations
|
||||
|
||||
/**
|
||||
* 将此 UUID 与指定的 UUID 比较。
|
||||
*
|
||||
* <p>
|
||||
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
|
||||
*
|
||||
* @param val 与此 UUID 比较的 UUID
|
||||
*
|
||||
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(UUID val)
|
||||
{
|
||||
// The ordering is intentionally set up so that the UUIDs
|
||||
// can simply be numerically compared as two numbers
|
||||
return (this.mostSigBits < val.mostSigBits ? -1 : //
|
||||
(this.mostSigBits > val.mostSigBits ? 1 : //
|
||||
(this.leastSigBits < val.leastSigBits ? -1 : //
|
||||
(this.leastSigBits > val.leastSigBits ? 1 : //
|
||||
0))));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
// Private method start
|
||||
/**
|
||||
* 返回指定数字对应的hex值
|
||||
*
|
||||
* @param val 值
|
||||
* @param digits 位
|
||||
* @return 值
|
||||
*/
|
||||
private static String digits(long val, int digits)
|
||||
{
|
||||
long hi = 1L << (digits * 4);
|
||||
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为time-based版本UUID
|
||||
*/
|
||||
private void checkTimeBase()
|
||||
{
|
||||
if (version() != 1)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not a time-based UUID");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
|
||||
*
|
||||
* @return {@link SecureRandom}
|
||||
*/
|
||||
public static SecureRandom getSecureRandom()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SecureRandom.getInstance("SHA1PRNG");
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机数生成器对象<br>
|
||||
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
|
||||
*
|
||||
* @return {@link ThreadLocalRandom}
|
||||
*/
|
||||
public static ThreadLocalRandom getRandom()
|
||||
{
|
||||
return ThreadLocalRandom.current();
|
||||
}
|
||||
}
|
||||
+59
-65
@@ -5,94 +5,88 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
|
||||
<description>
|
||||
framework框架核心
|
||||
</description>
|
||||
|
||||
|
||||
<description>
|
||||
framework框架核心
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot 拦截器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用Spring框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
</dependency>
|
||||
<!-- 验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.penggle</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Shiro使用EhCache缓存框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-ehcache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||
<dependency>
|
||||
<groupId>com.github.theborakompanioni</groupId>
|
||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||
</dependency>
|
||||
<!-- Shiro使用Spring框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
</dependency>
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||
<dependency>
|
||||
<groupId>com.github.theborakompanioni</groupId>
|
||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -12,6 +12,8 @@ import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.enums.BusinessStatus;
|
||||
import com.ruoyi.common.json.JSON;
|
||||
@@ -34,6 +36,9 @@ public class LogAspect
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
/** 排除敏感属性字段 */
|
||||
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
|
||||
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.common.annotation.Log)")
|
||||
public void logPointCut()
|
||||
@@ -84,7 +89,7 @@ public class LogAspect
|
||||
String ip = ShiroUtils.getIp();
|
||||
operLog.setOperIp(ip);
|
||||
// 返回参数
|
||||
operLog.setJsonResult(JSON.marshal(jsonResult));
|
||||
operLog.setJsonResult(StringUtils.substring(JSON.marshal(jsonResult), 0, 2000));
|
||||
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||
if (currentUser != null)
|
||||
@@ -154,8 +159,13 @@ public class LogAspect
|
||||
private void setRequestValue(SysOperLog operLog) throws Exception
|
||||
{
|
||||
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
|
||||
String params = JSON.marshal(map);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||
if (StringUtils.isNotEmpty(map))
|
||||
{
|
||||
PropertyPreFilters.MySimplePropertyPreFilter excludefilter = new PropertyPreFilters().addFilter();
|
||||
excludefilter.addExcludes(EXCLUDE_PROPERTIES);
|
||||
String params = JSONObject.toJSONString(map, excludefilter);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,51 +45,81 @@ public class ShiroConfig
|
||||
{
|
||||
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
|
||||
|
||||
// Session超时时间,单位为毫秒(默认30分钟)
|
||||
/**
|
||||
* Session超时时间,单位为毫秒(默认30分钟)
|
||||
*/
|
||||
@Value("${shiro.session.expireTime}")
|
||||
private int expireTime;
|
||||
|
||||
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
/**
|
||||
* 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
*/
|
||||
@Value("${shiro.session.validationInterval}")
|
||||
private int validationInterval;
|
||||
|
||||
// 同一个用户最大会话数
|
||||
/**
|
||||
* 同一个用户最大会话数
|
||||
*/
|
||||
@Value("${shiro.session.maxSession}")
|
||||
private int maxSession;
|
||||
|
||||
// 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
||||
/**
|
||||
* 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
||||
*/
|
||||
@Value("${shiro.session.kickoutAfter}")
|
||||
private boolean kickoutAfter;
|
||||
|
||||
// 验证码开关
|
||||
/**
|
||||
* 验证码开关
|
||||
*/
|
||||
@Value("${shiro.user.captchaEnabled}")
|
||||
private boolean captchaEnabled;
|
||||
|
||||
// 验证码类型
|
||||
/**
|
||||
* 验证码类型
|
||||
*/
|
||||
@Value("${shiro.user.captchaType}")
|
||||
private String captchaType;
|
||||
|
||||
// 设置Cookie的域名
|
||||
/**
|
||||
* 设置Cookie的域名
|
||||
*/
|
||||
@Value("${shiro.cookie.domain}")
|
||||
private String domain;
|
||||
|
||||
// 设置cookie的有效访问路径
|
||||
/**
|
||||
* 设置cookie的有效访问路径
|
||||
*/
|
||||
@Value("${shiro.cookie.path}")
|
||||
private String path;
|
||||
|
||||
// 设置HttpOnly属性
|
||||
/**
|
||||
* 设置HttpOnly属性
|
||||
*/
|
||||
@Value("${shiro.cookie.httpOnly}")
|
||||
private boolean httpOnly;
|
||||
|
||||
// 设置Cookie的过期时间,秒为单位
|
||||
/**
|
||||
* 设置Cookie的过期时间,秒为单位
|
||||
*/
|
||||
@Value("${shiro.cookie.maxAge}")
|
||||
private int maxAge;
|
||||
|
||||
// 登录地址
|
||||
/**
|
||||
* 设置cipherKey密钥
|
||||
*/
|
||||
@Value("${shiro.cookie.cipherKey}")
|
||||
private String cipherKey;
|
||||
|
||||
/**
|
||||
* 登录地址
|
||||
*/
|
||||
@Value("${shiro.user.loginUrl}")
|
||||
private String loginUrl;
|
||||
|
||||
// 权限认证失败地址
|
||||
/**
|
||||
* 权限认证失败地址
|
||||
*/
|
||||
@Value("${shiro.user.unauthorizedUrl}")
|
||||
private String unauthorizedUrl;
|
||||
|
||||
@@ -219,7 +249,6 @@ public class ShiroConfig
|
||||
public LogoutFilter logoutFilter()
|
||||
{
|
||||
LogoutFilter logoutFilter = new LogoutFilter();
|
||||
logoutFilter.setCacheManager(getEhCacheManager());
|
||||
logoutFilter.setLoginUrl(loginUrl);
|
||||
return logoutFilter;
|
||||
}
|
||||
@@ -328,7 +357,7 @@ public class ShiroConfig
|
||||
{
|
||||
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
|
||||
cookieRememberMeManager.setCookie(rememberMeCookie());
|
||||
cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
|
||||
cookieRememberMeManager.setCipherKey(Base64.decode(cipherKey));
|
||||
return cookieRememberMeManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ public class SysLoginService
|
||||
// 查询用户信息
|
||||
SysUser user = userService.selectUserByLoginName(username);
|
||||
|
||||
/**
|
||||
if (user == null && maybeMobilePhoneNumber(username))
|
||||
{
|
||||
user = userService.selectUserByPhoneNumber(username);
|
||||
@@ -80,6 +81,7 @@ public class SysLoginService
|
||||
{
|
||||
user = userService.selectUserByEmail(username);
|
||||
}
|
||||
*/
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
@@ -106,6 +108,7 @@ public class SysLoginService
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
private boolean maybeEmail(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.EMAIL_PATTERN))
|
||||
@@ -123,6 +126,7 @@ public class SysLoginService
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
|
||||
+2
-2
@@ -83,8 +83,8 @@ public class SysPasswordService
|
||||
return new Md5Hash(username + password + salt).toHex();
|
||||
}
|
||||
|
||||
public void unlock(String loginName){
|
||||
public void unlock(String loginName)
|
||||
{
|
||||
loginRecordCache.remove(loginName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-15
@@ -1,23 +1,20 @@
|
||||
package com.ruoyi.framework.shiro.web.filter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Deque;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.session.SessionException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||
|
||||
/**
|
||||
* 退出过滤器
|
||||
@@ -33,8 +30,6 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
*/
|
||||
private String loginUrl;
|
||||
|
||||
private Cache<String, Deque<Serializable>> cache;
|
||||
|
||||
public String getLoginUrl()
|
||||
{
|
||||
return loginUrl;
|
||||
@@ -61,7 +56,7 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
// 记录用户退出日志
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
|
||||
// 清理缓存
|
||||
cache.remove(loginName);
|
||||
SpringUtils.getBean(ISysUserOnlineService.class).removeUserCache(loginName, ShiroUtils.getSessionId());
|
||||
}
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
@@ -92,11 +87,4 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
}
|
||||
return super.getRedirectUrl(request, response, subject);
|
||||
}
|
||||
|
||||
// 设置Cache的key的前缀
|
||||
public void setCacheManager(CacheManager cacheManager)
|
||||
{
|
||||
// 必须和ehcache缓存配置中的缓存name一致
|
||||
this.cache = cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -61,6 +61,8 @@ public class CaptchaValidateFilter extends AccessControlFilter
|
||||
{
|
||||
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
|
||||
String code = String.valueOf(obj != null ? obj : "");
|
||||
// 验证码清除,防止多次使用。
|
||||
request.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
|
||||
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
|
||||
{
|
||||
return false;
|
||||
|
||||
+1
@@ -130,6 +130,7 @@ public class OnlineWebSessionManager extends DefaultWebSessionManager
|
||||
}
|
||||
invalidCount++;
|
||||
needOfflineIdList.add(userOnline.getSessionId());
|
||||
userOnlineService.removeUserCache(userOnline.getLoginName(), userOnline.getSessionId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,24 +5,24 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
|
||||
<description>
|
||||
generator代码生成
|
||||
</description>
|
||||
|
||||
|
||||
<description>
|
||||
generator代码生成
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!--velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
@@ -30,5 +30,5 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -188,15 +188,41 @@ public class GenController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*/
|
||||
@RequiresPermissions("tool:gen:code")
|
||||
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
|
||||
@GetMapping("/download/{tableName}")
|
||||
public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
|
||||
{
|
||||
byte[] data = genTableService.downloadCode(tableName);
|
||||
genCode(response, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码(自定义路径)
|
||||
*/
|
||||
@RequiresPermissions("tool:gen:code")
|
||||
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
|
||||
@GetMapping("/genCode/{tableName}")
|
||||
public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
|
||||
@ResponseBody
|
||||
public AjaxResult genCode(@PathVariable("tableName") String tableName)
|
||||
{
|
||||
byte[] data = genTableService.generatorCode(tableName);
|
||||
genCode(response, data);
|
||||
genTableService.generatorCode(tableName);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*/
|
||||
@RequiresPermissions("tool:gen:edit")
|
||||
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
|
||||
@GetMapping("/synchDb/{tableName}")
|
||||
@ResponseBody
|
||||
public AjaxResult synchDb(@PathVariable("tableName") String tableName)
|
||||
{
|
||||
genTableService.synchDb(tableName);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,7 +235,7 @@ public class GenController extends BaseController
|
||||
public void batchGenCode(HttpServletResponse response, String tables) throws IOException
|
||||
{
|
||||
String[] tableNames = Convert.toStrArray(tables);
|
||||
byte[] data = genTableService.generatorCode(tableNames);
|
||||
byte[] data = genTableService.downloadCode(tableNames);
|
||||
genCode(response, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,12 @@ public class GenTable extends BaseEntity
|
||||
@NotBlank(message = "作者不能为空")
|
||||
private String functionAuthor;
|
||||
|
||||
/** 生成代码方式(0zip压缩包 1自定义路径) */
|
||||
private String genType;
|
||||
|
||||
/** 生成路径(不填默认项目路径) */
|
||||
private String genPath;
|
||||
|
||||
/** 主键信息 */
|
||||
private GenTableColumn pkColumn;
|
||||
|
||||
@@ -83,6 +89,12 @@ public class GenTable extends BaseEntity
|
||||
/** 树名称字段 */
|
||||
private String treeName;
|
||||
|
||||
/** 上级菜单ID字段 */
|
||||
private String parentMenuId;
|
||||
|
||||
/** 上级菜单名称字段 */
|
||||
private String parentMenuName;
|
||||
|
||||
public Long getTableId()
|
||||
{
|
||||
return tableId;
|
||||
@@ -203,6 +215,26 @@ public class GenTable extends BaseEntity
|
||||
this.functionAuthor = functionAuthor;
|
||||
}
|
||||
|
||||
public String getGenType()
|
||||
{
|
||||
return genType;
|
||||
}
|
||||
|
||||
public void setGenType(String genType)
|
||||
{
|
||||
this.genType = genType;
|
||||
}
|
||||
|
||||
public String getGenPath()
|
||||
{
|
||||
return genPath;
|
||||
}
|
||||
|
||||
public void setGenPath(String genPath)
|
||||
{
|
||||
this.genPath = genPath;
|
||||
}
|
||||
|
||||
public GenTableColumn getPkColumn()
|
||||
{
|
||||
return pkColumn;
|
||||
@@ -273,6 +305,26 @@ public class GenTable extends BaseEntity
|
||||
this.treeName = treeName;
|
||||
}
|
||||
|
||||
public String getParentMenuId()
|
||||
{
|
||||
return parentMenuId;
|
||||
}
|
||||
|
||||
public void setParentMenuId(String parentMenuId)
|
||||
{
|
||||
this.parentMenuId = parentMenuId;
|
||||
}
|
||||
|
||||
public String getParentMenuName()
|
||||
{
|
||||
return parentMenuName;
|
||||
}
|
||||
|
||||
public void setParentMenuName(String parentMenuName)
|
||||
{
|
||||
this.parentMenuName = parentMenuName;
|
||||
}
|
||||
|
||||
public boolean isSub()
|
||||
{
|
||||
return isSub(this.tplCategory);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class GenTableColumn extends BaseEntity
|
||||
/** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
|
||||
private String queryType;
|
||||
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件) */
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、upload上传控件、summernote富文本控件) */
|
||||
private String htmlType;
|
||||
|
||||
/** 字典类型 */
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface GenTableColumnMapper
|
||||
* @return 列信息
|
||||
*/
|
||||
public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
|
||||
|
||||
|
||||
/**
|
||||
* 查询业务字段列表
|
||||
*
|
||||
@@ -42,6 +42,14 @@ public interface GenTableColumnMapper
|
||||
*/
|
||||
public int updateGenTableColumn(GenTableColumn genTableColumn);
|
||||
|
||||
/**
|
||||
* 删除业务字段
|
||||
*
|
||||
* @param genTableColumns 列数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
|
||||
|
||||
/**
|
||||
* 批量删除业务字段
|
||||
*
|
||||
@@ -49,4 +57,4 @@ public interface GenTableColumnMapper
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGenTableColumnByIds(Long[] ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,20 +83,34 @@ public interface IGenTableService
|
||||
public Map<String, String> previewCode(Long tableId);
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
public byte[] generatorCode(String tableName);
|
||||
public byte[] downloadCode(String tableName);
|
||||
|
||||
/**
|
||||
* 批量生成代码
|
||||
* 生成代码(自定义路径)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
public void generatorCode(String tableName);
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
public void synchDb(String tableName);
|
||||
|
||||
/**
|
||||
* 批量生成代码(下载方式)
|
||||
*
|
||||
* @param tableNames 表数组
|
||||
* @return 数据
|
||||
*/
|
||||
public byte[] generatorCode(String[] tableNames);
|
||||
public byte[] downloadCode(String[] tableNames);
|
||||
|
||||
/**
|
||||
* 修改保存参数校验
|
||||
|
||||
+113
-10
@@ -1,11 +1,13 @@
|
||||
package com.ruoyi.generator.service.impl;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -21,9 +23,11 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.GenConstants;
|
||||
import com.ruoyi.common.core.text.CharsetKit;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.exception.BusinessException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileUtils;
|
||||
import com.ruoyi.generator.domain.GenTable;
|
||||
import com.ruoyi.generator.domain.GenTableColumn;
|
||||
import com.ruoyi.generator.mapper.GenTableColumnMapper;
|
||||
@@ -156,9 +160,9 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
@Transactional
|
||||
public void importGenTable(List<GenTable> tableList, String operName)
|
||||
{
|
||||
for (GenTable table : tableList)
|
||||
try
|
||||
{
|
||||
try
|
||||
for (GenTable table : tableList)
|
||||
{
|
||||
String tableName = table.getTableName();
|
||||
GenUtils.initTable(table, operName);
|
||||
@@ -174,10 +178,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("表名 " + table.getTableName() + " 导入失败:", e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new BusinessException("导入失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,13 +219,13 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String tableName)
|
||||
public byte[] downloadCode(String tableName)
|
||||
{
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
@@ -229,6 +233,84 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
IOUtils.closeQuietly(zip);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码(自定义路径)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
@Override
|
||||
public void generatorCode(String tableName)
|
||||
{
|
||||
// 查询表信息
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
// 设置主子表信息
|
||||
setSubTable(table);
|
||||
// 设置主键列信息
|
||||
setPkColumn(table);
|
||||
|
||||
VelocityInitializer.initVelocity();
|
||||
|
||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||
|
||||
// 获取模板列表
|
||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
||||
for (String template : templates)
|
||||
{
|
||||
if (!StringUtils.contains(template, "sql.vm"))
|
||||
{
|
||||
// 渲染模板
|
||||
StringWriter sw = new StringWriter();
|
||||
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
|
||||
tpl.merge(context, sw);
|
||||
try
|
||||
{
|
||||
String path = getGenPath(table, template);
|
||||
FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new BusinessException("渲染模板失败,表名:" + table.getTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步数据库
|
||||
*
|
||||
* @param tableName 表名称
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void synchDb(String tableName)
|
||||
{
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
List<GenTableColumn> tableColumns = table.getColumns();
|
||||
List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
|
||||
|
||||
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
|
||||
if (StringUtils.isEmpty(dbTableColumns))
|
||||
{
|
||||
throw new BusinessException("同步数据失败,原表结构不存在");
|
||||
}
|
||||
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
|
||||
|
||||
dbTableColumns.forEach(column -> {
|
||||
if (!tableColumnNames.contains(column.getColumnName()))
|
||||
{
|
||||
GenUtils.initColumnField(column, table);
|
||||
genTableColumnMapper.insertGenTableColumn(column);
|
||||
}
|
||||
});
|
||||
|
||||
List<GenTableColumn> delColumns = tableColumns.stream()
|
||||
.filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
|
||||
if (StringUtils.isNotEmpty(delColumns))
|
||||
{
|
||||
genTableColumnMapper.deleteGenTableColumns(delColumns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成代码
|
||||
@@ -237,7 +319,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String[] tableNames)
|
||||
public byte[] downloadCode(String[] tableNames)
|
||||
{
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
@@ -334,7 +416,6 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
*/
|
||||
public void setPkColumn(GenTable table)
|
||||
{
|
||||
|
||||
for (GenTableColumn column : table.getColumns())
|
||||
{
|
||||
if (column.isPk())
|
||||
@@ -391,9 +472,31 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
|
||||
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
|
||||
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
|
||||
String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
|
||||
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
|
||||
|
||||
genTable.setTreeCode(treeCode);
|
||||
genTable.setTreeParentCode(treeParentCode);
|
||||
genTable.setTreeName(treeName);
|
||||
genTable.setParentMenuId(parentMenuId);
|
||||
genTable.setParentMenuName(parentMenuName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代码生成地址
|
||||
*
|
||||
* @param table 业务表信息
|
||||
* @param template 模板文件路径
|
||||
* @return 生成地址
|
||||
*/
|
||||
public static String getGenPath(GenTable table, String template)
|
||||
{
|
||||
String genPath = table.getGenPath();
|
||||
if (StringUtils.equals(genPath, "/"))
|
||||
{
|
||||
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
|
||||
}
|
||||
return genPath + File.separator + VelocityUtils.getFileName(template, table);
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,16 @@ public class GenUtils
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_SELECT);
|
||||
}
|
||||
// 文件字段设置上传控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_UPLOAD);
|
||||
}
|
||||
// 内容字段设置富文本控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_SUMMERNOTE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +205,7 @@ public class GenUtils
|
||||
/**
|
||||
* 关键字替换
|
||||
*
|
||||
* @param name 需要被替换的名字
|
||||
* @param text 需要被替换的名字
|
||||
* @return 替换后的名字
|
||||
*/
|
||||
public static String replaceText(String text)
|
||||
|
||||
@@ -22,6 +22,9 @@ public class VelocityUtils
|
||||
|
||||
/** html空间路径 */
|
||||
private static final String TEMPLATES_PATH = "main/resources/templates";
|
||||
|
||||
/** 默认上级菜单,系统工具 */
|
||||
private static final String DEFAULT_PARENT_MENU_ID = "3";
|
||||
|
||||
/**
|
||||
* 设置模板变量信息
|
||||
@@ -53,6 +56,7 @@ public class VelocityUtils
|
||||
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
|
||||
velocityContext.put("columns", genTable.getColumns());
|
||||
velocityContext.put("table", genTable);
|
||||
setMenuVelocityContext(velocityContext, genTable);
|
||||
if (GenConstants.TPL_TREE.equals(tplCategory))
|
||||
{
|
||||
setTreeVelocityContext(velocityContext, genTable);
|
||||
@@ -64,6 +68,14 @@ public class VelocityUtils
|
||||
return velocityContext;
|
||||
}
|
||||
|
||||
public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
|
||||
{
|
||||
String options = genTable.getOptions();
|
||||
JSONObject paramsObj = JSONObject.parseObject(options);
|
||||
String parentMenuId = getParentMenuId(paramsObj);
|
||||
context.put("parentMenuId", parentMenuId);
|
||||
}
|
||||
|
||||
public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
|
||||
{
|
||||
String options = genTable.getOptions();
|
||||
@@ -280,7 +292,21 @@ public class VelocityUtils
|
||||
public static String getPermissionPrefix(String moduleName, String businessName)
|
||||
{
|
||||
return StringUtils.format("{}:{}", moduleName, businessName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上级菜单ID字段
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
* @return 上级菜单ID字段
|
||||
*/
|
||||
public static String getParentMenuId(JSONObject paramsObj)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
|
||||
{
|
||||
return paramsObj.getString(GenConstants.PARENT_MENU_ID);
|
||||
}
|
||||
return DEFAULT_PARENT_MENU_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +321,7 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +336,7 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +351,7 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,5 +116,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{tableId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
|
||||
<delete id="deleteGenTableColumns">
|
||||
delete from gen_table_column where column_id in
|
||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||
#{item.columnId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
@@ -17,6 +17,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="businessName" column="business_name" />
|
||||
<result property="functionName" column="function_name" />
|
||||
<result property="functionAuthor" column="function_author" />
|
||||
<result property="genType" column="gen_type" />
|
||||
<result property="genPath" column="gen_path" />
|
||||
<result property="options" column="options" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
@@ -52,7 +54,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGenTableVo">
|
||||
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, options, create_by, create_time, update_by, update_time, remark from gen_table
|
||||
select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
|
||||
</sql>
|
||||
|
||||
<select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
|
||||
@@ -96,7 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
@@ -104,7 +106,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
@@ -112,7 +114,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
|
||||
SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
|
||||
c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
|
||||
FROM gen_table t
|
||||
LEFT JOIN gen_table_column c ON t.table_id = c.table_id
|
||||
@@ -130,6 +132,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessName != null and businessName != ''">business_name,</if>
|
||||
<if test="functionName != null and functionName != ''">function_name,</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
|
||||
<if test="genType != null and genType != ''">gen_type,</if>
|
||||
<if test="genPath != null and genPath != ''">gen_path,</if>
|
||||
<if test="remark != null and remark != ''">remark,</if>
|
||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||
create_time
|
||||
@@ -143,6 +147,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="businessName != null and businessName != ''">#{businessName},</if>
|
||||
<if test="functionName != null and functionName != ''">#{functionName},</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
|
||||
<if test="genType != null and genType != ''">#{genType},</if>
|
||||
<if test="genPath != null and genPath != ''">#{genPath},</if>
|
||||
<if test="remark != null and remark != ''">#{remark},</if>
|
||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||
sysdate()
|
||||
@@ -158,6 +164,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="subTableFkName != null and subTableFkName != ''">sub_table_fk_name = #{subTableFkName},</if>
|
||||
<if test="className != null and className != ''">class_name = #{className},</if>
|
||||
<if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
|
||||
<if test="genType != null and genType != ''">gen_type = #{genType},</if>
|
||||
<if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
|
||||
<if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
|
||||
<if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
|
||||
<if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
|
||||
|
||||
@@ -133,6 +133,47 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label is-required" title="分配到指定菜单下,例如 系统管理">上级菜单:<i class="fa fa-question-circle-o"></i></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="parentMenuId" name="params[parentMenuId]" type="hidden" th:value="*{parentMenuId}"/>
|
||||
<div class="input-group">
|
||||
<input id="parentMenuName" name="params[parentMenuName]" class="form-control" type="text" onclick="selectMenuTree()" placeholder="请选择上级菜单" maxlength="50" th:value="*{parentMenuName}" required>
|
||||
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" title="默认为zip压缩包下载,也可以自定义生成路径">生成代码方式:<i class="fa fa-question-circle-o"></i></label>
|
||||
<div class="col-sm-8">
|
||||
<label class="radio-box"> <input type="radio" name="genType" value="0" th:field="*{genType}" /> zip压缩包 </label>
|
||||
<label class="radio-box"> <input type="radio" name="genType" value="1" th:field="*{genType}" /> 自定义路径</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden row" id="pathinfo">
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-2 control-label" title="填写磁盘绝对路径,若不填写,则生成到当前Web项目下">生成基础路径:<i class="fa fa-question-circle-o"></i></label>
|
||||
<div class="col-xs-10">
|
||||
<div class="input-group input-group-sm">
|
||||
<input id="genPath" name="genPath" class="form-control" type="text" th:field="*{genPath}" placeholder="请输入项目路径" maxlength="200">
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">最近路径快速选择 <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li><a href="javascript:$('#genPath').val('/')"><i class="fa fa-refresh"></i>恢复默认的生成基础路径</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden" id="subInfo">
|
||||
<h4 class="form-header h4">关联信息</h4>
|
||||
@@ -426,6 +467,8 @@
|
||||
$(function() {
|
||||
var tplCategory = $("#tplCategory option:selected").val();
|
||||
tplCategoryVisible(tplCategory);
|
||||
var genType = $('input[name="genType"]:checked').val();
|
||||
pathInfoVisible(genType);
|
||||
});
|
||||
|
||||
$('#tplCategory').on('select2:select', function (event) {
|
||||
@@ -455,6 +498,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
$('input').on('ifChecked', function(event){
|
||||
var genType = $(event.target).val();
|
||||
pathInfoVisible(genType);
|
||||
});
|
||||
|
||||
function pathInfoVisible(genType) {
|
||||
if("0" == genType){
|
||||
$("#genPath").val("/");
|
||||
$("#pathinfo").addClass("hidden");
|
||||
} else if("1" == genType){
|
||||
$("#pathinfo").removeClass("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
// 选择字典处理函数
|
||||
function selectDictTree(columnId, obj) {
|
||||
var dictType = $.common.nullToStr($(obj).parent().find("input").val());
|
||||
@@ -463,18 +520,39 @@
|
||||
title: '选择字典类型',
|
||||
width: "380",
|
||||
url: url,
|
||||
callBack: doSubmit
|
||||
callBack: doDictSubmit
|
||||
};
|
||||
$.modal.openOptions(options);
|
||||
}
|
||||
|
||||
function doSubmit(index, layero){
|
||||
// 选择菜单处理函数
|
||||
function selectMenuTree() {
|
||||
var parentMenuId = $("#parentMenuId").val();
|
||||
var menuId = parentMenuId > 0 ? parentMenuId : 1;
|
||||
var url = ctx + "system/menu/selectMenuTree/" + menuId;
|
||||
var options = {
|
||||
title: '菜单选择',
|
||||
width: "380",
|
||||
url: url,
|
||||
callBack: doMenuSubmit
|
||||
};
|
||||
$.modal.openOptions(options);
|
||||
}
|
||||
|
||||
function doDictSubmit(index, layero){
|
||||
var body = layer.getChildFrame('body', index);
|
||||
var columnId = body.find('#columnId').val();
|
||||
var dictType = body.find('#dictType').val();
|
||||
layer.close(index);
|
||||
$("#columns_dict_" + columnId).val(dictType);
|
||||
}
|
||||
|
||||
function doMenuSubmit(index, layero){
|
||||
var body = layer.getChildFrame('body', index);
|
||||
$("#parentMenuId").val(body.find('#treeId').val());
|
||||
$("#parentMenuName").val(body.find('#treeName').val());
|
||||
layer.close(index);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -519,7 +597,9 @@
|
||||
<option value="select" {{if htmlType==="select"}}selected{{/if}}>下拉框</option>
|
||||
<option value="radio" {{if htmlType==="radio"}}selected{{/if}}>单选框</option>
|
||||
<option value="checkbox" {{if htmlType==="checkbox"}}selected{{/if}}>复选框</option>
|
||||
<option value="summernote" {{if htmlType==="summernote"}}selected{{/if}}>富文本</option>
|
||||
<option value="datetime" {{if htmlType==="datetime"}}selected{{/if}}>日期控件</option>
|
||||
<option value="upload" {{if htmlType==="upload"}}selected{{/if}}>上传控件</option>
|
||||
</select>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: bootstrap-table-export-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "tool/gen";
|
||||
var editFlag = [[${@permission.hasPermi('tool:gen:edit')}]];
|
||||
@@ -124,7 +125,8 @@
|
||||
actions.push('<a class="btn btn-info btn-xs ' + previewFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.tableId + '\')"><i class="fa fa-search"></i>预览</a> ');
|
||||
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.tableId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
|
||||
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.tableId + '\')"><i class="fa fa-remove"></i>删除</a> ');
|
||||
actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
|
||||
actions.push('<a class="btn btn-warning btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="synchDb(\'' + row.tableName + '\')"><i class="fa fa-refresh"></i>同步</a> ');
|
||||
actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\',\'' + row.genType + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
|
||||
return actions.join('');
|
||||
}
|
||||
}]
|
||||
@@ -162,14 +164,25 @@
|
||||
}
|
||||
|
||||
// 生成代码
|
||||
function genCode(tableName) {
|
||||
function genCode(tableName, genType) {
|
||||
$.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
|
||||
location.href = prefix + "/genCode/" + tableName;
|
||||
layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
|
||||
if(genType === "0") {
|
||||
location.href = prefix + "/download/" + tableName;
|
||||
layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
|
||||
} else if(genType === "1") {
|
||||
$.operate.get(prefix + "/genCode/" + tableName);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 同步数据库
|
||||
function synchDb(tableName){
|
||||
$.modal.confirm("确认要强制同步" + tableName + "表结构吗?", function() {
|
||||
$.operate.get(prefix + "/synchDb/" + tableName);
|
||||
})
|
||||
}
|
||||
|
||||
//批量生成代码
|
||||
// 批量生成代码
|
||||
function batchGenCode() {
|
||||
var rows = $.table.selectColumns("tableName");
|
||||
if (rows.length == 0) {
|
||||
|
||||
@@ -59,25 +59,27 @@
|
||||
{
|
||||
field: 'tableName',
|
||||
title: '表名称',
|
||||
width: '20%',
|
||||
sortable: true
|
||||
sortable: true,
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'tableComment',
|
||||
title: '表描述',
|
||||
width: '20%',
|
||||
sortable: true
|
||||
sortable: true,
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.tooltip(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
title: '创建时间',
|
||||
width: '20%',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'updateTime',
|
||||
title: '更新时间',
|
||||
width: '20%',
|
||||
sortable: true
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -8,6 +8,18 @@
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
<th:block th:include="include :: bootstrap-fileinput-css"/>
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
<th:block th:include="include :: summernote-css" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
@@ -46,6 +58,24 @@
|
||||
<input name="${field}" class="form-control" type="text"#if($column.required) required#end>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "upload")
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label#if($column.required) is-required#end">${comment}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" name="${field}">
|
||||
<div class="file-loading">
|
||||
<input class="form-control file-upload" id="${field}" name="file" type="file">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "summernote")
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label#if($column.required) is-required#end">${comment}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" class="form-control" name="${field}">
|
||||
<div class="summernote" id="${field}"></div>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">${comment}:</label>
|
||||
@@ -146,6 +176,18 @@
|
||||
<th:block th:include="include :: datetimepicker-js" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
<th:block th:include="include :: bootstrap-fileinput-js"/>
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
<th:block th:include="include :: summernote-js" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "${moduleName}/${businessName}"
|
||||
@@ -175,6 +217,61 @@
|
||||
});
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
|
||||
$(".file-upload").fileinput({
|
||||
uploadUrl: '/common/upload',
|
||||
maxFileCount: 1,
|
||||
autoReplace: true
|
||||
}).on('fileuploaded', function (event, data, previewId, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val(data.response.url)
|
||||
}).on('fileremoved', function (event, id, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
})
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
|
||||
$(function() {
|
||||
$('.summernote').summernote({
|
||||
lang: 'zh-CN',
|
||||
callbacks: {
|
||||
onChange: function(contents, $edittable) {
|
||||
$("input[name='" + this.id + "']").val(contents);
|
||||
},
|
||||
onImageUpload: function(files) {
|
||||
var obj = this;
|
||||
var data = new FormData();
|
||||
data.append("file", files[0]);
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: ctx + "common/upload",
|
||||
data: data,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
success: function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$('#' + obj.id).summernote('insertImage', result.url);
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
$.modal.alertWarning("图片上传失败。");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#if($table.tree)
|
||||
|
||||
/*${functionName}-新增-选择父部门树*/
|
||||
@@ -204,6 +301,7 @@
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
sidePagination: "client",
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
|
||||
@@ -8,6 +8,18 @@
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
<th:block th:include="include :: bootstrap-fileinput-css"/>
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
<th:block th:include="include :: summernote-css" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
@@ -46,6 +58,24 @@
|
||||
<input name="${field}" th:field="*{${field}}" class="form-control" type="text"#if($column.required) required#end>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "upload")
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label#if($column.required) is-required#end">${comment}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" name="${field}" th:field="*{${field}}">
|
||||
<div class="file-loading">
|
||||
<input class="form-control file-upload" id="${field}" name="file" type="file">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "summernote")
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label#if($column.required) is-required#end">${comment}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="hidden" class="form-control" th:field="*{${field}}">
|
||||
<div class="summernote" id="${field}"></div>
|
||||
</div>
|
||||
</div>
|
||||
#elseif($column.htmlType == "select" && "" != $dictType)
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">${comment}:</label>
|
||||
@@ -146,6 +176,18 @@
|
||||
<th:block th:include="include :: datetimepicker-js" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
<th:block th:include="include :: bootstrap-fileinput-js"/>
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
<th:block th:include="include :: summernote-js" />
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "${moduleName}/${businessName}";
|
||||
@@ -175,6 +217,71 @@
|
||||
});
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "upload")
|
||||
|
||||
$(".file-upload").each(function (i) {
|
||||
var val = $("input[name='" + this.id + "']").val()
|
||||
$(this).fileinput({
|
||||
'uploadUrl': '/common/upload',
|
||||
initialPreviewAsData: true,
|
||||
initialPreview: [val],
|
||||
maxFileCount: 1,
|
||||
autoReplace: true
|
||||
}).on('fileuploaded', function (event, data, previewId, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val(data.response.url)
|
||||
}).on('fileremoved', function (event, id, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
})
|
||||
$(this).fileinput('_initFileActions');
|
||||
});
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "summernote")
|
||||
|
||||
$(function() {
|
||||
$('.summernote').each(function(i) {
|
||||
$('#' + this.id).summernote({
|
||||
lang: 'zh-CN',
|
||||
callbacks: {
|
||||
onChange: function(contents, $edittable) {
|
||||
$("input[name='" + this.id + "']").val(contents);
|
||||
},
|
||||
onImageUpload: function(files) {
|
||||
var obj = this;
|
||||
var data = new FormData();
|
||||
data.append("file", files[0]);
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: ctx + "common/upload",
|
||||
data: data,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
success: function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$('#' + obj.id).summernote('insertImage', result.url);
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
$.modal.alertWarning("图片上传失败。");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
var content = $("input[name='" + this.id + "']").val();
|
||||
$('#' + this.id).summernote('code', content);
|
||||
})
|
||||
});
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#if($table.tree)
|
||||
|
||||
/*${functionName}-新增-选择父部门树*/
|
||||
@@ -205,6 +312,7 @@
|
||||
showRefresh: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
sidePagination: "client",
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package ${basePackage}.web.controller.${moduleName};
|
||||
package ${packageName}.controller;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- 菜单 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, url, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}', '3', '1', '/${moduleName}/${businessName}', 'C', '0', '${permissionPrefix}:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
values('${functionName}', '${parentMenuId}', '1', '/${moduleName}/${businessName}', 'C', '0', '${permissionPrefix}:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
|
||||
-- 按钮父菜单ID
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
+19
-19
@@ -5,30 +5,30 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.3.0</version>
|
||||
<version>4.4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-quartz</artifactId>
|
||||
|
||||
<description>
|
||||
quartz定时任务
|
||||
</description>
|
||||
|
||||
<description>
|
||||
quartz定时任务
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 定时任务 -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 定时任务 -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
@@ -36,5 +36,5 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -21,6 +21,7 @@ import com.ruoyi.common.exception.job.TaskException;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.quartz.domain.SysJob;
|
||||
import com.ruoyi.quartz.service.ISysJobService;
|
||||
import com.ruoyi.quartz.util.CronUtils;
|
||||
|
||||
/**
|
||||
* 调度任务信息操作处理
|
||||
@@ -128,6 +129,10 @@ public class SysJobController extends BaseController
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(@Validated SysJob job) throws SchedulerException, TaskException
|
||||
{
|
||||
if (!CronUtils.isValid(job.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
}
|
||||
return toAjax(jobService.insertJob(job));
|
||||
}
|
||||
|
||||
@@ -150,6 +155,10 @@ public class SysJobController extends BaseController
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(@Validated SysJob job) throws SchedulerException, TaskException
|
||||
{
|
||||
if (!CronUtils.isValid(job.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
}
|
||||
return toAjax(jobService.updateJob(job));
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user