mirror of
https://gitee.com/y_project/RuoYi-Cloud.git
synced 2026-01-26 11:51:55 +08:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cca4eeae72 | ||
|
|
bf544deeaa | ||
|
|
a9a1200e77 | ||
|
|
43bc0ca39b | ||
|
|
c0251e5cda | ||
|
|
56ea7c9caf | ||
|
|
17d5751452 | ||
|
|
8b5a16c692 | ||
|
|
5524d5a0bc | ||
|
|
40696a10e3 | ||
|
|
9bfe3e5328 | ||
|
|
165a957d67 | ||
|
|
4a48702ccb | ||
|
|
41cf67da6d | ||
|
|
4126f634ba | ||
|
|
337f6fd3db | ||
|
|
8ae4f5e90b | ||
|
|
7e2b00b98b | ||
|
|
57200e5f5d | ||
|
|
bb5b7466db | ||
|
|
c7908e1b8e | ||
|
|
76aa1cda49 | ||
|
|
59b8df2e90 | ||
|
|
5967f7f11b | ||
|
|
3ad7742838 | ||
|
|
3a400df707 | ||
|
|
4a608d4d21 | ||
|
|
d9ebddc669 | ||
|
|
7ecba12d3e | ||
|
|
30aa0c4fca | ||
|
|
99e1dfccf5 | ||
|
|
d0fe6f3462 | ||
|
|
c404c280f7 | ||
|
|
7bdd20ec24 | ||
|
|
e0ba2ba3c5 | ||
|
|
e76d087b21 | ||
|
|
394bde5e8e | ||
|
|
ad690bac17 | ||
|
|
e056ab0cc2 | ||
|
|
7549c904f2 | ||
|
|
0788a57bec | ||
|
|
eb48d6a80f | ||
|
|
1b70ef990b | ||
|
|
e48d75afcd | ||
|
|
c91194f848 | ||
|
|
a90b576116 | ||
|
|
9aee5142fd | ||
|
|
230d4170e1 | ||
|
|
2c250c1d1b | ||
|
|
7302189208 | ||
|
|
a40d691e31 | ||
|
|
719e1fdfa9 | ||
|
|
5734607e03 | ||
|
|
e6e673e9b4 | ||
|
|
6eda1dee45 | ||
|
|
ff3bc4b25e | ||
|
|
aa13a1d88e | ||
|
|
beaf17ddd2 | ||
|
|
029fe5c63f | ||
|
|
bea2f32781 | ||
|
|
3b88fe2b6f | ||
|
|
97a0326abd | ||
|
|
83460dfcb6 | ||
|
|
6ee4efa284 | ||
|
|
1c06db8999 | ||
|
|
5fa7b3f579 | ||
|
|
bb305dfb6f | ||
|
|
5585a4e807 |
22
README.md
22
README.md
@@ -4,8 +4,8 @@
|
||||
* 后端采用Spring Boot、Spring Cloud & Alibaba。
|
||||
* 注册中心、配置中心选型Nacos,权限认证使用OAuth2。
|
||||
* 流量控制框架选型Sentinel。
|
||||
* 感谢[ruoyi-cloud-design](https://gitee.com/zhangmrit/ruoyi-cloud),[pig](https://gitee.com/log4j/pig)。
|
||||
* 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||
* 感谢[ruoyi-cloud-design](https://gitee.com/zhangmrit/ruoyi-cloud),[pig](https://gitee.com/log4j/pig)。
|
||||
* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
||||
|
||||
|
||||
@@ -74,27 +74,27 @@ com.ruoyi
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -110,4 +110,4 @@ com.ruoyi
|
||||
|
||||
## 若依微服务交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=yqInfq0S) 点击按钮入群。
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) 点击按钮入群。
|
||||
12
pom.xml
12
pom.xml
@@ -6,14 +6,14 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依微服务系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>2.0.0</ruoyi.version>
|
||||
<ruoyi.version>2.1.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>
|
||||
@@ -21,6 +21,7 @@
|
||||
<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
|
||||
<spring-boot-admin.version>2.2.3</spring-boot-admin.version>
|
||||
<spring-boot.mybatis>2.1.2</spring-boot.mybatis>
|
||||
<nacos.version>1.3.0</nacos.version>
|
||||
<swagger.fox.version>2.9.2</swagger.fox.version>
|
||||
<swagger.core.version>1.5.24</swagger.core.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
@@ -55,6 +56,13 @@
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Alibaba Nacos 配置 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot 依赖配置 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -11,13 +11,11 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
|
||||
@@ -118,22 +116,16 @@ public class AuthServerConfig extends AuthorizationServerConfigurerAdapter
|
||||
@Bean
|
||||
public TokenEnhancer tokenEnhancer()
|
||||
{
|
||||
return new TokenEnhancer()
|
||||
{
|
||||
@Override
|
||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication)
|
||||
return (accessToken, authentication) -> {
|
||||
if (authentication.getUserAuthentication() != null)
|
||||
{
|
||||
if (accessToken instanceof DefaultOAuth2AccessToken)
|
||||
{
|
||||
DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
|
||||
LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal();
|
||||
Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
|
||||
additionalInformation.put(SecurityConstants.DETAILS_USERNAME, authentication.getName());
|
||||
additionalInformation.put(SecurityConstants.DETAILS_USER_ID, user.getUserId());
|
||||
token.setAdditionalInformation(additionalInformation);
|
||||
}
|
||||
return accessToken;
|
||||
};
|
||||
Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
|
||||
LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal();
|
||||
additionalInformation.put(SecurityConstants.DETAILS_USER_ID, user.getUserId());
|
||||
additionalInformation.put(SecurityConstants.DETAILS_USERNAME, user.getUsername());
|
||||
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
|
||||
}
|
||||
return accessToken;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.auth.exception;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||
|
||||
/**
|
||||
* oauth2自定义异常
|
||||
*
|
||||
* @author ruoyi
|
||||
**/
|
||||
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
|
||||
public class CustomOauthException extends OAuth2Exception
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CustomOauthException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.ruoyi.auth.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.ruoyi.common.core.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
|
||||
/**
|
||||
* 自定义异常返回
|
||||
*
|
||||
* @author ruoyi
|
||||
**/
|
||||
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CustomOauthExceptionSerializer.class);
|
||||
|
||||
public static final String BAD_CREDENTIALS = "Bad credentials";
|
||||
|
||||
public CustomOauthExceptionSerializer()
|
||||
{
|
||||
super(CustomOauthException.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(CustomOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||
throws IOException
|
||||
{
|
||||
jsonGenerator.writeStartObject();
|
||||
jsonGenerator.writeNumberField(AjaxResult.CODE_TAG, HttpStatus.ERROR);
|
||||
if (StringUtils.equals(e.getMessage(), BAD_CREDENTIALS))
|
||||
{
|
||||
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, "用户名或密码错误");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("oauth2 认证异常 {} ", e);
|
||||
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, e.getMessage());
|
||||
}
|
||||
jsonGenerator.writeEndObject();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.ruoyi.auth.exception;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
|
||||
@@ -15,7 +15,6 @@ public class CustomWebResponseExceptionTranslator implements WebResponseExceptio
|
||||
@Override
|
||||
public ResponseEntity<OAuth2Exception> translate(Exception e)
|
||||
{
|
||||
OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
|
||||
return ResponseEntity.status(HttpServletResponse.SC_UNAUTHORIZED).body(oAuth2Exception);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new CustomOauthException(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Excel
|
||||
{
|
||||
/**
|
||||
* 导出时在excel中排序
|
||||
*/
|
||||
public int sort() default Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* 导出到Excel中的名字.
|
||||
*/
|
||||
@@ -29,6 +34,11 @@ public @interface Excel
|
||||
*/
|
||||
public String readConverterExp() default "";
|
||||
|
||||
/**
|
||||
* 分隔符,读取字符串组内容
|
||||
*/
|
||||
public String separator() default ",";
|
||||
|
||||
/**
|
||||
* 导出类型(0数字 1字符串)
|
||||
*/
|
||||
|
||||
@@ -31,10 +31,11 @@ public class Constants
|
||||
* 成功标记
|
||||
*/
|
||||
public static final Integer SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 失败标记
|
||||
*/
|
||||
public static final Integer FAIL = 501;
|
||||
public static final Integer FAIL = 500;
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
|
||||
@@ -22,6 +22,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" };
|
||||
|
||||
@@ -5,7 +5,7 @@ package com.ruoyi.common.core.constant;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface HttpStatus
|
||||
public class HttpStatus
|
||||
{
|
||||
/**
|
||||
* 操作成功
|
||||
|
||||
@@ -5,7 +5,7 @@ package com.ruoyi.common.core.constant;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ScheduleConstants
|
||||
public class ScheduleConstants
|
||||
{
|
||||
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package com.ruoyi.common.core.constant;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ServiceNameConstants
|
||||
public class ServiceNameConstants
|
||||
{
|
||||
/**
|
||||
* 认证服务的serviceid
|
||||
|
||||
@@ -12,6 +12,12 @@ public class R<T> implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 成功 */
|
||||
public static final int SUCCESS = Constants.SUCCESS;
|
||||
|
||||
/** 失败 */
|
||||
public static final int FAIL = Constants.FAIL;
|
||||
|
||||
private int code;
|
||||
|
||||
private String msg;
|
||||
@@ -20,40 +26,40 @@ public class R<T> implements Serializable
|
||||
|
||||
public static <T> R<T> ok()
|
||||
{
|
||||
return restResult(null, Constants.SUCCESS, null);
|
||||
return restResult(null, SUCCESS, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> ok(T data)
|
||||
{
|
||||
return restResult(data, Constants.SUCCESS, null);
|
||||
return restResult(data, SUCCESS, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> ok(T data, String msg)
|
||||
{
|
||||
return restResult(data, Constants.SUCCESS, msg);
|
||||
return restResult(data, SUCCESS, msg);
|
||||
}
|
||||
|
||||
public static <T> R<T> failed()
|
||||
public static <T> R<T> fail()
|
||||
{
|
||||
return restResult(null, Constants.FAIL, null);
|
||||
return restResult(null, FAIL, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> failed(String msg)
|
||||
public static <T> R<T> fail(String msg)
|
||||
{
|
||||
return restResult(null, Constants.FAIL, msg);
|
||||
return restResult(null, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> R<T> failed(T data)
|
||||
public static <T> R<T> fail(T data)
|
||||
{
|
||||
return restResult(data, Constants.FAIL, null);
|
||||
return restResult(data, FAIL, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> failed(T data, String msg)
|
||||
public static <T> R<T> fail(T data, String msg)
|
||||
{
|
||||
return restResult(data, Constants.FAIL, msg);
|
||||
return restResult(data, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> R<T> failed(int code, String msg)
|
||||
public static <T> R<T> fail(int code, String msg)
|
||||
{
|
||||
return restResult(null, code, msg);
|
||||
}
|
||||
|
||||
@@ -376,6 +376,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
|
||||
*
|
||||
* @return UUID 的哈希码值。
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
long hilo = mostSigBits ^ leastSigBits;
|
||||
@@ -391,6 +392,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
|
||||
*
|
||||
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if ((null == obj) || (obj.getClass() != UUID.class))
|
||||
@@ -414,6 +416,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
|
||||
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(UUID val)
|
||||
{
|
||||
// The ordering is intentionally set up so that the UUIDs
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.ruoyi.common.core.utils.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 文件处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileUtils extends org.apache.commons.io.FileUtils
|
||||
{
|
||||
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
|
||||
|
||||
/**
|
||||
* 输出指定文件的byte数组
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @param os 输出流
|
||||
* @return
|
||||
*/
|
||||
public static void writeBytes(String filePath, OutputStream os) throws IOException
|
||||
{
|
||||
FileInputStream fis = null;
|
||||
try
|
||||
{
|
||||
File file = new File(filePath);
|
||||
if (!file.exists())
|
||||
{
|
||||
throw new FileNotFoundException(filePath);
|
||||
}
|
||||
fis = new FileInputStream(file);
|
||||
byte[] b = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(b)) > 0)
|
||||
{
|
||||
os.write(b, 0, length);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (os != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
os.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (fis != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fis.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param filePath 文件
|
||||
* @return
|
||||
*/
|
||||
public static boolean deleteFile(String filePath)
|
||||
{
|
||||
boolean flag = false;
|
||||
File file = new File(filePath);
|
||||
// 路径为文件且不为空则进行删除
|
||||
if (file.isFile() && file.exists())
|
||||
{
|
||||
file.delete();
|
||||
flag = true;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件名称验证
|
||||
*
|
||||
* @param filename 文件名称
|
||||
* @return true 正常 false 非法
|
||||
*/
|
||||
public static boolean isValidFilename(String filename)
|
||||
{
|
||||
return filename.matches(FILENAME_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @param fileName 文件名
|
||||
* @return 编码后的文件名
|
||||
*/
|
||||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
final String agent = request.getHeader("USER-AGENT");
|
||||
String filename = fileName;
|
||||
if (agent.contains("MSIE"))
|
||||
{
|
||||
// IE浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
filename = filename.replace("+", " ");
|
||||
}
|
||||
else if (agent.contains("Firefox"))
|
||||
{
|
||||
// 火狐浏览器
|
||||
filename = new String(fileName.getBytes(), "ISO8859-1");
|
||||
}
|
||||
else if (agent.contains("Chrome"))
|
||||
{
|
||||
// google浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其它浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
@@ -110,8 +110,9 @@ public class IpUtils
|
||||
{
|
||||
case 1:
|
||||
l = Long.parseLong(elements[0]);
|
||||
if ((l < 0L) || (l > 4294967295L))
|
||||
if ((l < 0L) || (l > 4294967295L)){
|
||||
return null;
|
||||
}
|
||||
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
|
||||
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
|
||||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
|
||||
@@ -119,12 +120,14 @@ public class IpUtils
|
||||
break;
|
||||
case 2:
|
||||
l = Integer.parseInt(elements[0]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[0] = (byte) (int) (l & 0xFF);
|
||||
l = Integer.parseInt(elements[1]);
|
||||
if ((l < 0L) || (l > 16777215L))
|
||||
if ((l < 0L) || (l > 16777215L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
|
||||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
|
||||
bytes[3] = (byte) (int) (l & 0xFF);
|
||||
@@ -133,13 +136,15 @@ public class IpUtils
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
l = Integer.parseInt(elements[i]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[i] = (byte) (int) (l & 0xFF);
|
||||
}
|
||||
l = Integer.parseInt(elements[2]);
|
||||
if ((l < 0L) || (l > 65535L))
|
||||
if ((l < 0L) || (l > 65535L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
|
||||
bytes[3] = (byte) (int) (l & 0xFF);
|
||||
break;
|
||||
@@ -147,8 +152,9 @@ public class IpUtils
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
l = Integer.parseInt(elements[i]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[i] = (byte) (int) (l & 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -6,13 +6,14 @@ import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
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.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
@@ -192,7 +193,10 @@ public class ExcelUtil<T>
|
||||
// 设置类的私有字段属性可访问.
|
||||
field.setAccessible(true);
|
||||
Integer column = cellMap.get(attr.name());
|
||||
fieldsMap.put(column, field);
|
||||
if (column != null)
|
||||
{
|
||||
fieldsMap.put(column, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < rows; i++)
|
||||
@@ -263,7 +267,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
||||
{
|
||||
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
|
||||
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
|
||||
}
|
||||
ReflectUtils.invokeSetter(entity, propertyName, val);
|
||||
}
|
||||
@@ -523,13 +527,14 @@ public class ExcelUtil<T>
|
||||
Object value = getTargetValue(vo, field, attr);
|
||||
String dateFormat = attr.dateFormat();
|
||||
String readConverterExp = attr.readConverterExp();
|
||||
String separator = attr.separator();
|
||||
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));
|
||||
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -607,28 +612,36 @@ public class ExcelUtil<T>
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String convertByExp(String propertyValue, String converterExp) throws Exception
|
||||
public static String convertByExp(String propertyValue, String converterExp, String separator)
|
||||
{
|
||||
try
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
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))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
if (itemArray[0].equals(value))
|
||||
{
|
||||
propertyString.append(itemArray[1] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[0].equals(propertyValue))
|
||||
{
|
||||
return itemArray[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,28 +649,36 @@ public class ExcelUtil<T>
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @param separator 分隔符
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String reverseByExp(String propertyValue, String converterExp) throws Exception
|
||||
public static String reverseByExp(String propertyValue, String converterExp, String separator)
|
||||
{
|
||||
try
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
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))
|
||||
{
|
||||
for (String value : propertyValue.split(separator))
|
||||
{
|
||||
if (itemArray[1].equals(value))
|
||||
{
|
||||
propertyString.append(itemArray[0] + separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[1].equals(propertyValue))
|
||||
{
|
||||
return itemArray[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,6 +760,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -809,14 +831,7 @@ public class ExcelUtil<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Double) val % 1 > 0)
|
||||
{
|
||||
val = new DecimalFormat("0.00").format(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = new DecimalFormat("0").format(val);
|
||||
}
|
||||
val = new BigDecimal(val.toString()); // 浮点格式处理
|
||||
}
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.STRING)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.common.core.utils.sql;
|
||||
|
||||
import com.ruoyi.common.core.exception.BaseException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -10,9 +11,9 @@ import com.ruoyi.common.core.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,79 @@
|
||||
package com.ruoyi.common.core.web.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tree基类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class TreeEntity extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 父菜单名称 */
|
||||
private String parentName;
|
||||
|
||||
/** 父菜单ID */
|
||||
private Long parentId;
|
||||
|
||||
/** 显示顺序 */
|
||||
private Integer orderNum;
|
||||
|
||||
/** 祖级列表 */
|
||||
private String ancestors;
|
||||
|
||||
/** 子部门 */
|
||||
private List<?> children = new ArrayList<>();
|
||||
|
||||
public String getParentName()
|
||||
{
|
||||
return parentName;
|
||||
}
|
||||
|
||||
public void setParentName(String parentName)
|
||||
{
|
||||
this.parentName = parentName;
|
||||
}
|
||||
|
||||
public Long getParentId()
|
||||
{
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(Long parentId)
|
||||
{
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Integer getOrderNum()
|
||||
{
|
||||
return orderNum;
|
||||
}
|
||||
|
||||
public void setOrderNum(Integer orderNum)
|
||||
{
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
|
||||
public String getAncestors()
|
||||
{
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
public void setAncestors(String ancestors)
|
||||
{
|
||||
this.ancestors = ancestors;
|
||||
}
|
||||
|
||||
public List<?> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<?> children)
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ public class DataScopeAspect
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param user 用户
|
||||
* @param alias 别名
|
||||
* @param deptAlias 部门别名
|
||||
* @param userAlias 用户别名
|
||||
*/
|
||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -198,8 +198,14 @@ public class LogAspect
|
||||
{
|
||||
if (!isFilterObject(paramsArray[i]))
|
||||
{
|
||||
Object jsonObj = JSON.toJSON(paramsArray[i]);
|
||||
params += jsonObj.toString() + " ";
|
||||
try
|
||||
{
|
||||
Object jsonObj = JSON.toJSON(paramsArray[i]);
|
||||
params += jsonObj.toString() + " ";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException
|
||||
{
|
||||
if (t == null)
|
||||
@@ -45,6 +46,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException
|
||||
{
|
||||
if (bytes == null || bytes.length <= 0)
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
package com.ruoyi.common.redis.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.ListOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -33,13 +28,10 @@ public class RedisService
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param value 缓存的值
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> ValueOperations<String, T> setCacheObject(String key, T value)
|
||||
public <T> void setCacheObject(final String key, final T value)
|
||||
{
|
||||
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||
operation.set(key, value);
|
||||
return operation;
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,13 +41,35 @@ public class RedisService
|
||||
* @param value 缓存的值
|
||||
* @param timeout 时间
|
||||
* @param timeUnit 时间颗粒度
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit)
|
||||
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
|
||||
{
|
||||
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||
operation.set(key, value, timeout, timeUnit);
|
||||
return operation;
|
||||
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout)
|
||||
{
|
||||
return expire(key, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @param unit 时间单位
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout, final TimeUnit unit)
|
||||
{
|
||||
return redisTemplate.expire(key, timeout, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +78,7 @@ public class RedisService
|
||||
* @param key 缓存键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> T getCacheObject(String key)
|
||||
public <T> T getCacheObject(final String key)
|
||||
{
|
||||
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||
return operation.get(key);
|
||||
@@ -75,19 +89,20 @@ public class RedisService
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void deleteObject(String key)
|
||||
public boolean deleteObject(final String key)
|
||||
{
|
||||
redisTemplate.delete(key);
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除集合对象
|
||||
*
|
||||
* @param collection
|
||||
* @param collection 多个对象
|
||||
* @return
|
||||
*/
|
||||
public void deleteObject(Collection collection)
|
||||
public long deleteObject(final Collection collection)
|
||||
{
|
||||
redisTemplate.delete(collection);
|
||||
return redisTemplate.delete(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,18 +112,10 @@ public class RedisService
|
||||
* @param dataList 待缓存的List数据
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList)
|
||||
public <T> long setCacheList(final String key, final List<T> dataList)
|
||||
{
|
||||
ListOperations listOperation = redisTemplate.opsForList();
|
||||
if (null != dataList)
|
||||
{
|
||||
int size = dataList.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
listOperation.leftPush(key, dataList.get(i));
|
||||
}
|
||||
}
|
||||
return listOperation;
|
||||
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
||||
return count == null ? 0 : count;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,17 +124,9 @@ public class RedisService
|
||||
* @param key 缓存的键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> List<T> getCacheList(String key)
|
||||
public <T> List<T> getCacheList(final String key)
|
||||
{
|
||||
List<T> dataList = new ArrayList<T>();
|
||||
ListOperations<String, T> listOperation = redisTemplate.opsForList();
|
||||
Long size = listOperation.size(key);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
dataList.add(listOperation.index(key, i));
|
||||
}
|
||||
return dataList;
|
||||
return redisTemplate.opsForList().range(key, 0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,15 +136,10 @@ public class RedisService
|
||||
* @param dataSet 缓存的数据
|
||||
* @return 缓存数据的对象
|
||||
*/
|
||||
public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet)
|
||||
public <T> long setCacheSet(final String key, final Set<T> dataSet)
|
||||
{
|
||||
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||
Iterator<T> it = dataSet.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
setOperation.add(it.next());
|
||||
}
|
||||
return setOperation;
|
||||
Long count = redisTemplate.opsForSet().add(key, dataSet);
|
||||
return count == null ? 0 : count;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,12 +148,9 @@ public class RedisService
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Set<T> getCacheSet(String key)
|
||||
public <T> Set<T> getCacheSet(final String key)
|
||||
{
|
||||
Set<T> dataSet = new HashSet<T>();
|
||||
BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
|
||||
dataSet = operation.members();
|
||||
return dataSet;
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,19 +158,12 @@ public class RedisService
|
||||
*
|
||||
* @param key
|
||||
* @param dataMap
|
||||
* @return
|
||||
*/
|
||||
public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap)
|
||||
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
|
||||
{
|
||||
HashOperations hashOperations = redisTemplate.opsForHash();
|
||||
if (null != dataMap)
|
||||
{
|
||||
for (Map.Entry<String, T> entry : dataMap.entrySet())
|
||||
{
|
||||
hashOperations.put(key, entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (dataMap != null) {
|
||||
redisTemplate.opsForHash().putAll(key, dataMap);
|
||||
}
|
||||
return hashOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,10 +172,46 @@ public class RedisService
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Map<String, T> getCacheMap(String key)
|
||||
public <T> Map<String, T> getCacheMap(final String key)
|
||||
{
|
||||
Map<String, T> map = redisTemplate.opsForHash().entries(key);
|
||||
return map;
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 往Hash中存入数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @param value 值
|
||||
*/
|
||||
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
|
||||
{
|
||||
redisTemplate.opsForHash().put(key, hKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @return Hash中的对象
|
||||
*/
|
||||
public <T> T getCacheMapValue(final String key, final String hKey)
|
||||
{
|
||||
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
||||
return opsForHash.get(key, hKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多个Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKeys Hash键集合
|
||||
* @return Hash对象集合
|
||||
*/
|
||||
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
|
||||
{
|
||||
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,7 +220,7 @@ public class RedisService
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
*/
|
||||
public Collection<String> keys(String pattern)
|
||||
public Collection<String> keys(final String pattern)
|
||||
{
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import com.ruoyi.common.security.feign.OAuth2FeignConfig;
|
||||
import com.ruoyi.common.security.config.ApplicationConfig;
|
||||
import com.ruoyi.common.security.config.SecurityImportBeanDefinitionRegistrar;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@@ -23,7 +20,7 @@ import com.ruoyi.common.security.config.SecurityImportBeanDefinitionRegistrar;
|
||||
// 开启线程异步执行
|
||||
@EnableAsync
|
||||
// 自动加载类
|
||||
@Import(SecurityImportBeanDefinitionRegistrar.class)
|
||||
@Import({ SecurityImportBeanDefinitionRegistrar.class, OAuth2FeignConfig.class, ApplicationConfig.class })
|
||||
public @interface EnableCustomConfig
|
||||
{
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.common.security.config;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ApplicationConfig
|
||||
{
|
||||
/**
|
||||
* 时区配置
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
|
||||
{
|
||||
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 忽略服务间的认证
|
||||
*
|
||||
* @author ruoyi
|
||||
**/
|
||||
@Component
|
||||
@Configurable
|
||||
@ConfigurationProperties(prefix = "security.oauth2.ignore")
|
||||
public class AuthIgnoreConfig
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.security.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @EnableGlobalMethodSecurity(securedEnabled=true)
|
||||
* 开启@Secured 注解过滤权限
|
||||
*
|
||||
* @EnableGlobalMethodSecurity(jsr250Enabled=true)
|
||||
* 开启@RolesAllowed 注解过滤权限
|
||||
*
|
||||
* @EnableGlobalMethodSecurity(prePostEnabled=true)
|
||||
* 使用表达式时间方法级别的安全性 4个注解可用
|
||||
* -@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
|
||||
* -@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常
|
||||
* -@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果
|
||||
* -@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig
|
||||
{
|
||||
|
||||
}
|
||||
@@ -28,6 +28,6 @@ public class CustomAccessDeniedHandler extends OAuth2AccessDeniedHandler
|
||||
logger.info("权限不足,请联系管理员 {}", request.getRequestURI());
|
||||
|
||||
String msg = authException.getMessage();
|
||||
ServletUtils.renderString(response, JSON.toJSONString(R.failed(HttpStatus.FORBIDDEN, msg)));
|
||||
ServletUtils.renderString(response, JSON.toJSONString(R.fail(HttpStatus.FORBIDDEN, msg)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.ruoyi.common.security.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
import com.ruoyi.common.core.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.exception.BaseException;
|
||||
import com.ruoyi.common.core.exception.CustomException;
|
||||
import com.ruoyi.common.core.exception.DemoModeException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 基础异常
|
||||
*/
|
||||
@ExceptionHandler(BaseException.class)
|
||||
public AjaxResult baseException(BaseException e)
|
||||
{
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*/
|
||||
@ExceptionHandler(CustomException.class)
|
||||
public AjaxResult businessException(CustomException e)
|
||||
{
|
||||
if (StringUtils.isNull(e.getCode()))
|
||||
{
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
return AjaxResult.error(e.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
public AjaxResult handlerNoFoundException(Exception e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error(HttpStatus.NOT_FOUND, "路径不存在,请检查路径是否正确");
|
||||
}
|
||||
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public AjaxResult handleAuthorizationException(AccessDeniedException e)
|
||||
{
|
||||
log.error(e.getMessage());
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
@ExceptionHandler(AccountExpiredException.class)
|
||||
public AjaxResult handleAccountExpiredException(AccountExpiredException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UsernameNotFoundException.class)
|
||||
public AjaxResult handleUsernameNotFoundException(UsernameNotFoundException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public AjaxResult handleException(Exception e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义验证异常
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
public AjaxResult validatedBindException(BindException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
String message = e.getAllErrors().get(0).getDefaultMessage();
|
||||
return AjaxResult.error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义验证异常
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public Object validExceptionHandler(MethodArgumentNotValidException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
String message = e.getBindingResult().getFieldError().getDefaultMessage();
|
||||
return AjaxResult.error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 演示模式异常
|
||||
*/
|
||||
@ExceptionHandler(DemoModeException.class)
|
||||
public AjaxResult demoModeException(DemoModeException e)
|
||||
{
|
||||
return AjaxResult.error("演示模式,不允许操作");
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ public class PermissionService
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
* @param permissions 权限列表
|
||||
* @param authorities 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.ruoyi.common.security.service.UserDetailsServiceImpl,\
|
||||
com.ruoyi.common.security.handler.CustomAccessDeniedHandler
|
||||
com.ruoyi.common.security.service.PermissionService,\
|
||||
com.ruoyi.common.security.config.MethodSecurityConfig,\
|
||||
com.ruoyi.common.security.handler.CustomAccessDeniedHandler,\
|
||||
com.ruoyi.common.security.handler.GlobalExceptionHandler
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.ruoyi.common.swagger.config;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties("swagger")
|
||||
public class SwaggerProperties
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -28,4 +28,4 @@ public class RuoYiGatewayApplication
|
||||
" | | \\ / \\ / \n" +
|
||||
" ''-' `'-' `-..-' ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import static com.google.code.kaptcha.Constants.*;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
@@ -14,42 +15,67 @@ import com.google.code.kaptcha.util.Config;
|
||||
@Configuration
|
||||
public class CaptchaConfig
|
||||
{
|
||||
@Bean(name = "captchaProducer")
|
||||
public DefaultKaptcha getKaptchaBean()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
|
||||
@Bean(name = "captchaProducerMath")
|
||||
public DefaultKaptcha getKaptchaBeanMath()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty("kaptcha.border", "yes");
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.border.color", "105,179,90");
|
||||
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue");
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty("kaptcha.image.width", "160");
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty("kaptcha.image.height", "60");
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "35");
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
|
||||
// 验证码文本生成器
|
||||
properties.setProperty("kaptcha.textproducer.impl", "com.ruoyi.gateway.config.KaptchaTextCreator");
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator");
|
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty("kaptcha.textproducer.char.space", "3");
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "6");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1,
|
||||
// fontSize)
|
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.noise.color", "white");
|
||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
|
||||
// 干扰实现类
|
||||
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple
|
||||
// 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy
|
||||
// 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ruoyi.gateway.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 黑名单过滤器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config>
|
||||
{
|
||||
@Override
|
||||
public GatewayFilter apply(Config config)
|
||||
{
|
||||
return (exchange, chain) -> {
|
||||
|
||||
String url = exchange.getRequest().getURI().getPath();
|
||||
if (config.matchBlacklist(url))
|
||||
{
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
return exchange.getResponse().writeWith(
|
||||
Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(AjaxResult.error("服务拒绝访问")))));
|
||||
}
|
||||
|
||||
return chain.filter(exchange);
|
||||
};
|
||||
}
|
||||
|
||||
public BlackListUrlFilter()
|
||||
{
|
||||
super(Config.class);
|
||||
}
|
||||
|
||||
public static class Config
|
||||
{
|
||||
private List<String> blacklistUrl;
|
||||
|
||||
private List<Pattern> blacklistUrlPattern = new ArrayList<>();
|
||||
|
||||
public boolean matchBlacklist(String url)
|
||||
{
|
||||
return blacklistUrlPattern.isEmpty() ? false : blacklistUrlPattern.stream().filter(p -> p.matcher(url).find()).findAny().isPresent();
|
||||
}
|
||||
|
||||
public List<String> getBlacklistUrl()
|
||||
{
|
||||
return blacklistUrl;
|
||||
}
|
||||
|
||||
public void setBlacklistUrl(List<String> blacklistUrl)
|
||||
{
|
||||
this.blacklistUrl = blacklistUrl;
|
||||
this.blacklistUrlPattern.clear();
|
||||
this.blacklistUrl.forEach(url -> {
|
||||
this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,10 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
|
||||
private static final String CODE = "code";
|
||||
|
||||
private static final String UUID = "uuid";
|
||||
|
||||
private static final String GRANT_TYPE = "grant_type";
|
||||
|
||||
private static final String REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Object config)
|
||||
@@ -43,6 +47,13 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
|
||||
{
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
// 刷新token请求,不处理
|
||||
String grantType = request.getQueryParams().getFirst(GRANT_TYPE);
|
||||
if (StringUtils.containsIgnoreCase(request.getURI().getPath(), AUTH_URL) && StringUtils.containsIgnoreCase(grantType, REFRESH_TOKEN))
|
||||
{
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
// 消息头存在内容,且不存在验证码参数,不处理
|
||||
String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||
@@ -59,6 +70,7 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
|
||||
catch (Exception e)
|
||||
{
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
|
||||
return exchange.getResponse().writeWith(
|
||||
Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(AjaxResult.error(e.getMessage())))));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ruoyi.gateway.handler;
|
||||
|
||||
import org.springframework.cloud.gateway.support.NotFoundException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 网关统一异常处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Order(-1)
|
||||
@Configuration
|
||||
public class GatewayExceptionHandler implements ErrorWebExceptionHandler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
|
||||
{
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
|
||||
if (exchange.getResponse().isCommitted())
|
||||
{
|
||||
return Mono.error(ex);
|
||||
}
|
||||
|
||||
String msg;
|
||||
|
||||
if (ex instanceof NotFoundException)
|
||||
{
|
||||
msg = "服务未找到";
|
||||
}
|
||||
else if (ex instanceof ResponseStatusException)
|
||||
{
|
||||
ResponseStatusException responseStatusException = (ResponseStatusException) ex;
|
||||
msg = responseStatusException.getMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "内部服务器错误";
|
||||
}
|
||||
|
||||
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
|
||||
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
|
||||
return response.writeWith(Mono.fromSupplier(() -> {
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.ruoyi.gateway.service.impl;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -25,28 +26,46 @@ import com.ruoyi.gateway.service.ValidateCodeService;
|
||||
@Service
|
||||
public class ValidateCodeServiceImpl implements ValidateCodeService
|
||||
{
|
||||
@Autowired
|
||||
private Producer producer;
|
||||
@Resource(name = "captchaProducer")
|
||||
private Producer captchaProducer;
|
||||
|
||||
@Resource(name = "captchaProducerMath")
|
||||
private Producer captchaProducerMath;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
// 验证码类型
|
||||
private String captchaType = "math";
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult createCapcha() throws IOException, CaptchaException
|
||||
{
|
||||
// 生成验证码
|
||||
String capText = producer.createText();
|
||||
String capStr = capText.substring(0, capText.lastIndexOf("@"));
|
||||
String verifyCode = capText.substring(capText.lastIndexOf("@") + 1);
|
||||
BufferedImage image = producer.createImage(capStr);
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtils.simpleUUID();
|
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
||||
|
||||
redisService.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
||||
String capStr = null, code = null;
|
||||
BufferedImage image = null;
|
||||
|
||||
// 生成验证码
|
||||
if ("math".equals(captchaType))
|
||||
{
|
||||
String capText = captchaProducerMath.createText();
|
||||
capStr = capText.substring(0, capText.lastIndexOf("@"));
|
||||
code = capText.substring(capText.lastIndexOf("@") + 1);
|
||||
image = captchaProducerMath.createImage(capStr);
|
||||
}
|
||||
else if ("char".equals(captchaType))
|
||||
{
|
||||
capStr = code = captchaProducer.createText();
|
||||
image = captchaProducer.createImage(capStr);
|
||||
}
|
||||
|
||||
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
||||
// 转换流信息写出
|
||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
||||
try
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -148,15 +148,27 @@ public class GenController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* 生成代码(下载方式)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码(自定义路径)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('tool:gen:code')")
|
||||
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
|
||||
@GetMapping("/genCode/{tableName}")
|
||||
public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
|
||||
public AjaxResult genCode(HttpServletResponse response, @PathVariable("tableName") String tableName)
|
||||
{
|
||||
byte[] data = genTableService.generatorCode(tableName);
|
||||
genCode(response, data);
|
||||
genTableService.generatorCode(tableName);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,7 +180,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);
|
||||
}
|
||||
|
||||
@@ -183,4 +195,4 @@ public class GenController extends BaseController
|
||||
response.setContentType("application/octet-stream; charset=UTF-8");
|
||||
IOUtils.write(data, response.getOutputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,12 @@ public class GenTable extends BaseEntity
|
||||
@NotBlank(message = "作者不能为空")
|
||||
private String functionAuthor;
|
||||
|
||||
/** 生成代码方式(0zip压缩包 1自定义路径) */
|
||||
private String genType;
|
||||
|
||||
/** 生成路径(不填默认项目路径) */
|
||||
private String genPath;
|
||||
|
||||
/** 主键信息 */
|
||||
private GenTableColumn pkColumn;
|
||||
|
||||
@@ -74,6 +80,12 @@ public class GenTable extends BaseEntity
|
||||
/** 树名称字段 */
|
||||
private String treeName;
|
||||
|
||||
/** 上级菜单ID字段 */
|
||||
private String parentMenuId;
|
||||
|
||||
/** 上级菜单名称字段 */
|
||||
private String parentMenuName;
|
||||
|
||||
public Long getTableId()
|
||||
{
|
||||
return tableId;
|
||||
@@ -174,6 +186,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;
|
||||
@@ -234,6 +266,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 isTree()
|
||||
{
|
||||
return isTree(this.tplCategory);
|
||||
@@ -268,4 +320,4 @@ public class GenTable extends BaseEntity
|
||||
}
|
||||
return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService
|
||||
/**
|
||||
* 查询业务字段列表
|
||||
*
|
||||
* @param genTableColumn 业务字段编号
|
||||
* @param tableId 业务字段编号
|
||||
* @return 业务字段集合
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.gen.service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -22,7 +23,10 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.core.constant.Constants;
|
||||
import com.ruoyi.common.core.constant.GenConstants;
|
||||
import com.ruoyi.common.core.exception.CustomException;
|
||||
import com.ruoyi.common.core.text.CharsetKit;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.gen.domain.GenTable;
|
||||
import com.ruoyi.gen.domain.GenTableColumn;
|
||||
import com.ruoyi.gen.mapper.GenTableColumnMapper;
|
||||
@@ -79,6 +83,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
* @param genTable 业务信息
|
||||
* @return 数据库表集合
|
||||
*/
|
||||
@Override
|
||||
public List<GenTable> selectDbTableList(GenTable genTable)
|
||||
{
|
||||
return genTableMapper.selectDbTableList(genTable);
|
||||
@@ -90,6 +95,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
* @param tableNames 表名称组
|
||||
* @return 数据库表集合
|
||||
*/
|
||||
@Override
|
||||
public List<GenTable> selectDbTableListByNames(String[] tableNames)
|
||||
{
|
||||
return genTableMapper.selectDbTableListByNames(tableNames);
|
||||
@@ -120,7 +126,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
/**
|
||||
* 删除业务对象
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @param tableIds 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@@ -140,10 +146,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
@Transactional
|
||||
public void importGenTable(List<GenTable> tableList)
|
||||
{
|
||||
String operName = "";
|
||||
for (GenTable table : tableList)
|
||||
String operName = SecurityUtils.getUsername();
|
||||
try
|
||||
{
|
||||
try
|
||||
for (GenTable table : tableList)
|
||||
{
|
||||
String tableName = table.getTableName();
|
||||
GenUtils.initTable(table, operName);
|
||||
@@ -159,10 +165,10 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("表名 " + table.getTableName() + " 导入失败:", e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CustomException("导入失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +204,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);
|
||||
@@ -214,13 +220,55 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成代码
|
||||
* 生成代码(自定义路径)
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public void generatorCode(String tableName)
|
||||
{
|
||||
// 查询表信息
|
||||
GenTable table = genTableMapper.selectGenTableByName(tableName);
|
||||
// 查询列信息
|
||||
List<GenTableColumn> columns = table.getColumns();
|
||||
setPkColumn(table, columns);
|
||||
|
||||
VelocityInitializer.initVelocity();
|
||||
|
||||
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||
|
||||
// 获取模板列表
|
||||
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
|
||||
for (String template : templates)
|
||||
{
|
||||
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.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 CustomException("渲染模板失败,表名:" + table.getTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成代码(下载方式)
|
||||
*
|
||||
* @param tableNames 表数组
|
||||
* @return 数据
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String[] tableNames)
|
||||
public byte[] downloadCode(String[] tableNames)
|
||||
{
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
@@ -276,6 +324,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
*
|
||||
* @param genTable 业务信息
|
||||
*/
|
||||
@Override
|
||||
public void validateEdit(GenTable genTable)
|
||||
{
|
||||
if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
|
||||
@@ -300,7 +349,7 @@ public class GenTableServiceImpl implements IGenTableService
|
||||
/**
|
||||
* 设置主键列信息
|
||||
*
|
||||
* @param genTable 业务表信息
|
||||
* @param table 业务表信息
|
||||
* @param columns 业务字段列表
|
||||
*/
|
||||
public void setPkColumn(GenTable table, List<GenTableColumn> columns)
|
||||
@@ -332,9 +381,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface IGenTableColumnService
|
||||
/**
|
||||
* 查询业务字段列表
|
||||
*
|
||||
* @param genTableColumn 业务字段编号
|
||||
* @param tableId 业务字段编号
|
||||
* @return 业务字段集合
|
||||
*/
|
||||
public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
|
||||
|
||||
@@ -75,20 +75,28 @@ 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 表名称
|
||||
* @return 数据
|
||||
*/
|
||||
public void generatorCode(String tableName);
|
||||
|
||||
/**
|
||||
* 批量生成代码(下载方式)
|
||||
*
|
||||
* @param tableNames 表数组
|
||||
* @return 数据
|
||||
*/
|
||||
public byte[] generatorCode(String[] tableNames);
|
||||
public byte[] downloadCode(String[] tableNames);
|
||||
|
||||
/**
|
||||
* 修改保存参数校验
|
||||
|
||||
@@ -62,7 +62,7 @@ public class GenUtils
|
||||
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
|
||||
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
|
||||
{
|
||||
column.setJavaType(GenConstants.TYPE_DOUBLE);
|
||||
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
|
||||
}
|
||||
// 如果是整形
|
||||
else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
|
||||
@@ -195,7 +195,7 @@ public class GenUtils
|
||||
/**
|
||||
* 关键字替换
|
||||
*
|
||||
* @param name 需要被替换的名字
|
||||
* @param text 需要被替换的名字
|
||||
* @return 替换后的名字
|
||||
*/
|
||||
public static String replaceText(String text)
|
||||
|
||||
@@ -23,6 +23,9 @@ public class VelocityUtils
|
||||
|
||||
/** mybatis空间路径 */
|
||||
private static final String MYBATIS_PATH = "main/resources/mapper";
|
||||
|
||||
/** 默认上级菜单,系统工具 */
|
||||
private static final String DEFAULT_PARENT_MENU_ID = "3";
|
||||
|
||||
/**
|
||||
* 设置模板变量信息
|
||||
@@ -55,12 +58,21 @@ 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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -190,7 +202,7 @@ public class VelocityUtils
|
||||
/**
|
||||
* 根据列类型获取导入包
|
||||
*
|
||||
* @param column 列集合
|
||||
* @param columns 列集合
|
||||
* @return 返回需要导入的包列表
|
||||
*/
|
||||
public static HashSet<String> getImportList(List<GenTableColumn> columns)
|
||||
@@ -221,13 +233,27 @@ public class VelocityUtils
|
||||
public static String getPermissionPrefix(String moduleName, String businessName)
|
||||
{
|
||||
return StringUtils.format("{}:{}", moduleName, businessName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上级菜单ID字段
|
||||
*
|
||||
* @param paramsObj 生成其他选项
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树编码
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树编码
|
||||
*/
|
||||
public static String getTreecode(JSONObject paramsObj)
|
||||
@@ -236,13 +262,13 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树父编码
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树父编码
|
||||
*/
|
||||
public static String getTreeParentCode(JSONObject paramsObj)
|
||||
@@ -251,13 +277,13 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树名称
|
||||
*
|
||||
* @param options 生成其他选项
|
||||
* @param paramsObj 生成其他选项
|
||||
* @return 树名称
|
||||
*/
|
||||
public static String getTreeName(JSONObject paramsObj)
|
||||
@@ -266,7 +292,7 @@ public class VelocityUtils
|
||||
{
|
||||
return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
|
||||
}
|
||||
return "";
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,4 +321,4 @@ public class VelocityUtils
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,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" />
|
||||
@@ -50,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGenTableVo">
|
||||
select table_id, table_name, table_comment, 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, 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">
|
||||
@@ -62,6 +64,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">
|
||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@@ -94,7 +102,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.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.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
|
||||
@@ -102,7 +110,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.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.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
|
||||
@@ -120,6 +128,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
|
||||
@@ -133,6 +143,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()
|
||||
@@ -146,6 +158,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</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>
|
||||
|
||||
@@ -63,12 +63,12 @@ public class ${ClassName}Controller extends BaseController
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
|
||||
@Log(title = "${functionName}", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export")
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, ${ClassName} ${className}) throws IOException
|
||||
{
|
||||
List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
|
||||
ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
|
||||
return util.exportExcel(response, list, "${businessName}");
|
||||
util.exportExcel(response, list, "${businessName}");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,11 +5,11 @@ import ${import};
|
||||
#end
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
|
||||
import com.ruoyi.common.core.annotation.Excel;
|
||||
#if($table.crud)
|
||||
import com.ruoyi.framework.web.domain.BaseEntity;
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
#elseif($table.tree)
|
||||
import com.ruoyi.framework.web.domain.TreeEntity;
|
||||
import com.ruoyi.common.core.web.domain.TreeEntity;
|
||||
#end
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ package ${packageName}.service.impl;
|
||||
import java.util.List;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.core.utils.DateUtils;
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- 菜单 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
|
||||
-- 按钮父菜单ID
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
#foreach($column in $columns)
|
||||
#if($column.query)
|
||||
#set($dictType=$column.dictType)
|
||||
@@ -51,23 +51,30 @@
|
||||
#end
|
||||
#end
|
||||
<el-form-item>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="handleQuery"
|
||||
>搜索</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['${moduleName}:${businessName}:add']"
|
||||
>新增</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<div class="top-right-btn">
|
||||
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
||||
<el-button size="mini" circle icon="el-icon-refresh" @click="handleQuery" />
|
||||
</el-tooltip>
|
||||
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
|
||||
<el-button size="mini" circle icon="el-icon-search" @click="showSearch=!showSearch" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
@@ -157,6 +164,23 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${field}Options"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictValue">
|
||||
{{dict.dictLabel}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-radio-group v-model="form.${field}">
|
||||
@@ -212,6 +236,8 @@ export default {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// ${functionName}表格数据
|
||||
${businessName}List: [],
|
||||
// ${functionName}树选项
|
||||
@@ -236,7 +262,7 @@ export default {
|
||||
queryParams: {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.query)
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@@ -312,7 +338,7 @@ export default {
|
||||
#end
|
||||
// $comment字典翻译
|
||||
${column.javaField}Format(row, column) {
|
||||
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
|
||||
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
|
||||
},
|
||||
#end
|
||||
#end
|
||||
@@ -326,10 +352,13 @@ export default {
|
||||
this.form = {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "radio")
|
||||
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#elseif($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#else
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@@ -356,20 +385,30 @@ export default {
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.getTreeselect();
|
||||
if (row != undefined) {
|
||||
if (row != null) {
|
||||
this.form.${treeParentCode} = row.${treeCode};
|
||||
}
|
||||
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
|
||||
this.form = response.data;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
||||
#end
|
||||
#end
|
||||
this.open = true;
|
||||
this.title = "修改${functionName}";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
submitForm() {
|
||||
this.#[[$]]#refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.${pkColumn.javaField} != undefined) {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
||||
#end
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
@@ -404,4 +443,4 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
#foreach($column in $columns)
|
||||
#if($column.query)
|
||||
#set($dictType=$column.dictType)
|
||||
@@ -51,7 +51,7 @@
|
||||
#end
|
||||
#end
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -95,6 +95,14 @@
|
||||
v-hasPermi="['${moduleName}:${businessName}:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<div class="top-right-btn">
|
||||
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
||||
<el-button size="mini" circle icon="el-icon-refresh" @click="handleQuery" />
|
||||
</el-tooltip>
|
||||
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
|
||||
<el-button size="mini" circle icon="el-icon-search" @click="showSearch=!showSearch" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
|
||||
@@ -185,6 +193,23 @@
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${field}Options"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictValue">
|
||||
{{dict.dictLabel}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox" && $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-checkbox-group v-model="form.${field}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "radio" && "" != $dictType)
|
||||
<el-form-item label="${comment}">
|
||||
<el-radio-group v-model="form.${field}">
|
||||
@@ -243,6 +268,8 @@ export default {
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// ${functionName}表格数据
|
||||
@@ -269,7 +296,7 @@ export default {
|
||||
pageSize: 10,
|
||||
#foreach ($column in $columns)
|
||||
#if($column.query)
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@@ -326,7 +353,7 @@ export default {
|
||||
#end
|
||||
// $comment字典翻译
|
||||
${column.javaField}Format(row, column) {
|
||||
return this.selectDictLabel(this.${column.javaField}Options, row.${column.javaField});
|
||||
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
|
||||
},
|
||||
#end
|
||||
#end
|
||||
@@ -340,10 +367,13 @@ export default {
|
||||
this.form = {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "radio")
|
||||
$column.javaField: "0"#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#elseif($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#else
|
||||
$column.javaField: undefined#if($velocityCount != $columns.size()),#end
|
||||
$column.javaField: null#if($velocityCount != $columns.size()),#end
|
||||
|
||||
#end
|
||||
#end
|
||||
@@ -363,7 +393,7 @@ export default {
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.${pkColumn.javaField})
|
||||
this.single = selection.length!=1
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
@@ -378,15 +408,25 @@ export default {
|
||||
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
|
||||
get${BusinessName}(${pkColumn.javaField}).then(response => {
|
||||
this.form = response.data;
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.split(",");
|
||||
#end
|
||||
#end
|
||||
this.open = true;
|
||||
this.title = "修改${functionName}";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function() {
|
||||
submitForm() {
|
||||
this.#[[$]]#refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.${pkColumn.javaField} != undefined) {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.htmlType == "checkbox")
|
||||
this.form.$column.javaField = this.form.${column.javaField}.join(",");
|
||||
#end
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -21,8 +21,10 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.web.page.TableDataInfo;
|
||||
import com.ruoyi.common.log.annotation.Log;
|
||||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.job.domain.SysJob;
|
||||
import com.ruoyi.job.service.ISysJobService;
|
||||
import com.ruoyi.job.util.CronUtils;
|
||||
|
||||
/**
|
||||
* 调度任务信息操作处理
|
||||
@@ -79,6 +81,11 @@ public class SysJobController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
|
||||
{
|
||||
if (!CronUtils.isValid(sysJob.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
}
|
||||
sysJob.setCreateBy(SecurityUtils.getUsername());
|
||||
return toAjax(jobService.insertJob(sysJob));
|
||||
}
|
||||
|
||||
@@ -90,6 +97,11 @@ public class SysJobController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException
|
||||
{
|
||||
if (!CronUtils.isValid(sysJob.getCronExpression()))
|
||||
{
|
||||
return AjaxResult.error("cron表达式不正确");
|
||||
}
|
||||
sysJob.setUpdateBy(SecurityUtils.getUsername());
|
||||
return toAjax(jobService.updateJob(sysJob));
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public abstract class AbstractQuartzJob implements Job
|
||||
* 执行后
|
||||
*
|
||||
* @param context 工作执行上下文对象
|
||||
* @param sysScheduleJob 系统计划任务
|
||||
* @param sysJob 系统计划任务
|
||||
*/
|
||||
protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@ public class JobInvokeUtil
|
||||
/**
|
||||
* 校验是否为为class包名
|
||||
*
|
||||
* @param str 名称
|
||||
* @param invokeTarget 名称
|
||||
* @return true是 false否
|
||||
*/
|
||||
public static boolean isValidClassName(String invokeTarget)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.web.page.TableDataInfo;
|
||||
import com.ruoyi.common.log.annotation.Log;
|
||||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.system.domain.SysClientDetails;
|
||||
import com.ruoyi.system.service.ISysClientDetailsService;
|
||||
|
||||
@@ -67,6 +68,7 @@ public class SysClientDetailsController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("新增终端'" + clientId + "'失败,编号已存在");
|
||||
}
|
||||
sysClientDetails.setClientSecret(SecurityUtils.encryptPassword(sysClientDetails.getClientSecret()));
|
||||
return toAjax(sysClientDetailsService.insertSysClientDetails(sysClientDetails));
|
||||
}
|
||||
|
||||
@@ -78,6 +80,7 @@ public class SysClientDetailsController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody SysClientDetails sysClientDetails)
|
||||
{
|
||||
sysClientDetails.setClientSecret(SecurityUtils.encryptPassword(sysClientDetails.getClientSecret()));
|
||||
return toAjax(sysClientDetailsService.updateSysClientDetails(sysClientDetails));
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ public class SysConfigController extends BaseController
|
||||
/**
|
||||
* 根据参数编号获取详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasRole('admin')")
|
||||
@GetMapping(value = "/{configId}")
|
||||
public AjaxResult getInfo(@PathVariable Long configId)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ruoyi.system.controller;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -26,6 +27,7 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
|
||||
import com.ruoyi.common.log.annotation.Log;
|
||||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.system.api.domain.SysRole;
|
||||
import com.ruoyi.system.api.domain.SysUser;
|
||||
import com.ruoyi.system.api.model.UserInfo;
|
||||
import com.ruoyi.system.service.ISysPermissionService;
|
||||
@@ -102,6 +104,10 @@ public class SysUserController extends BaseController
|
||||
public R<UserInfo> info(@PathVariable("username") String username)
|
||||
{
|
||||
SysUser sysUser = userService.selectUserByUserName(username);
|
||||
if (StringUtils.isNull(sysUser))
|
||||
{
|
||||
return R.fail("用户名或密码错误");
|
||||
}
|
||||
// 角色集合
|
||||
Set<String> roles = permissionService.getRolePermission(sysUser.getUserId());
|
||||
// 权限集合
|
||||
@@ -141,7 +147,8 @@ public class SysUserController extends BaseController
|
||||
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
|
||||
{
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("roles", roleService.selectRoleAll());
|
||||
List<SysRole> roles = roleService.selectRoleAll();
|
||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
ajax.put("posts", postService.selectPostAll());
|
||||
if (StringUtils.isNotNull(userId))
|
||||
{
|
||||
|
||||
@@ -49,12 +49,4 @@ public interface ISysClientDetailsService
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysClientDetailsByIds(String[] clientIds);
|
||||
|
||||
/**
|
||||
* 删除终端配置信息
|
||||
*
|
||||
* @param clientId 终端配置ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysClientDetailsById(String clientId);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public interface ISysPermissionService
|
||||
/**
|
||||
* 获取角色数据权限
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param userId 用户Id
|
||||
* @return 角色权限信息
|
||||
*/
|
||||
public Set<String> getRolePermission(Long userId);
|
||||
@@ -15,7 +15,7 @@ public interface ISysPermissionService
|
||||
/**
|
||||
* 获取菜单数据权限
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param userId 用户Id
|
||||
* @return 菜单权限信息
|
||||
*/
|
||||
public Set<String> getMenuPermission(Long userId);
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
//package com.ruoyi.system.service;
|
||||
//
|
||||
//import com.ruoyi.system.domain.SysUserOnline;
|
||||
//
|
||||
///**
|
||||
// * 在线用户 服务层
|
||||
// *
|
||||
// * @author ruoyi
|
||||
// */
|
||||
//public interface ISysUserOnlineService
|
||||
//{
|
||||
// /**
|
||||
// * 通过登录地址查询信息
|
||||
// *
|
||||
// * @param ipaddr 登录地址
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
|
||||
//
|
||||
// /**
|
||||
// * 通过用户名称查询信息
|
||||
// *
|
||||
// * @param userName 用户名称
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// public SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
|
||||
//
|
||||
// /**
|
||||
// * 通过登录地址/用户名称查询信息
|
||||
// *
|
||||
// * @param ipaddr 登录地址
|
||||
// * @param userName 用户名称
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
|
||||
//
|
||||
// /**
|
||||
// * 设置在线用户信息
|
||||
// *
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户
|
||||
// */
|
||||
// public SysUserOnline loginUserToUserOnline(LoginUser user);
|
||||
//}
|
||||
@@ -2,9 +2,11 @@ package com.ruoyi.system.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.system.mapper.SysClientDetailsMapper;
|
||||
import com.ruoyi.common.core.constant.CacheConstants;
|
||||
import com.ruoyi.system.domain.SysClientDetails;
|
||||
import com.ruoyi.system.mapper.SysClientDetailsMapper;
|
||||
import com.ruoyi.system.service.ISysClientDetailsService;
|
||||
|
||||
/**
|
||||
@@ -61,6 +63,7 @@ public class SysClientDetailsServiceImpl implements ISysClientDetailsService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#sysClientDetails.clientId")
|
||||
public int updateSysClientDetails(SysClientDetails sysClientDetails)
|
||||
{
|
||||
return sysClientDetailsMapper.updateSysClientDetails(sysClientDetails);
|
||||
@@ -73,20 +76,9 @@ public class SysClientDetailsServiceImpl implements ISysClientDetailsService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(value = CacheConstants.CLIENT_DETAILS_KEY, allEntries = true)
|
||||
public int deleteSysClientDetailsByIds(String[] clientIds)
|
||||
{
|
||||
return sysClientDetailsMapper.deleteSysClientDetailsByIds(clientIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除终端配置信息
|
||||
*
|
||||
* @param clientId 终端配置ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSysClientDetailsById(String clientId)
|
||||
{
|
||||
return sysClientDetailsMapper.deleteSysClientDetailsById(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
/**
|
||||
* 清空缓存数据
|
||||
*/
|
||||
@Override
|
||||
public void clearCache()
|
||||
{
|
||||
Collection<String> keys = redisService.keys(Constants.SYS_CONFIG_KEY + "*");
|
||||
|
||||
@@ -62,6 +62,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService
|
||||
* @param dictCodes 需要删除的字典数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteDictDataByIds(Long[] dictCodes)
|
||||
{
|
||||
int row = dictDataMapper.deleteDictDataByIds(dictCodes);
|
||||
|
||||
@@ -107,6 +107,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
|
||||
* @param dictType 字典类型
|
||||
* @return 字典类型
|
||||
*/
|
||||
@Override
|
||||
public SysDictType selectDictTypeByType(String dictType)
|
||||
{
|
||||
return dictTypeMapper.selectDictTypeByType(dictType);
|
||||
@@ -118,6 +119,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
|
||||
* @param dictIds 需要删除的字典ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteDictTypeByIds(Long[] dictIds)
|
||||
{
|
||||
for (Long dictId : dictIds)
|
||||
@@ -139,6 +141,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
|
||||
/**
|
||||
* 清空缓存数据
|
||||
*/
|
||||
@Override
|
||||
public void clearCache()
|
||||
{
|
||||
DictUtils.clearDictCache();
|
||||
|
||||
@@ -121,6 +121,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
||||
* @param roleId 角色ID
|
||||
* @return 选中菜单列表
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> selectMenuListByRoleId(Long roleId)
|
||||
{
|
||||
return menuMapper.selectMenuListByRoleId(roleId);
|
||||
|
||||
@@ -86,6 +86,7 @@ public class SysNoticeServiceImpl implements ISysNoticeService
|
||||
* @param noticeIds 需要删除的公告ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteNoticeByIds(Long[] noticeIds)
|
||||
{
|
||||
return noticeMapper.deleteNoticeByIds(noticeIds);
|
||||
|
||||
@@ -48,6 +48,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
|
||||
* @param operIds 需要删除的操作日志ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOperLogByIds(Long[] operIds)
|
||||
{
|
||||
return operLogMapper.deleteOperLogByIds(operIds);
|
||||
|
||||
@@ -22,9 +22,10 @@ public class SysPermissionServiceImpl implements ISysPermissionService
|
||||
/**
|
||||
* 获取角色数据权限
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param userId 用户Id
|
||||
* @return 角色权限信息
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getRolePermission(Long userId)
|
||||
{
|
||||
Set<String> roles = new HashSet<String>();
|
||||
@@ -43,9 +44,10 @@ public class SysPermissionServiceImpl implements ISysPermissionService
|
||||
/**
|
||||
* 获取菜单数据权限
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param userId 用户Id
|
||||
* @return 菜单权限信息
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getMenuPermission(Long userId)
|
||||
{
|
||||
Set<String> perms = new HashSet<String>();
|
||||
|
||||
@@ -68,6 +68,7 @@ public class SysPostServiceImpl implements ISysPostService
|
||||
* @param userId 用户ID
|
||||
* @return 选中岗位ID列表
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> selectPostListByUserId(Long userId)
|
||||
{
|
||||
return postMapper.selectPostListByUserId(userId);
|
||||
@@ -140,6 +141,7 @@ public class SysPostServiceImpl implements ISysPostService
|
||||
* @return 结果
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
@Override
|
||||
public int deletePostByIds(Long[] postIds)
|
||||
{
|
||||
for (Long postId : postIds)
|
||||
|
||||
@@ -81,6 +81,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
*
|
||||
* @return 角色列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysRole> selectRoleAll()
|
||||
{
|
||||
return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
|
||||
@@ -92,6 +93,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @param userId 用户ID
|
||||
* @return 选中角色ID列表
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> selectRoleListByUserId(Long userId)
|
||||
{
|
||||
return roleMapper.selectRoleListByUserId(userId);
|
||||
@@ -103,6 +105,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @param roleId 角色ID
|
||||
* @return 角色对象信息
|
||||
*/
|
||||
@Override
|
||||
public SysRole selectRoleById(Long roleId)
|
||||
{
|
||||
return roleMapper.selectRoleById(roleId);
|
||||
@@ -149,6 +152,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
*
|
||||
* @param role 角色信息
|
||||
*/
|
||||
@Override
|
||||
public void checkRoleAllowed(SysRole role)
|
||||
{
|
||||
if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
|
||||
@@ -207,6 +211,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @param role 角色信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateRoleStatus(SysRole role)
|
||||
{
|
||||
return roleMapper.updateRole(role);
|
||||
@@ -296,6 +301,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @param roleIds 需要删除的角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteRoleByIds(Long[] roleIds)
|
||||
{
|
||||
for (Long roleId : roleIds)
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
//package com.ruoyi.system.service.impl;
|
||||
//
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//import com.ruoyi.common.core.utils.StringUtils;
|
||||
//import com.ruoyi.system.domain.SysUserOnline;
|
||||
//import com.ruoyi.system.service.ISysUserOnlineService;
|
||||
//
|
||||
///**
|
||||
// * 在线用户 服务层处理
|
||||
// *
|
||||
// * @author ruoyi
|
||||
// */
|
||||
//@Service
|
||||
//public class SysUserOnlineServiceImpl implements ISysUserOnlineService
|
||||
//{
|
||||
// /**
|
||||
// * 通过登录地址查询信息
|
||||
// *
|
||||
// * @param ipaddr 登录地址
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// @Override
|
||||
// public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user)
|
||||
// {
|
||||
// if (StringUtils.equals(ipaddr, user.getIpaddr()))
|
||||
// {
|
||||
// return loginUserToUserOnline(user);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 通过用户名称查询信息
|
||||
// *
|
||||
// * @param userName 用户名称
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// @Override
|
||||
// public SysUserOnline selectOnlineByUserName(String userName, LoginUser user)
|
||||
// {
|
||||
// if (StringUtils.equals(userName, user.getUsername()))
|
||||
// {
|
||||
// return loginUserToUserOnline(user);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 通过登录地址/用户名称查询信息
|
||||
// *
|
||||
// * @param ipaddr 登录地址
|
||||
// * @param userName 用户名称
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户信息
|
||||
// */
|
||||
// @Override
|
||||
// public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user)
|
||||
// {
|
||||
// if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
|
||||
// {
|
||||
// return loginUserToUserOnline(user);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 设置在线用户信息
|
||||
// *
|
||||
// * @param user 用户信息
|
||||
// * @return 在线用户
|
||||
// */
|
||||
// public SysUserOnline loginUserToUserOnline(LoginUser user)
|
||||
// {
|
||||
// if (StringUtils.isNull(user) && StringUtils.isNull(user.getUser()))
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// SysUserOnline sysUserOnline = new SysUserOnline();
|
||||
// sysUserOnline.setTokenId(user.getToken());
|
||||
// sysUserOnline.setUserName(user.getUsername());
|
||||
// sysUserOnline.setIpaddr(user.getIpaddr());
|
||||
// sysUserOnline.setLoginLocation(user.getLoginLocation());
|
||||
// sysUserOnline.setBrowser(user.getBrowser());
|
||||
// sysUserOnline.setOs(user.getOs());
|
||||
// sysUserOnline.setLoginTime(user.getLoginTime());
|
||||
// if (StringUtils.isNotNull(user.getUser().getDept()))
|
||||
// {
|
||||
// sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
|
||||
// }
|
||||
// return sysUserOnline;
|
||||
// }
|
||||
//}
|
||||
@@ -194,6 +194,7 @@ public class SysUserServiceImpl implements ISysUserService
|
||||
*
|
||||
* @param user 用户信息
|
||||
*/
|
||||
@Override
|
||||
public void checkUserAllowed(SysUser user)
|
||||
{
|
||||
if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
|
||||
@@ -270,10 +271,11 @@ public class SysUserServiceImpl implements ISysUserService
|
||||
/**
|
||||
* 修改用户头像
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param userName 用户名
|
||||
* @param avatar 头像地址
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public boolean updateUserAvatar(String userName, String avatar)
|
||||
{
|
||||
return userMapper.updateUserAvatar(userName, avatar) > 0;
|
||||
@@ -378,6 +380,7 @@ public class SysUserServiceImpl implements ISysUserService
|
||||
* @param userIds 需要删除的用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteUserByIds(Long[] userIds)
|
||||
{
|
||||
for (Long userId : userIds)
|
||||
|
||||
@@ -37,8 +37,8 @@ public class DictUtils
|
||||
Object cacheObj = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
|
||||
if (StringUtils.isNotNull(cacheObj))
|
||||
{
|
||||
List<SysDictData> DictDatas = StringUtils.cast(cacheObj);
|
||||
return DictDatas;
|
||||
List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
|
||||
return dictDatas;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="checkDeptNameUnique" resultMap="SysDeptResult">
|
||||
<include refid="selectDeptVo"/>
|
||||
where dept_name=#{deptName} and parent_id = #{parentId}
|
||||
where dept_name=#{deptName} and parent_id = #{parentId} limit 1
|
||||
</select>
|
||||
|
||||
<insert id="insertDept" parameterType="SysDept">
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
## 开发
|
||||
## 开发
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/y_project/RuoYi-Vue
|
||||
|
||||
# 进入项目目录
|
||||
# 进入项目目录
|
||||
cd ruoyi-ui
|
||||
|
||||
# 安装依赖
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
|
||||
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
|
||||
npm install --registry=https://registry.npm.taobao.org
|
||||
|
||||
# 启动服务
|
||||
# 启动服务
|
||||
npm run dev
|
||||
```
|
||||
|
||||
浏览器访问 http://localhost:80
|
||||
浏览器访问 http://localhost:80
|
||||
|
||||
## 发布
|
||||
## 发布
|
||||
|
||||
```bash
|
||||
# 构建测试环境
|
||||
# 构建测试环境
|
||||
npm run build:stage
|
||||
|
||||
# 构建生产环境
|
||||
# 构建生产环境
|
||||
npm run build:prod
|
||||
```
|
||||
@@ -1,5 +1,13 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
'env': {
|
||||
'development': {
|
||||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
||||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
||||
'plugins': ['dynamic-import-node']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "ruoyi",
|
||||
"version": "2.3.0",
|
||||
"version": "2.1.0",
|
||||
"description": "若依管理系统",
|
||||
"author": "若依",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve --open",
|
||||
"dev": "vue-cli-service serve",
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
@@ -43,10 +43,11 @@
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"axios": "0.18.1",
|
||||
"clipboard": "2.0.4",
|
||||
"core-js": "3.6.5",
|
||||
"echarts": "4.2.1",
|
||||
"element-ui": "2.13.0",
|
||||
"element-ui": "2.13.2",
|
||||
"file-saver": "2.0.1",
|
||||
"js-beautify": "^1.10.2",
|
||||
"js-beautify": "1.10.2",
|
||||
"fuse.js": "3.4.4",
|
||||
"js-cookie": "2.2.0",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
@@ -65,35 +66,31 @@
|
||||
"vuex": "3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.0.0",
|
||||
"@babel/register": "7.0.0",
|
||||
"@babel/parser": "^7.7.4",
|
||||
"@vue/cli-plugin-babel": "3.5.3",
|
||||
"@vue/cli-plugin-eslint": "^3.9.1",
|
||||
"@vue/cli-plugin-unit-jest": "3.5.3",
|
||||
"@vue/cli-service": "3.5.3",
|
||||
"@vue/cli-plugin-babel": "4.4.4",
|
||||
"@vue/cli-plugin-eslint": "4.4.4",
|
||||
"@vue/cli-plugin-unit-jest": "4.4.4",
|
||||
"@vue/cli-service": "4.4.4",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"autoprefixer": "^9.5.1",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.0.1",
|
||||
"autoprefixer": "9.5.1",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"chalk": "2.4.2",
|
||||
"chokidar": "2.1.5",
|
||||
"connect": "3.6.6",
|
||||
"eslint": "5.15.3",
|
||||
"eslint-plugin-vue": "5.2.2",
|
||||
"eslint": "6.7.2",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"http-proxy-middleware": "^0.19.1",
|
||||
"husky": "1.3.1",
|
||||
"lint-staged": "8.1.5",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"node-sass": "^4.9.0",
|
||||
"plop": "2.3.0",
|
||||
"runjs": "^4.3.2",
|
||||
"sass-loader": "^7.1.0",
|
||||
"runjs": "4.3.2",
|
||||
"sass": "1.26.10",
|
||||
"sass-loader": "8.0.2",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"script-loader": "0.7.2",
|
||||
"serve-static": "^1.13.2",
|
||||
"serve-static": "1.13.2",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.0",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
|
||||
@@ -2,11 +2,11 @@ import request from '@/utils/request'
|
||||
|
||||
const client_id = 'web'
|
||||
const client_secret = '123456'
|
||||
const grant_type = 'password'
|
||||
const scope = 'server'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, code, uuid) {
|
||||
const grant_type = 'password'
|
||||
return request({
|
||||
url: '/auth/oauth/token',
|
||||
method: 'post',
|
||||
@@ -14,6 +14,16 @@ export function login(username, password, code, uuid) {
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新方法
|
||||
export function refreshToken(refresh_token) {
|
||||
const grant_type = 'refresh_token'
|
||||
return request({
|
||||
url: '/auth/oauth/token',
|
||||
method: 'post',
|
||||
params: { client_id, client_secret, grant_type, scope, refresh_token }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询在线用户列表
|
||||
export function list(query) {
|
||||
return request({
|
||||
url: '/monitor/online/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 强退用户
|
||||
export function forceLogout(tokenId) {
|
||||
return request({
|
||||
url: '/monitor/online/' + tokenId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@@ -42,6 +42,7 @@ export function importTable(data) {
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 预览生成代码
|
||||
export function previewTable(tableId) {
|
||||
return request({
|
||||
@@ -49,6 +50,7 @@ export function previewTable(tableId) {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 删除表数据
|
||||
export function delTable(tableId) {
|
||||
return request({
|
||||
@@ -57,3 +59,10 @@ export function delTable(tableId) {
|
||||
})
|
||||
}
|
||||
|
||||
// 生成代码(自定义路径)
|
||||
export function genCode(tableName) {
|
||||
return request({
|
||||
url: '/code/gen/genCode/' + tableName,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -142,7 +142,28 @@
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
@@ -198,4 +219,8 @@
|
||||
opacity: .8;
|
||||
color: #fff!important;
|
||||
background: #42b983!important;
|
||||
}
|
||||
|
||||
.top-right-btn {
|
||||
float: right;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ export default {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
/deep/ .el-input__inner {
|
||||
::v-deep .el-input__inner {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding-left: 0;
|
||||
|
||||
@@ -94,7 +94,7 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.reload()
|
||||
location.href = '/index';
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user