初始化仓库

This commit is contained in:
huanghui 2024-01-31 14:19:24 +08:00
commit 2f813b3418
218 changed files with 15846 additions and 0 deletions

105
README.md Normal file
View File

@ -0,0 +1,105 @@
## 后端springboot
### 采用redis缓存
#### 1.pom.xml文件改动
- 1、增加redis依赖,删除exclusions即可
```xml
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-gaea</artifactId>
<version>2.0.5.RELEASE</version>
<!--删除下方内容-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</exclusion>
</exclusions>
<!--删除-->
</dependency>
```
- 2、 删除ehcache相关依赖
```xml
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
```
#### 2.删除代码
- 1、删除cache文件夹
目录地址com.anjiplus.template.gaea.business.cache
- 2、删除相关bean
文件地址com.anjiplus.template.gaea.business.config.BusinessAutoConfiguration.java
```java
@Bean
public CacheHelper gaeaCacheHelper(){
return new ReportCacheHelper();
}
@Bean
public EhCacheCache ehCacheCache() {
return (EhCacheCache) ehCacheCacheManager().getCache("reportCache");
}
/**
* 创建ehCacheCacheManager
*/
@Bean
public EhCacheCacheManager ehCacheCacheManager() {
return new EhCacheCacheManager();
}
```
底层的实现方式如下:
CacheHelper底层默认实现为RedisCacheHelper。
@ConditionalOnMissingBean 注解起到的作用
```java
package com.anji.plus.gaea;
@Configuration
@EnableConfigurationProperties({GaeaProperties.class})
public class GaeaAutoConfiguration {
@Bean
@ConditionalOnClass({RedisAutoConfiguration.class})
@ConditionalOnMissingBean
public CacheHelper cacheHelper() {
return new RedisCacheHelper();
}
}
```
#### 3.bootstrap.yml加上对应的redis配置
注意yml格式
```yaml
spring:
redis:
host: 10.108.x.x
port: 6379
password: ****
database: 1
timeout: 10000
pool:
max-active: 8
max-idle: 8
max-wait: -1
min-idle: 0
```
哨兵模式
```yaml
spring:
redis:
sentinel:
master: master01
nodes: 10.108.xx.xx:26379,10.108.xx.xx:26379,10.108.xx.xx:26379
database: 1
password: *******
timeout: 10000
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/kudu/libfb303-0.9.2.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

250
pom.xml Normal file
View File

@ -0,0 +1,250 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/>
</parent>
<name>BigData</name>
<modelVersion>4.0.0</modelVersion>
<groupId>com.BigData</groupId>
<artifactId>BigData</artifactId>
<version>1.0.1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<additionalparam>-Xdoclint:none</additionalparam>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-gaea</artifactId>
<version>2.0.5.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-starter-gaea-oss</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
</dependencies>
<developers>
<developer>
<name>develop.anji-plus.com</name>
<email>MS@anji-plus.com</email>
<url>https://github.com/anji-plus</url>
</developer>
</developers>
<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,62 @@
<assembly>
<id>assembly</id>
<formats>
<format>zip</format>
</formats>
<!-- <dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets> -->
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>lib/mssqlserver</directory>
<outputDirectory>lib</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>lib/kudu</directory>
<outputDirectory>lib</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>lib/oracle</directory>
<outputDirectory>lib</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>bootstrap.yml</include>
</includes>
</fileSet>
<fileSet>
<directory>target</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>aj-report-*.jar</include>
</includes>
<excludes>
<exclude>*-javadoc.jar</exclude>
<exclude>*-sources.jar</exclude>
</excludes>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>./../</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>LICENSE</include>
<include>NOTICE</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,5 @@
#!/bin/bash
cd `dirname $0`
./stop.sh
./start.sh

View File

@ -0,0 +1,42 @@
@echo off & setlocal enabledelayedexpansion
rem 判断cmd中是否有JAVA_HOME
rem set JAVA_HOME=D:\App\Java\jdk1.8.0_172
IF "%JAVA_HOME%" == "" (
goto END
) ELSE (
goto START
)
:END
rem cmd中未找到JAVA_HOME请在此启动文件中第4行指定然后尝试
echo Not JAVA_HOME Find, Please add JAVA_HOME in this file line 4
pause
exit
:START
rem 获取应用的根目录
cd ../
set BIN_DIR=%cd%
set CONF_YML=%BIN_DIR%\conf\bootstrap.yml
cd %BIN_DIR%\lib
rem 查找aj-report*.jar启动文件版本号每次会变
for /f "delims=" %%i in ('dir /a-d /b /on aj-report*.jar') do (
set BOOT_JAR=%%i
)
rem 查找附加的驱动加到java启动的classpath中
for %%i in ("*") do (
if "%%i" neq "%BOOT_JAR%" (
set LIB_JARS=!LIB_JARS!%BIN_DIR%\lib\%%i;
)
)
rem 启动内存设置,请根据自己需要调整
cd %BIN_DIR%\bin
set JAVA_OPTS= -server -Xms1g -Xmx2g -Xmn256m -XX:PermSize=128m -Xss256k
rem 正式启动
"%JAVA_HOME%"\bin\java %JAVA_OPTS% -Xbootclasspath/a:%LIB_JARS% -jar -Dspring.config.location=%CONF_YML% %BIN_DIR%\lib\%BOOT_JAR%
pause

View File

@ -0,0 +1,26 @@
#!/bin/bash
#判断java是否存在
command -v java >/dev/null 2>&1 || { echo >&2 "require java but it's not installed. Aborting."; sleep 5;exit 1; }
cd `dirname $0`
BIN_DIR=`pwd` #安装目录
cd ../
DEPLOY_DIR=`pwd`
LIB_DIR=$DEPLOY_DIR/lib #jar目录
CONF_DIR=$DEPLOY_DIR/conf #conf目录
LOGS_DIR=$DEPLOY_DIR/logs #log目录
LIB_JARS=`ls $LIB_DIR|grep -v aj-report|awk '{print "'$LIB_DIR'/"$0}'|tr "\n" ":"`
PIDS=`ps -f | grep java | grep "aj-report" |awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo "ERROR: The AJ-Report already started!"
echo "PID: $PIDS"
exit 1
fi
JAVA_OPTS=" -server -Xms1g -Xmx2g -Xmn256m -XX:PermSize=128m -Xss256k "
nohup java $JAVA_OPTS -Xbootclasspath/a:$LIB_JARS -jar -Dspring.config.location=$CONF_DIR/bootstrap.yml $LIB_DIR/aj-report-*.jar >/dev/null 2>&1 &
echo "AJ-Report 正在后台执行请查看aj-report.log日志(${DEPLOY_DIR}/logs/aj-report.log),确定软件运行情况"

View File

@ -0,0 +1,12 @@
#!/bin/bash
pid=`ps ax | grep -i 'aj-report' | grep java | grep -v grep | awk '{print $1}'`
if [ -z "$pid" ] ; then
echo "No AJ-Report Server running."
exit -1;
fi
kill -9 ${pid}
echo "Send shutdown request to aj-reporte(${pid}) OK"

View File

@ -0,0 +1,29 @@
package com.anjiplus.template.gaea.business;
import com.anji.plus.gaea.annotation.enabled.EnabledGaeaConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 业务模板
* @author lr
* @since 2021-02-03
*/
@EnabledGaeaConfiguration
@SpringBootApplication(scanBasePackages = {
"com.anjiplus.template.gaea",
"com.anji.plus"
})
@MapperScan(basePackages = {
"com.anjiplus.template.gaea.business.modules.*.dao",
"com.anjiplus.template.gaea.business.modules.*.**.dao",
"com.anji.plus.gaea.*.module.*.dao"
})
@EnableSwagger2
public class ReportApplication {
public static void main( String[] args ) {
SpringApplication.run(ReportApplication.class);
}
}

View File

@ -0,0 +1,25 @@
package com.anjiplus.template.gaea.business.base;
import org.springframework.context.i18n.LocaleContextHolder;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.dto.BaseDTO;
import com.anji.plus.gaea.curd.entity.BaseEntity;
import com.anji.plus.gaea.curd.params.PageParam;
/**
* 项目级的Controller公共处理基类
*
* @author WongBin
* @date 2021/3/26
*/
public abstract class BaseController<P extends PageParam, T extends BaseEntity, D extends BaseDTO>
extends GaeaBaseController<P,T,D> {
/**
* 获取当前语言类型
* @return
*/
public String getI18nLang(){
return LocaleContextHolder.getLocale().getLanguage();
}
}

View File

@ -0,0 +1,15 @@
package com.anjiplus.template.gaea.business.base;
import com.anji.plus.gaea.curd.entity.BaseEntity;
import com.anji.plus.gaea.curd.params.PageParam;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import org.springframework.context.i18n.LocaleContextHolder;
/**
* 项目级的Service公共处理基类
* @author WongBin
* @date 2021/3/26
*/
public interface BaseService<P extends PageParam, T extends BaseEntity> extends GaeaBaseService<P, T> {
}

View File

@ -0,0 +1,21 @@
package com.anjiplus.template.gaea.business.base;
import com.anji.plus.gaea.bean.ResponseBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc 用户管理 controller
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@RestController
public class HealthController {
@GetMapping("health")
public ResponseBean health() {
return ResponseBean.builder().build();
}
}

View File

@ -0,0 +1,150 @@
package com.anjiplus.template.gaea.business.cache;
import com.anji.plus.gaea.cache.CacheHelper;
import com.google.common.collect.Maps;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ReportCacheHelper implements CacheHelper, ApplicationContextAware {
@Autowired
private Cache cache;
@Override
public String stringGet(String key) {
Cache.ValueWrapper valueWrapper = cache.get(key);
if (valueWrapper != null) {
return (String) valueWrapper.get();
}
return CacheHelper.super.stringGet(key);
}
@Override
public Boolean setIfAbsent(String key, String value) {
cache.putIfAbsent(key, value);
return true;
}
@Override
public boolean exist(String key) {
String cacheHoldTime = stringGet(key + "_HoldTime");
if (cacheHoldTime != null && Long.parseLong(cacheHoldTime) > 0) {
if (Long.parseLong(cacheHoldTime) < System.currentTimeMillis()) {
delete(key + "_HoldTime");
delete(key);
return false;
}
}
return cache.get(key) != null;
}
@Override
public void stringSet(String key, String value) {
cache.put(key, value);
}
@Override
public String regKey(String key) {
return CacheHelper.super.regKey(key);
}
@Override
public void stringSetExpire(String key, String value, long seconds) {
stringSet(key, value);
if (seconds > 0) {
//缓存失效时间
stringSet(key + "_HoldTime", String.valueOf(System.currentTimeMillis() + seconds * 1000));
}
}
@Override
public Map<String, String> hashGet(String key) {
Cache.ValueWrapper t = cache.get(key);
if (t != null) {
return (Map<String, String>) t.get();
}
return Maps.newHashMap();
}
@Override
public String hashGetString(String key, String hashKey) {
Map<String, String> stringStringMap = hashGet(key);
return stringStringMap.get(hashKey);
}
@Override
public void hashDel(String key, String hashKey) {
Map<String, String> stringStringMap = hashGet(key);
stringStringMap.remove(hashKey);
}
@Override
public void hashBatchDel(String key, Set<String> hashKeys) {
Map<String, String> stringStringMap = hashGet(key);
hashKeys.forEach(stringStringMap::remove);
}
@Override
public boolean hashExist(String key, String hashKey) {
if (exist(key)) {
Map<String, String> map = hashGet(key);
return map.containsKey(hashKey);
}
return false;
}
@Override
public boolean hashAnyExist(String key, String[] hashKeys) {
return CacheHelper.super.hashAnyExist(key, hashKeys);
}
@Override
public void hashSet(String key, String hashKey, String hashValue) {
Map<String, String> map;
if (exist(key)) {
map = hashGet(key);
} else {
map = new HashMap<>();
}
map.put(hashKey, hashValue);
hashSet(key, map);
}
@Override
public void hashSet(String key, Map<String, String> hash) {
cache.put(key, hash);
}
@Override
public boolean delete(String key) {
if (exist(key)) {
cache.evict(key);
}
return true;
}
@Override
public boolean delete(List<String> keys) {
keys.forEach(this::delete);
return true;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
/*基于内存的本地缓存*/
cache = (Cache) applicationContext.getBean("ehCacheCache");
}
}

View File

@ -0,0 +1,139 @@
package com.anjiplus.template.gaea.business.code;
/**
* 响应码
* @author lr
* @since 2021-02-22
*/
public interface ResponseCode {
String NOT_NULL = "field.not.null";
String NOT_EMPTY = "field.not.empty";
String MIN = "field.min";
String MAX = "field.max";
String DICT_ERROR = "field.dict.error";
String USER_PASSWORD_ERROR = "User.password.error";
/**
* 用户名或者密码不正确
*/
String LOGIN_ERROR = "login.error";
/**
* 新密码不能和原密码一致
*/
String USER_PASSWORD_CONFIG_PASSWORD_CANOT_EQUAL = "user.password.config.password.canot.equal";
/**
* 密码和确认密码不一致
*/
String USER_INCONSISTENT_PASSWORD_ERROR = "user.inconsistent.password.error";
/**
* 旧密码不正确
*/
String USER_OLD_PASSWORD_ERROR = "user.old.password.error";
/**
* 用户token过期
*/
String USER_TOKEN_EXPIRED = "User.token.expired";
/**
* 字典项重复
*/
String DICT_ITEM_REPEAT = "Dict.item.code.exist";
/**
* 数字字典国际化标识不能为null
*/
String DICT_CODE_LOCALE_NULL = "500-00002";
/**
* 参数为空
*/
String PARAM_IS_NULL = "Rule.execute.param.null";
/**
* 规则编译不通过
*/
String RULE_CONTENT_COMPILE_ERROR = "Rule.content.compile.error";
/**
* 规则执行不通过
*/
String RULE_CONTENT_EXECUTE_ERROR = "Rule.content.execute.error";
/**
* 规则编码已存在
*/
String RULE_CODE_EXIST = "Rule.code.exist";
/**
* 对应规则内容不存在
*/
String RULE_CONTENT_NOT_EXIST = "Rule.content.not.exist";
/**
* 对应规则字段值不存在
*/
String RULE_FIELDS_NOT_EXIST = "Rule.fields.not.exist";
/**
* 规则字段必填
*/
String RULE_FIELD_VALUE_IS_REQUIRED = "Rule.field.value.is.required";
/**
* 规则字段值类型错误
*/
String RULE_FIELD_VALUE_TYPE_ERROR = "Rule.field.value.type.error";
/**
* 规则参数校验不通过
*/
String RULE_FIELDS_CHECK_ERROR = "Rule.fields.check.error";
/**
* 组件未加载
*/
String COMPONENT_NOT_LOAD = "Component.load.check.error";
String AUTH_PASSWORD_NOTSAME = "1001";
String OLD_PASSWORD_ERROR = "1003";
String USER_ONTEXIST_ORGINFO = "1004";
String USER_ONTEXIST_ROLEINFO = "1005";
String MENU_TABLE_CODE_EXIST = "1006";
String USER_CODE_ISEXIST = "1007";
String ROLE_CODE_ISEXIST = "1008";
String MENU_CODE_ISEXIST = "1009";
String ORG_CODE_ISEXIST = "1010";
String SEARCHNAME_ISEXIST = "1011";
String SETTINGNAME_ISEXIST = "1012";
String DICCODE_ISEXIST = "1013";
String DEVICEID_LENGTH = "1014";
String USERINFO_EMPTY = "1015";
String FILE_EMPTY_FILENAME = "2001";
String FILE_SUFFIX_UNSUPPORTED = "2002";
String FILE_UPLOAD_ERROR = "2003";
String FILE_ONT_EXSIT = "2004";
String FILE_OPERATION_FAILED = "file.operation.failed";
String PUSHCODE_NEED_UNIQUE = "3001";
String RECEIVER_IS_EMPTY = "3002";
String DATA_SOURCE_CONNECTION_FAILED = "4001";
String DATA_SOURCE_TYPE_DOES_NOT_MATCH_TEMPORARILY = "4002";
String EXECUTE_SQL_ERROR = "4003";
String INCOMPLETE_PARAMETER_REPLACEMENT_VALUES = "4004";
String EXECUTE_JS_ERROR = "4005";
String ANALYSIS_DATA_ERROR = "4006";
String REPORT_CODE_ISEXIST = "4007";
String SET_CODE_ISEXIST = "4008";
String SOURCE_CODE_ISEXIST = "4009";
String CLASS_NOT_FOUND = "4010";
String EXECUTE_GROOVY_ERROR = "4011";
String REPORT_SHARE_LINK_INVALID = "report.share.link.invalid";
}

View File

@ -0,0 +1,51 @@
package com.anjiplus.template.gaea.business.config;
import com.anji.plus.gaea.cache.CacheHelper;
import com.anjiplus.template.gaea.business.cache.ReportCacheHelper;
import com.anjiplus.template.gaea.business.runner.ApplicationInitRunner;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.cache.ehcache.EhCacheCache;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* business配置类
* @author lr
* @since 2021-04-08
*/
@Configuration
@MapperScan(basePackages = {
"com.anjiplus.template.gaea.business.modules.*.dao",
"com.anjiplus.template.gaea.business.modules.*.**.dao"
})
public class BusinessAutoConfiguration {
/**
* 系统启动完执行
* @return
*/
@Bean
public ApplicationInitRunner applicationInitRunner() {
return new ApplicationInitRunner();
}
@Bean
public CacheHelper gaeaCacheHelper(){
return new ReportCacheHelper();
}
@Bean
public EhCacheCache ehCacheCache() {
return (EhCacheCache) ehCacheCacheManager().getCache("reportCache");
}
/**
* 创建ehCacheCacheManager
*/
@Bean
public EhCacheCacheManager ehCacheCacheManager() {
return new EhCacheCacheManager();
}
}

View File

@ -0,0 +1,56 @@
package com.anjiplus.template.gaea.business.config;
import com.zaxxer.hikari.HikariDataSource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Created by raodeming on 2021/7/5.
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = {"spring.flyway.enabled"})
public class DatabaseInitializer {
private final FlywayProperties flywayProperties;
private final DataSourceProperties dataSourceProperties;
@PostConstruct
public void init() throws SQLException {
log.info("DatabaseInitializer uses flyway init-sqls to initiate database");
String url = dataSourceProperties.getUrl();
// jdbc url最后一个 '/' 用于分割具体 schema?参数
int lastSplitIndex = url.lastIndexOf('?');
// 获取spring.datasource.url具体数据库schema前的jdbc url
String addressUrl = url.substring(0, lastSplitIndex);
String addresslast = url.substring(lastSplitIndex);
addressUrl = addressUrl.substring(0, addressUrl.lastIndexOf("/"));
// 直连数据库地址:jdbc:mysql://yourIp:port
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(addressUrl.concat(addresslast));
dataSource.setUsername(dataSourceProperties.getUsername());
dataSource.setPassword(dataSourceProperties.getPassword());
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
for (String sql : flywayProperties.getInitSqls()) {
// 通过flyway的init-sqls配置进行建库与数据库配置
// executeUpdate:执行给定的SQL语句该语句可以是INSERTUPDATE或DELETE语句或不返回任何内容的SQL语句例如SQL DDL语句
statement.executeUpdate(sql);
}
statement.close();
connection.close();
dataSource.close();
log.info("DatabaseInitializer initialize completed");
}
}

View File

@ -0,0 +1,34 @@
package com.anjiplus.template.gaea.business.config;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.pool.HikariPool;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Created by raodeming on 2021/8/6.
*/
@Component
@ConfigurationProperties(prefix = "spring.datasource.hikari")
@Data
public class HikariPoolProperties extends HikariConfig {
public HikariPool dataSource(String url, String username, String password, String driverClassName) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setConnectionTimeout(getConnectionTimeout());
hikariConfig.setValidationTimeout(getValidationTimeout());
hikariConfig.setIdleTimeout(getIdleTimeout());
hikariConfig.setMaxLifetime(getMaxLifetime());
hikariConfig.setMaximumPoolSize(getMaximumPoolSize());
hikariConfig.setMinimumIdle(getMinimumIdle());
HikariPool hikariPool = new HikariPool(hikariConfig);
return hikariPool;
}
}

View File

@ -0,0 +1,39 @@
package com.anjiplus.template.gaea.business.constant;
/**
* 常量
* @author lr
* @since 2021-03-26
*/
public interface BusinessConstant {
String LEFT_BIG_BOAST = "{";
String RIGTH_BIG_BOAST = "}";
String LEFT_MIDDLE_BOAST = "[";
String RIGHT_MIDDLE_BOAST = "]";
String SLASH = "/";
String USER_GUEST = "guest";
String USER_ADMIN = "admin";
/**
* 字典项重复
*/
String DICT_ITEM_EXIST_GROUP = "dictItemExist";
/**
* 所有url的权限码缓存key
*/
String GAEA_SECURITY_AUTHORITIES= "gaea:security:authorities:all";
/**
* 用户登录的token缓存key
*/
String GAEA_SECURITY_LOGIN_TOKEN = "gaea:security:login:token:%s";
/**
* 用户登录的主信息缓存信息
*/
String GAEA_SECURITY_LOGIN_USER = "gaea:security:login:user:%s";
}

View File

@ -0,0 +1,47 @@
package com.anjiplus.template.gaea.business.enums;
public enum DeleteFlagEnum {
DELETED(1,"已删除"),
UNDELETED(0,"未删除"),
;
private int codeValue;
private String codeDesc;
private DeleteFlagEnum(int codeValue, String codeDesc) {
this.codeValue = codeValue;
this.codeDesc = codeDesc;
}
public int getCodeValue(){ return this.codeValue;}
public String getCodeDesc(){ return this.codeDesc;}
//根据codeValue获取枚举
public static DeleteFlagEnum parseFromCodeValue(int codeValue){
for (DeleteFlagEnum e : DeleteFlagEnum.values()){
if(e.codeValue == codeValue){ return e;}
}
return null;
}
//根据codeValue获取描述
public static String getCodeDescByCodeValue(int codeValue){
DeleteFlagEnum enumItem = parseFromCodeValue(codeValue);
return enumItem == null ? "" : enumItem.getCodeDesc();
}
//验证codeValue是否有效
public static boolean validateCodeValue(int codeValue){ return parseFromCodeValue(codeValue)!=null;}
//列出所有值字符串
public static String getString(){
StringBuffer buffer = new StringBuffer();
for (DeleteFlagEnum e : DeleteFlagEnum.values()){
buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
}
buffer.deleteCharAt(buffer.lastIndexOf(","));
return buffer.toString().trim();
}
}

View File

@ -0,0 +1,47 @@
package com.anjiplus.template.gaea.business.enums;
public enum EnableFlagEnum {
ENABLE(1,"启用"),
DISABLE(0,"禁用"),
;
private int codeValue;
private String codeDesc;
private EnableFlagEnum(int codeValue, String codeDesc) {
this.codeValue = codeValue;
this.codeDesc = codeDesc;
}
public int getCodeValue(){ return this.codeValue;}
public String getCodeDesc(){ return this.codeDesc;}
//根据codeValue获取枚举
public static EnableFlagEnum parseFromCodeValue(int codeValue){
for (EnableFlagEnum e : EnableFlagEnum.values()){
if(e.codeValue == codeValue){ return e;}
}
return null;
}
//根据codeValue获取描述
public static String getCodeDescByCodeBalue(int codeValue){
EnableFlagEnum enumItem = parseFromCodeValue(codeValue);
return enumItem == null ? "" : enumItem.getCodeDesc();
}
//验证codeValue是否有效
public static boolean validateCodeValue(int codeValue){ return parseFromCodeValue(codeValue)!=null;}
//列出所有值字符串
public static String getString(){
StringBuffer buffer = new StringBuffer();
for (EnableFlagEnum e : EnableFlagEnum.values()){
buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
}
buffer.deleteCharAt(buffer.lastIndexOf(","));
return buffer.toString().trim();
}
}

View File

@ -0,0 +1,73 @@
package com.anjiplus.template.gaea.business.enums;
/**
* @author zhouhang
* @description EXCEL居中方式
* @date 2021/4/26
*/
public enum ExcelCenterStyleEnum {
/**
* 左对齐
*/
LEFT((short) 1, 1, "左对齐"),
/**
* 右对齐
*/
RIGHT((short) 3, 2, "右对齐"),
/**
* 居中
*/
CENTER((short) 2, 0, "居中"),
;
/**
* excel居中code
*/
private final short excelCode;
/**
* 在线文档居中code
*/
private final Integer onlineExcelCode;
/**
* 名称
*/
private final String name;
public Integer getOnlineExcelCode() {
return onlineExcelCode;
}
public String getName() {
return name;
}
public short getExcelCode() {
return excelCode;
}
ExcelCenterStyleEnum(short excelCode, Integer onlineExcelCode, String name) {
this.excelCode = excelCode;
this.onlineExcelCode = onlineExcelCode;
this.name = name;
}
/**
* @param code excel居中样式code
* @return Enum_ExcelCenterStyle
* @description 根据excel居中样式获取在线文档居中样式
* @author zhouhang
* @date 2021/4/26
*/
public static ExcelCenterStyleEnum getExcelCenterStyleByExcelCenterCode(short code) {
for (ExcelCenterStyleEnum value : ExcelCenterStyleEnum.values()) {
if (code == value.getExcelCode()) {
return value;
}
}
return CENTER;
}
}

View File

@ -0,0 +1,30 @@
package com.anjiplus.template.gaea.business.enums;
/**
* Created by raodeming on 2021/9/3.
*/
public enum ExportTypeEnum {
/**gaea_excel*/
GAEA_TEMPLATE_EXCEL("gaea_template_excel", "gaea_template_excel"),
/**gaea_pdf*/
GAEA_TEMPLATE_PDF("gaea_template_pdf", "gaea_template_pdf"),
;
private String codeValue;
private String codeDesc;
private ExportTypeEnum(String codeValue, String codeDesc) {
this.codeValue = codeValue;
this.codeDesc = codeDesc;
}
public String getCodeValue() {
return this.codeValue;
}
public String getCodeDesc() {
return this.codeDesc;
}
}

View File

@ -0,0 +1,33 @@
package com.anjiplus.template.gaea.business.enums;
/**
* Created by raodeming on 2022/5/8.
*/
public enum ReportTypeEnum {
/**report_screen*/
report_screen("report_screen", "大屏报表"),
/**report_excel*/
report_excel("report_excel", "excel报表"),
;
private String codeValue;
private String codeDesc;
ReportTypeEnum() {
}
private ReportTypeEnum(String codeValue, String codeDesc) {
this.codeValue = codeValue;
this.codeDesc = codeDesc;
}
public String getCodeValue() {
return this.codeValue;
}
public String getCodeDesc() {
return this.codeDesc;
}
}

View File

@ -0,0 +1,56 @@
package com.anjiplus.template.gaea.business.enums;
public enum SetTypeEnum {
SQL("sql", "sql"),
HTTP("http", "http"),
;
private String codeValue;
private String codeDesc;
private SetTypeEnum(String codeValue, String codeDesc) {
this.codeValue = codeValue;
this.codeDesc = codeDesc;
}
public String getCodeValue() {
return this.codeValue;
}
public String getCodeDesc() {
return this.codeDesc;
}
//根据codeValue获取枚举
public static SetTypeEnum parseFromCodeValue(String codeValue) {
for (SetTypeEnum e : SetTypeEnum.values()) {
if (e.codeValue == codeValue) {
return e;
}
}
return null;
}
//根据codeValue获取描述
public static String getCodeDescByCodeBalue(String codeValue) {
SetTypeEnum enumItem = parseFromCodeValue(codeValue);
return enumItem == null ? "" : enumItem.getCodeDesc();
}
//验证codeValue是否有效
public static boolean validateCodeValue(String codeValue) {
return parseFromCodeValue(codeValue) != null;
}
//列出所有值字符串
public static String getString() {
StringBuffer buffer = new StringBuffer();
for (SetTypeEnum e : SetTypeEnum.values()) {
buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
}
buffer.deleteCharAt(buffer.lastIndexOf(","));
return buffer.toString().trim();
}
}

View File

@ -0,0 +1,43 @@
package com.anjiplus.template.gaea.business.filter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by raodeming on 2021/6/24.
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// 设置允许Cookie
res.addHeader("Access-Control-Allow-Credentials", "true");
// 允许http://www.xxx.com域自行设置这里只做示例发起跨域请求
res.addHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
// 设置允许跨域请求的方法
res.addHeader("Access-Control-Allow-Methods", "*");
// 允许跨域请求包含content-type
res.addHeader("Access-Control-Allow-Headers", "*");
res.addHeader("Access-Control-Expose-Headers", "*");
chain.doFilter(req, res);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}

View File

@ -0,0 +1,245 @@
package com.anjiplus.template.gaea.business.filter;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.cache.CacheHelper;
import com.anji.plus.gaea.constant.GaeaConstant;
import com.anji.plus.gaea.utils.JwtBean;
import com.anjiplus.template.gaea.business.constant.BusinessConstant;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.GaeaUserDto;
import com.anjiplus.template.gaea.business.util.JwtUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import static com.anji.plus.gaea.constant.GaeaConstant.URL_REPLACEMENT;
/**
* 简单的鉴权
* @author raodeming
* @date 2021/6/24.
*/
@Component
@Order(Integer.MIN_VALUE + 99)
public class TokenFilter implements Filter {
private static final Pattern PATTERN = Pattern.compile(".*().*");
@Value("${server.servlet.context-path:/}")
private String SLASH = "/";
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
private CacheHelper cacheHelper;
@Autowired
private JwtBean jwtBean;
/**
* 跳过token验证和权限验证的url清单
*/
@Value("#{'${customer.skip-authenticate-urls:}'.split(',')}")
private List<String> skipAuthenticateUrls;
private Pattern skipAuthenticatePattern;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 生成匹配正则跳过token验证和权限验证的url
skipAuthenticatePattern = fitByList(skipAuthenticateUrls);
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String uri = request.getRequestURI();
// TODO 暂时先不校验 直接放行
/*if (true) {
filterChain.doFilter(request, response);
return;
}*/
//OPTIONS直接放行
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
filterChain.doFilter(request, response);
return;
}
// swagger相关的直接放行
if (uri.contains("swagger-ui") || uri.contains("swagger-resources")) {
filterChain.doFilter(request, response);
return;
}
if (SLASH.equals(uri) || SLASH.concat(BusinessConstant.SLASH).equals(uri)) {
if (BusinessConstant.SLASH.equals(uri)) {
response.sendRedirect("/index.html");
return;
}
response.sendRedirect(SLASH + "/index.html");
return;
}
// 不需要token验证和权限验证的url直接放行
boolean skipAuthenticate = skipAuthenticatePattern.matcher(uri).matches();
if (skipAuthenticate) {
filterChain.doFilter(request, response);
return;
}
//获取token
String token = request.getHeader("Authorization");
//针对大屏分享优先处理
String shareToken = request.getHeader("Share-Token");
if (StringUtils.isNotBlank(shareToken) && StringUtils.isBlank(token)) {
//需要处理
// /reportDashboard/getData
// /reportDashboard/{reportCode}
// /reportExcel/preview
List<String> reportCodeList = JwtUtil.getReportCodeList(shareToken);
if (!uri.endsWith("/reportDashboard/getData") && !uri.endsWith("/reportExcel/preview") && reportCodeList.stream().noneMatch(uri::contains)) {
ResponseBean responseBean = ResponseBean.builder().code("50014")
.message("分享链接已过期").build();
response.getWriter().print(JSONObject.toJSONString(responseBean));
return;
}
filterChain.doFilter(request, response);
return;
}
if (StringUtils.isBlank(token)) {
error(response);
return;
}
// 判断token是否过期
String loginName = jwtBean.getUsername(token);
String tokenKey = String.format(BusinessConstant.GAEA_SECURITY_LOGIN_TOKEN, loginName);
String userKey = String.format(BusinessConstant.GAEA_SECURITY_LOGIN_USER, loginName);
if (!cacheHelper.exist(tokenKey)) {
error(response);
return;
}
String gaeaUserJsonStr = cacheHelper.stringGet(userKey);
// 判断用户是否有该url的权限
if (!BusinessConstant.USER_ADMIN.equals(loginName)) {
AtomicBoolean authorizeFlag = authorize(request, gaeaUserJsonStr);
if (!authorizeFlag.get()) {
authError(response);//无权限
return;
}
}
// 延长有效期
cacheHelper.stringSetExpire(tokenKey, token, 3600);
cacheHelper.stringSetExpire(userKey, gaeaUserJsonStr, 3600);
//执行
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
Filter.super.destroy();
}
/**
* 根据名单生成正则
*
* @param skipUrlList
* @return
*/
private Pattern fitByList(List<String> skipUrlList) {
if (skipUrlList == null || skipUrlList.size() == 0) {
return PATTERN;
}
StringBuffer patternString = new StringBuffer();
patternString.append(".*(");
skipUrlList.stream().forEach(url -> {
patternString.append(url.trim());
patternString.append("|");
});
if (skipUrlList.size() > 0) {
patternString.deleteCharAt(patternString.length() - 1);
}
patternString.append(").*");
return Pattern.compile(patternString.toString());
}
/** 判断用户是否有该接口的权限
* @return
*/
private AtomicBoolean authorize(HttpServletRequest request, String gaeaUserJsonStr){
//判断接口权限
//请求路径
String requestUrl = request.getRequestURI();
if (!BusinessConstant.SLASH.equals(SLASH)) {
requestUrl = requestUrl.substring(SLASH.length());
}
String methodValue = request.getMethod();
//请求方法+#+请求路径
String path = methodValue + GaeaConstant.URL_SPLIT + requestUrl;
GaeaUserDto gaeaUserDto = JSONObject.parseObject(gaeaUserJsonStr, GaeaUserDto.class);
List<String> userAuthorities = gaeaUserDto.getAuthorities();
Map<String, String> authoritiesAllMap = cacheHelper.hashGet(BusinessConstant.GAEA_SECURITY_AUTHORITIES);
AtomicBoolean authFlag = new AtomicBoolean(false);
// 接口GET#/gaeaDictItem/pageList
if(authoritiesAllMap.containsKey(path)){
String permissionCode = authoritiesAllMap.get(path);
boolean flag = userAuthorities.contains(permissionCode);
authFlag.set(flag);
return authFlag;
}
// 接口GET#/accessUser/roleTree/**
Optional<String> optionalMatchKey = authoritiesAllMap.keySet().stream()
.filter(key -> StringUtils.isNotBlank(key) && key.contains(URL_REPLACEMENT))
.filter(key -> antPathMatcher.match(key, path)).findFirst();
if(optionalMatchKey.isPresent() == false){
authFlag.set(true);
return authFlag;
}
String authoritieKey = optionalMatchKey.get();
String needPermission = authoritiesAllMap.get(authoritieKey);
boolean flag = userAuthorities.contains(needPermission);
authFlag.set(flag);
return authFlag;
}
private void error(HttpServletResponse response) throws IOException {
ResponseBean responseBean = ResponseBean.builder().code("User.credentials.expired").message("The Token has expired").build();
response.setContentType(ContentType.APPLICATION_JSON.getMimeType());
response.getWriter().print(JSONObject.toJSONString(responseBean));
}
private void authError(HttpServletResponse response) throws IOException {
ResponseBean responseBean = ResponseBean.builder().code("User.no.authority").message("no auth").build();
response.setContentType(ContentType.APPLICATION_JSON.getMimeType());
response.getWriter().print(JSONObject.toJSONString(responseBean));
}
}

View File

@ -0,0 +1,77 @@
package com.anjiplus.template.gaea.business.filter;
import com.anji.plus.gaea.constant.GaeaConstant;
import org.apache.catalina.util.ParameterMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.ognl.IteratorEnumeration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
/**
* @author: Raod
* @since: 2022-01-26
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
public class UrlDecodeFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
ParameterMap<String, String[]> parameterMap = (ParameterMap) httpServletRequest.getParameterMap();
ParamHttpServletRequestWrapper wrapper = new ParamHttpServletRequestWrapper(httpServletRequest, parameterMap);
Enumeration<String> parameterNames = wrapper.getParameterNames();
while (parameterNames.hasMoreElements()) {
String paramName = parameterNames.nextElement();
String parameter = httpServletRequest.getParameter(paramName);
if (StringUtils.isNotBlank(parameter)) {
String decode = URLDecoder.decode(parameter, GaeaConstant.CHARSET_UTF8);
parameterMap.setLocked(false);
parameterMap.put(paramName, new String[]{decode});
}
}
filterChain.doFilter(wrapper, servletResponse);
}
/**
* 参数
*/
class ParamHttpServletRequestWrapper extends HttpServletRequestWrapper {
private ParameterMap<String, String[]> parameterMap;
public ParamHttpServletRequestWrapper(HttpServletRequest request, ParameterMap<String, String[]> parameterMap) {
super(request);
this.parameterMap = parameterMap;
}
@Override
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
@Override
public Enumeration<String> getParameterNames() {
Set<String> keySet = parameterMap.keySet();
IteratorEnumeration iteratorEnumeration = new IteratorEnumeration(keySet.iterator());
return iteratorEnumeration;
}
@Override
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}
}
}

View File

@ -0,0 +1,67 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.controller;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.annotation.AccessKey;
import com.anji.plus.gaea.bean.KeyValue;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.anji.plus.gaea.utils.GaeaUtils;
import com.anjiplus.template.gaea.business.modules.accessauthority.dao.entity.AccessAuthority;
import com.anjiplus.template.gaea.business.modules.accessauthority.service.AccessAuthorityService;
import com.anjiplus.template.gaea.business.modules.accessauthority.controller.dto.AccessAuthorityDto;
import com.anjiplus.template.gaea.business.modules.accessauthority.controller.param.AccessAuthorityParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* @desc 权限管理 controller
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@RestController
@Api(tags = "权限管理管理")
@RequestMapping("/accessAuthority")
@Permission(code = "authorityManage", name = "权限管理")
public class AccessAuthorityController extends GaeaBaseController<AccessAuthorityParam, AccessAuthority, AccessAuthorityDto> {
@Autowired
private AccessAuthorityService accessAuthorityService;
@Override
public GaeaBaseService<AccessAuthorityParam, AccessAuthority> getService() {
return accessAuthorityService;
}
@Override
public AccessAuthority getEntity() {
return new AccessAuthority();
}
@Override
public AccessAuthorityDto getDTO() {
return new AccessAuthorityDto();
}
/**
* 获取一二级菜单
* @return
*/
@Permission( code = "query", name = "查询")
@GetMapping("/menuTree")
public ResponseBean menuTree(){
String username = UserContentHolder.getContext().getUsername();
List<TreeNode> parentTreeList = accessAuthorityService.getAuthorityTree(username, false);
return responseSuccessWithData(parentTreeList);
}
}

View File

@ -0,0 +1,58 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.controller.dto;
import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import io.swagger.annotations.ApiModelProperty;
import com.anji.plus.gaea.annotation.Formatter;
import lombok.Data;
/**
*
* @description 权限管理 dto
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@Data
public class AccessAuthorityDto extends GaeaBaseDTO implements Serializable {
/** 父菜单代码 */
@ApiModelProperty(value = "父菜单代码")
private String parentTarget;
/** 目标菜单 */
@ApiModelProperty(value = "菜单代码")
@NotEmpty(message = "6002")
private String target;
/** 目标菜单名称 */
@ApiModelProperty(value = "菜单名称")
@NotEmpty(message = "6002")
private String targetName;
/** 目标按钮 */
@ApiModelProperty(value = "按钮代码")
@NotEmpty(message = "6002")
private String action;
/** 目标按钮名称 */
@ApiModelProperty(value = "按钮名称")
@NotEmpty(message = "6002")
private String actionName;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
@ApiModelProperty(value = " 0--未删除 1--已删除 DIC_NAME=DEL_FLAG")
private Integer deleteFlag;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
@NotNull(message = "6002")
private Integer enableFlag;
@ApiModelProperty(value = "sort")
private Integer sort;
}

View File

@ -0,0 +1,44 @@
/**/
package com.anjiplus.template.gaea.business.modules.accessauthority.controller.param;
import lombok.Data;
import java.io.Serializable;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import java.util.List;
import java.util.Date;
/**
* @desc AccessAuthority 权限管理查询输入类
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@Data
public class AccessAuthorityParam extends PageParam implements Serializable{
/** 父菜单代码 */
@Query(value = QueryEnum.LIKE)
private String parentTarget;
/** 菜单代码 */
@Query(value = QueryEnum.LIKE)
private String target;
/** 菜单名称 */
@Query(value = QueryEnum.LIKE)
private String targetName;
/** 按钮代码 */
@Query(value = QueryEnum.LIKE)
private String action;
/** 按钮名称 */
@Query(value = QueryEnum.LIKE)
private String actionName;
// 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG
@Query
private Integer enableFlag;
}

View File

@ -0,0 +1,17 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.accessauthority.dao.entity.AccessAuthority;
import java.util.List;
/**
* AccessAuthority Mapper
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@Mapper
public interface AccessAuthorityMapper extends GaeaBaseMapper<AccessAuthority> {
}

View File

@ -0,0 +1,43 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.dao.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import javax.validation.constraints.*;
import java.util.Date;
/**
* @description 权限管理 entity
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@TableName(keepGlobalPrefix=true, value="access_authority")
@Data
public class AccessAuthority extends GaeaBaseEntity {
/** 父菜单代码 */
private String parentTarget;
/** 菜单代码 */
private String target;
/** 菜单名称 */
private String targetName;
/** 按钮代码 */
private String action;
/** 按钮名称 */
private String actionName;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
private Integer deleteFlag;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
private Integer sort;
}

View File

@ -0,0 +1,29 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.service;
import com.anji.plus.gaea.bean.TreeNode;
import com.anjiplus.template.gaea.business.modules.accessauthority.dao.entity.AccessAuthority;
import com.anjiplus.template.gaea.business.modules.accessauthority.controller.param.AccessAuthorityParam;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import java.util.List;
/**
* @desc AccessAuthority 权限管理服务接口
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
public interface AccessAuthorityService extends GaeaBaseService<AccessAuthorityParam, AccessAuthority> {
/**
* @param loginName 当前登录的用户名
* @param withActionNode 带第三层的按钮节点
* @return
*/
List<TreeNode> getAuthorityTree(String loginName, boolean withActionNode);
/**
* 扫描所有mvc url的需要权限码建立拦截体系
*/
void scanGaeaSecurityAuthorities();
}

View File

@ -0,0 +1,140 @@
package com.anjiplus.template.gaea.business.modules.accessauthority.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.cache.CacheHelper;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.init.InitRequestUrlMappings;
import com.anjiplus.template.gaea.business.constant.BusinessConstant;
import com.anjiplus.template.gaea.business.modules.accessauthority.dao.entity.AccessAuthority;
import com.anjiplus.template.gaea.business.modules.accessauthority.service.AccessAuthorityService;
import com.anjiplus.template.gaea.business.modules.accessauthority.dao.AccessAuthorityMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @desc AccessAuthority 权限管理服务实现
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:10.009
**/
@Service
public class AccessAuthorityServiceImpl implements AccessAuthorityService {
@Autowired
private InitRequestUrlMappings initRequestUrlMappings;
@Autowired
private CacheHelper cacheHelper;
@Autowired
private AccessAuthorityMapper accessAuthorityMapper;
@Override
public GaeaBaseMapper<AccessAuthority> getMapper() {
return accessAuthorityMapper;
}
@Override
public List<TreeNode> getAuthorityTree(String loginName, boolean withActionNode) {
// 查询出所有的菜单记录
LambdaQueryWrapper<AccessAuthority> wrapper = Wrappers.lambdaQuery();
wrapper.select(AccessAuthority::getParentTarget, AccessAuthority::getTarget, AccessAuthority::getTargetName, AccessAuthority::getAction, AccessAuthority::getActionName)
.eq(AccessAuthority::getEnableFlag, 1)
.eq(AccessAuthority::getDeleteFlag, 0)
.orderByAsc(AccessAuthority::getSort);
// 按operator去筛选 后面再加where
List<AccessAuthority> accessAuthorityList = getMapper().selectList(wrapper);
// 筛选出一级菜单
List<TreeNode> parentNodes = accessAuthorityList.stream().filter(accessAuthority -> StringUtils.isBlank(accessAuthority.getParentTarget()))
.map(item -> {
TreeNode treeNode = new TreeNode();
treeNode.setId(item.getTarget());
treeNode.setLabel(item.getTargetName());
return treeNode;
}).collect(Collectors.toList());
// 菜单-按钮的map
Map<String, List<AccessAuthority>> targetActionsMap = accessAuthorityList.stream()
.filter(accessAuthority -> StringUtils.isNoneBlank(accessAuthority.getParentTarget()))
.collect(Collectors.groupingBy(AccessAuthority::getTarget));
// 设置每个一级菜单的二菜单
parentNodes.stream().forEach(parentNode -> {
List<String> alreadyTargets = new ArrayList<>();
accessAuthorityList.stream().forEach(authority -> {
if(!StringUtils.equals(parentNode.getId(), authority.getParentTarget()) || alreadyTargets.contains(authority.getTarget())){
return;
}
// 找到一级菜单对应的二级菜单
// 初始化二级菜单节点
TreeNode levelTwoMenuNode = new TreeNode();
levelTwoMenuNode.setId(authority.getTarget());
levelTwoMenuNode.setLabel(authority.getTargetName());
levelTwoMenuNode.setChildren(new ArrayList<TreeNode>());
// 初始化二级菜单的按钮
if(withActionNode){
List<AccessAuthority> actionList = targetActionsMap.get(authority.getTarget());
if(actionList != null && !actionList.isEmpty()){
actionList.stream().forEach(action ->{
TreeNode buttonNode = new TreeNode();
buttonNode.setId(String.format("%s_%s", action.getTarget(), action.getAction()));
buttonNode.setLabel(action.getActionName());
levelTwoMenuNode.getChildren().add(buttonNode);
});
}
}
// 将上面找到的二级菜单加入到一菜单的子树中去
List<TreeNode> children = parentNode.getChildren();
if(children == null){
children = new ArrayList<TreeNode>();
}
children.add(levelTwoMenuNode);
parentNode.setChildren(children);
// 已经找过的二级菜单后面不在重复添加
alreadyTargets.add(authority.getTarget());
});
});
return parentNodes;
}
@Override
public void scanGaeaSecurityAuthorities() {
/* 获取当前应用中所有的请求信息
{
"applicationName": "aj-report",
"authCode": "authorityManage:query",
"authName": "权限管理查询",
"beanName": "accessAuthorityController",
"menuCode": "authorityManage",
"path": "GET#/accessAuthority/menuTree"
}*/
List<InitRequestUrlMappings.RequestInfo> requestInfos = initRequestUrlMappings.getRequestInfos(Enabled.YES.getValue());
// key="GET#/accessAuthority/menuTree" value="authorityManage:query"
Map<String, String> securityAuthorityMap = new HashMap<String, String>();
requestInfos.stream().forEach(requestInfo -> {
securityAuthorityMap.put(requestInfo.getPath(), requestInfo.getAuthCode());
});
// 将key存入到缓存中
cacheHelper.hashSet(BusinessConstant.GAEA_SECURITY_AUTHORITIES, securityAuthorityMap);
}
}

View File

@ -0,0 +1,75 @@
package com.anjiplus.template.gaea.business.modules.accessrole.controller;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.annotation.AccessKey;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.anji.plus.gaea.utils.GaeaUtils;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRole;
import com.anjiplus.template.gaea.business.modules.accessrole.service.AccessRoleService;
import com.anjiplus.template.gaea.business.modules.accessrole.controller.dto.AccessRoleDto;
import com.anjiplus.template.gaea.business.modules.accessrole.controller.param.AccessRoleParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import java.util.List;
import java.util.Map;
/**
* @desc 角色管理 controller
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@RestController
@Api(tags = "角色管理管理")
@RequestMapping("/accessRole")
@Permission(code = "roleManage", name = "角色管理")
public class AccessRoleController extends GaeaBaseController<AccessRoleParam, AccessRole, AccessRoleDto> {
@Autowired
private AccessRoleService accessRoleService;
@Override
public GaeaBaseService<AccessRoleParam, AccessRole> getService() {
return accessRoleService;
}
@Override
public AccessRole getEntity() {
return new AccessRole();
}
@Override
public AccessRoleDto getDTO() {
return new AccessRoleDto();
}
/**
* 获取角色的 菜单按钮树 一级菜单 二级菜单 三级按钮
* @return
*/
@Permission( code = "grantAuthority", name = "分配权限")
@GetMapping("/authorityTree/{roleCode}")
public ResponseBean authorityTree(@PathVariable("roleCode")String roleCode){
String operator = UserContentHolder.getContext().getUsername();
Map map = accessRoleService.getAuthorityTree(roleCode, operator);
return responseSuccessWithData(map);
}
/**
* 保存角色的权限
* @return
*/
@Permission( code = "grantAuthority", name = "分配权限")
@PostMapping("/saveAuthorityTree")
public ResponseBean saveAuthorityTree(@RequestBody AccessRoleDto dto){
Boolean data = accessRoleService.saveAuthorityTree(dto);
return responseSuccessWithData(data);
}
}

View File

@ -0,0 +1,46 @@
package com.anjiplus.template.gaea.business.modules.accessrole.controller.dto;
import java.io.Serializable;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import io.swagger.annotations.ApiModelProperty;
import com.anji.plus.gaea.annotation.Formatter;
import lombok.Data;
/**
*
* @description 角色管理 dto
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@Data
public class AccessRoleDto extends GaeaBaseDTO implements Serializable {
/** 角色编码 */
@ApiModelProperty(value = "角色编码")
@NotEmpty(message = "6002")
private String roleCode;
/** 角色名称 */
@ApiModelProperty(value = "角色名称")
@NotEmpty(message = "6002")
private String roleName;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
@ApiModelProperty(value = " 0--未删除 1--已删除 DIC_NAME=DEL_FLAG")
private Integer deleteFlag;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
@NotNull(message = "6002")
private Integer enableFlag;
/** 角色保存的权限 */
private List<String> authorityList;
}

View File

@ -0,0 +1,33 @@
/**/
package com.anjiplus.template.gaea.business.modules.accessrole.controller.param;
import lombok.Data;
import java.io.Serializable;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import java.util.List;
import java.util.Date;
/**
* @desc AccessRole 角色管理查询输入类
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@Data
public class AccessRoleParam extends PageParam implements Serializable{
/** 角色编码 */
@Query(value = QueryEnum.LIKE)
private String roleCode;
// 角色名称
@Query(value = QueryEnum.LIKE)
private String roleName;
// 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG
@Query
private Integer enableFlag;
}

View File

@ -0,0 +1,15 @@
package com.anjiplus.template.gaea.business.modules.accessrole.dao;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRoleAuthority;
import org.apache.ibatis.annotations.Mapper;
/**
* AccessRoleAuthority Mapper
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@Mapper
public interface AccessRoleAuthorityMapper extends GaeaBaseMapper<AccessRoleAuthority> {
}

View File

@ -0,0 +1,22 @@
package com.anjiplus.template.gaea.business.modules.accessrole.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRole;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* AccessRole Mapper
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@Mapper
public interface AccessRoleMapper extends GaeaBaseMapper<AccessRole> {
List<String> checkedAuthoritys(@Param("roleCode")String roleCode);
}

View File

@ -0,0 +1,30 @@
package com.anjiplus.template.gaea.business.modules.accessrole.dao.entity;
import lombok.Data;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import javax.validation.constraints.*;
import java.util.Date;
/**
* @description 角色管理 entity
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@TableName(keepGlobalPrefix=true, value="access_role")
@Data
public class AccessRole extends GaeaBaseEntity {
/** 角色编码 */
private String roleCode;
/** 角色名称 */
private String roleName;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
private Integer deleteFlag;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
}

View File

@ -0,0 +1,44 @@
package com.anjiplus.template.gaea.business.modules.accessrole.dao.entity;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
import java.util.Date;
/**
* @description 角色--菜单--按钮关联关系 entity
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@TableName(keepGlobalPrefix=true, value="access_role_authority")
@Data
public class AccessRoleAuthority extends GaeaBaseEntity {
/** 角色编码 */
private String roleCode;
/** 菜单代码 */
private String target;
/** 按钮代码 */
private String action;
@TableField(exist = false)
private String createBy;
@TableField(exist = false)
private Date createTime;
@TableField(exist = false)
private String updateBy;
@TableField(exist = false)
private Date updateTime;
@TableField(exist = false)
private Integer version;
}

View File

@ -0,0 +1,34 @@
package com.anjiplus.template.gaea.business.modules.accessrole.service;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anjiplus.template.gaea.business.modules.accessrole.controller.dto.AccessRoleDto;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRole;
import com.anjiplus.template.gaea.business.modules.accessrole.controller.param.AccessRoleParam;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import java.util.Map;
/**
* @desc AccessRole 角色管理服务接口
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
public interface AccessRoleService extends GaeaBaseService<AccessRoleParam, AccessRole> {
/** 查询某角色的权限树
* @param roleCode 被操作的对象
* @param operator 当前登录者
* @return
*/
Map getAuthorityTree(String roleCode, String operator);
/** 保存角色的权限
* @param accessRoleDto
* @return
*/
Boolean saveAuthorityTree(AccessRoleDto accessRoleDto);
}

View File

@ -0,0 +1,101 @@
package com.anjiplus.template.gaea.business.modules.accessrole.service.impl;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.anjiplus.template.gaea.business.modules.accessauthority.service.AccessAuthorityService;
import com.anjiplus.template.gaea.business.modules.accessrole.controller.dto.AccessRoleDto;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.AccessRoleAuthorityMapper;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRole;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRoleAuthority;
import com.anjiplus.template.gaea.business.modules.accessrole.service.AccessRoleService;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.AccessRoleMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @desc AccessRole 角色管理服务实现
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:14.136
**/
@Service
public class AccessRoleServiceImpl implements AccessRoleService {
@Autowired
private AccessRoleMapper accessRoleMapper;
@Autowired
private AccessRoleAuthorityMapper accessRoleAuthorityMapper;
@Autowired
private AccessAuthorityService accessAuthorityService;
@Override
public GaeaBaseMapper<AccessRole> getMapper() {
return accessRoleMapper;
}
@Override
public Map getAuthorityTree(String roleCode, String operator) {
Map<String, Object> result = new HashMap<String, Object>();
// 菜单按钮树
List<TreeNode> treeData = accessAuthorityService.getAuthorityTree(operator, true);
// 该角色已选中的菜单及按钮
// List<String> checkedKeys = accessRoleMapper.checkedAuthoritys(roleCode);
LambdaQueryWrapper<AccessRoleAuthority> accessRoleAuthorityWrapper = Wrappers.lambdaQuery();
accessRoleAuthorityWrapper.select(AccessRoleAuthority::getTarget, AccessRoleAuthority::getAction);
accessRoleAuthorityWrapper.eq(AccessRoleAuthority::getRoleCode, roleCode);
List<AccessRoleAuthority> accessRoleAuthorities = accessRoleAuthorityMapper.selectList(accessRoleAuthorityWrapper);
List<String> checkedKeys = accessRoleAuthorities.stream()
.map(accessRoleAuthority -> accessRoleAuthority.getTarget().concat("_").concat(accessRoleAuthority.getAction())).distinct().collect(Collectors.toList());
result.put("treeData", treeData);
result.put("checkedKeys", checkedKeys);
return result;
}
@Override
public Boolean saveAuthorityTree(AccessRoleDto accessRoleDto) {
// 校验
String roleCode = accessRoleDto.getRoleCode();
List<String> authorityList = accessRoleDto.getAuthorityList();
if(StringUtils.isBlank(roleCode)){
throw BusinessExceptionBuilder.build(ResponseCode.NOT_EMPTY, roleCode);
}
if(authorityList == null || authorityList.isEmpty()){
throw BusinessExceptionBuilder.build(ResponseCode.NOT_EMPTY, authorityList);
}
// 先清除该角色已保存的权限
LambdaQueryWrapper<AccessRoleAuthority> wrapper = Wrappers.lambdaQuery();
wrapper.eq(AccessRoleAuthority::getRoleCode, roleCode);
accessRoleAuthorityMapper.delete(wrapper);
// 保存勾选的权限(菜单和按钮)
authorityList.stream().forEach(authorityStr -> {
if(!authorityStr.contains("_")){
return;
}
String[] array = authorityStr.split("_");
AccessRoleAuthority accessRoleAuthority = new AccessRoleAuthority();
accessRoleAuthority.setRoleCode(roleCode);
accessRoleAuthority.setTarget(array[0].trim());
accessRoleAuthority.setAction(array[1].trim());
accessRoleAuthorityMapper.insert(accessRoleAuthority);
});
return true;
}
}

View File

@ -0,0 +1,113 @@
package com.anjiplus.template.gaea.business.modules.accessuser.controller;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.GaeaUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.UpdatePasswordDto;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUser;
import com.anjiplus.template.gaea.business.modules.accessuser.service.AccessUserService;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.AccessUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.param.AccessUserParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import io.swagger.annotations.Api;
import java.util.Map;
/**
* @desc 用户管理 controller
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@RestController
@Api(tags = "用户管理管理")
@RequestMapping("/accessUser")
@Permission(code = "userManage", name = "用户管理")
public class AccessUserController extends GaeaBaseController<AccessUserParam, AccessUser, AccessUserDto> {
@Autowired
private AccessUserService accessUserService;
@Override
public GaeaBaseService<AccessUserParam, AccessUser> getService() {
return accessUserService;
}
@Override
public AccessUser getEntity() {
return new AccessUser();
}
@Override
public AccessUserDto getDTO() {
return new AccessUserDto();
}
/**
* 获取用户的角色树
* @return
*/
@Permission( code = "grantRole", name = "分配角色")
@GetMapping("/roleTree/{loginName}")
public ResponseBean getRoleTree(@PathVariable("loginName")String loginName){
String operator = UserContentHolder.getContext().getUsername();
Map map = accessUserService.getRoleTree(loginName, operator);
return responseSuccessWithData(map);
}
/**
* 保存用户的角色树
* @return
*/
@Permission( code = "grantRole", name = "分配角色")
@PostMapping("/saveRoleTree")
public ResponseBean saveRoleTree(@RequestBody AccessUserDto dto){
Boolean data = accessUserService.saveRoleTree(dto);
return responseSuccessWithData(data);
}
/**
* 重置密码
* @param dto
* @return
*/
@Permission( code = "resetPassword", name = "重置密码")
@PostMapping({"/resetPassword"})
public ResponseBean resetPassword(@RequestBody GaeaUserDto dto) {
Boolean data = accessUserService.resetPassword(dto);
return responseSuccessWithData(data);
}
/**
* 简单实现登录
* @param dto
* @return
*/
@PostMapping({"/login"})
public ResponseBean login(@RequestBody @Validated GaeaUserDto dto) {
return responseSuccessWithData(accessUserService.login(dto));
}
/**
* 修改自己的密码
* @param dto
* @return
*/
@PostMapping("/updatePassword")
public ResponseBean updatePassword(@RequestBody UpdatePasswordDto dto) {
return responseSuccessWithData(accessUserService.updatePassword(dto));
}
}

View File

@ -0,0 +1,66 @@
package com.anjiplus.template.gaea.business.modules.accessuser.controller.dto;
import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUser;
import io.swagger.annotations.ApiModelProperty;
import com.anji.plus.gaea.annotation.Formatter;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
*
* @description 用户管理 dto
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@Data
public class AccessUserDto extends GaeaBaseDTO implements Serializable {
/**  登录名 */
@ApiModelProperty(value = " 登录名")
@NotEmpty(message = "6002")
private String loginName;
/** 真实用户 */
@ApiModelProperty(value = "真实用户")
@NotEmpty(message = "6002")
private String realName;
/** 手机号码 */
@ApiModelProperty(value = "手机号码")
private String phone;
/** 用户邮箱 */
@ApiModelProperty(value = "用户邮箱")
private String email;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
@NotNull(message = "6002")
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
@ApiModelProperty(value = " 0--未删除 1--已删除 DIC_NAME=DEL_FLAG")
private Integer deleteFlag;
/** 最后一次登录IP */
@ApiModelProperty(value = "最后一次登录IP")
private String lastLoginIp;
/** 最后一次登陆时间 */
@ApiModelProperty(value = "最后一次登陆时间")
private Date lastLoginTime;
/** 备注 */
@ApiModelProperty(value = "备注")
private String remark;
/** 用户勾选的角色 */
private List<String> roleCodeList;
}

View File

@ -0,0 +1,30 @@
package com.anjiplus.template.gaea.business.modules.accessuser.controller.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
@ApiModel(value = "用户登录")
@Data
public class GaeaUserDto {
@ApiModelProperty(value = "登录名")
@NotBlank
private String loginName;
@ApiModelProperty(value = "密码")
@NotBlank
private String password;
/** 真实用户 */
private String realName;
/** 登录成功后的 */
private String token;
/** 用户所拥有的权限合集 */
private List<String> authorities;
}

View File

@ -0,0 +1,25 @@
package com.anjiplus.template.gaea.business.modules.accessuser.controller.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
@ApiModel(value = "修改密码")
@Data
public class UpdatePasswordDto {
@ApiModelProperty(value = "旧密码密码")
@NotBlank
private String oldPassword;
@ApiModelProperty(value = "密码")
@NotBlank
private String password;
@ApiModelProperty(value = "密码")
@NotBlank
private String confirmPassword;
}

View File

@ -0,0 +1,37 @@
/**/
package com.anjiplus.template.gaea.business.modules.accessuser.controller.param;
import lombok.Data;
import java.io.Serializable;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import java.util.List;
import java.util.Date;
/**
* @desc AccessUser 用户管理查询输入类
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@Data
public class AccessUserParam extends PageParam implements Serializable{
//  登录名
@Query(value = QueryEnum.LIKE)
private String loginName;
// 真实用户
@Query(value = QueryEnum.LIKE)
private String realName;
// 手机号码
@Query(value = QueryEnum.LIKE)
private String phone;
// 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG
@Query
private Integer enableFlag;
}

View File

@ -0,0 +1,26 @@
package com.anjiplus.template.gaea.business.modules.accessuser.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* AccessUser Mapper
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@Mapper
public interface AccessUserMapper extends GaeaBaseMapper<AccessUser> {
/** 查询用户所拥有的所有角色下的权限
* @param loginName
* @return
*/
List<String> queryAuthoritiesByLoginName(@Param("loginName")String loginName);
}

View File

@ -0,0 +1,15 @@
package com.anjiplus.template.gaea.business.modules.accessuser.dao;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUserRole;
import org.apache.ibatis.annotations.Mapper;
/**
* AccessUser Mapper
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@Mapper
public interface AccessUserRoleMapper extends GaeaBaseMapper<AccessUserRole> {
}

View File

@ -0,0 +1,48 @@
package com.anjiplus.template.gaea.business.modules.accessuser.dao.entity;
import lombok.Data;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import javax.validation.constraints.*;
import java.util.Date;
/**
* @description 用户管理 entity
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@TableName(keepGlobalPrefix=true, value="access_user")
@Data
public class AccessUser extends GaeaBaseEntity {
/**  登录名 */
private String loginName;
/** 密码 */
private String password;
/** 真实用户 */
private String realName;
/** 手机号码 */
private String phone;
/** 用户邮箱 */
private String email;
/** 备注 */
private String remark;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
private Integer deleteFlag;
/** 最后一次登录IP */
private String lastLoginIp;
/** 最后一次登陆时间 */
private Date lastLoginTime;
}

View File

@ -0,0 +1,40 @@
package com.anjiplus.template.gaea.business.modules.accessuser.dao.entity;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @description 用户--角色关联关系 entity
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@TableName(keepGlobalPrefix=true, value="access_user_role")
@Data
public class AccessUserRole extends GaeaBaseEntity {
/**  登录名 */
private String loginName;
/** 角色编码 */
private String roleCode;
@TableField(exist = false)
private String createBy;
@TableField(exist = false)
private Date createTime;
@TableField(exist = false)
private String updateBy;
@TableField(exist = false)
private Date updateTime;
@TableField(exist = false)
private Integer version;
}

View File

@ -0,0 +1,52 @@
package com.anjiplus.template.gaea.business.modules.accessuser.service;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.AccessUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.GaeaUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.UpdatePasswordDto;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUser;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.param.AccessUserParam;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import java.util.Map;
/**
* @desc AccessUser 用户管理服务接口
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
public interface AccessUserService extends GaeaBaseService<AccessUserParam, AccessUser> {
/** 获取用户的角色树
* @param loginName 被操作的对象
* @param operator 当前登录者
* @return
*/
Map getRoleTree(String loginName, String operator);
/** 保存用户的角色树
* @param accessUserDto
* @return
*/
Boolean saveRoleTree(AccessUserDto accessUserDto);
/** 重置密码
* @param gaeaUserDto
* @return
*/
Boolean resetPassword(GaeaUserDto gaeaUserDto);
/** 用户登录
* @param gaeaUserDto
* @return
*/
GaeaUserDto login(GaeaUserDto gaeaUserDto);
/**
* 修改密码
* @param dto
* @return
*/
Boolean updatePassword(UpdatePasswordDto dto);
}

View File

@ -0,0 +1,277 @@
package com.anjiplus.template.gaea.business.modules.accessuser.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.cache.CacheHelper;
import com.anji.plus.gaea.constant.BaseOperationEnum;
import com.anji.plus.gaea.constant.GaeaConstant;
import com.anji.plus.gaea.exception.BusinessException;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anji.plus.gaea.utils.GaeaUtils;
import com.anji.plus.gaea.utils.JwtBean;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.anjiplus.template.gaea.business.constant.BusinessConstant;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.AccessRoleAuthorityMapper;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.AccessRoleMapper;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRole;
import com.anjiplus.template.gaea.business.modules.accessrole.dao.entity.AccessRoleAuthority;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.AccessUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.GaeaUserDto;
import com.anjiplus.template.gaea.business.modules.accessuser.controller.dto.UpdatePasswordDto;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.AccessUserRoleMapper;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUser;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.entity.AccessUserRole;
import com.anjiplus.template.gaea.business.modules.accessuser.service.AccessUserService;
import com.anjiplus.template.gaea.business.modules.accessuser.dao.AccessUserMapper;
import com.anjiplus.template.gaea.business.util.MD5Util;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* @desc AccessUser 用户管理服务实现
* @author 木子李·De <lide1202@hotmail.com>
* @date 2019-02-17 08:50:11.902
**/
@Service
public class AccessUserServiceImpl implements AccessUserService {
@Autowired
private AccessRoleMapper accessRoleMapper;
@Autowired
private AccessUserMapper accessUserMapper;
@Autowired
private AccessUserRoleMapper accessUserRoleMapper;
@Autowired
private AccessRoleAuthorityMapper accessRoleAuthorityMapper;
@Value("${customer.user.default.password:'123456'}")
private String defaultPassword;
@Override
public GaeaBaseMapper<AccessUser> getMapper() {
return accessUserMapper;
}
@Autowired
private JwtBean jwtBean;
@Autowired
private CacheHelper cacheHelper;
@Override
public Map getRoleTree(String loginName, String operator) {
Map<String, Object> result = new HashMap<String, Object>();
List<TreeNode> treeData = new ArrayList<>();
List checkedKeys = new ArrayList();
// 角色树
LambdaQueryWrapper<AccessRole> roleQuery = Wrappers.lambdaQuery();
roleQuery.select(AccessRole::getRoleCode, AccessRole::getRoleName);
// 按operator去筛选role 后面再加where
List<AccessRole> roleList = accessRoleMapper.selectList(roleQuery);
if(roleList == null || roleList.isEmpty()){
result.put("treeData", treeData);
result.put("checkedKeys", checkedKeys);
return result;
}
treeData = roleList.stream().map(role -> {
TreeNode treeNode = new TreeNode();
treeNode.setId(role.getRoleCode());
treeNode.setLabel(role.getRoleName());
return treeNode;
}).collect(Collectors.toList());
// 该用户已保存的角色
LambdaQueryWrapper<AccessUserRole> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.select(AccessUserRole::getRoleCode)
.eq(AccessUserRole::getLoginName, loginName);
checkedKeys = accessUserRoleMapper.selectObjs(queryWrapper);
result.put("treeData", treeData);
result.put("checkedKeys", checkedKeys);
return result;
}
@Override
public Boolean saveRoleTree(AccessUserDto accessUserDto) {
// 校验
String loginName = accessUserDto.getLoginName();
List<String> roleCodeList = accessUserDto.getRoleCodeList();
if(StringUtils.isBlank(loginName)){
throw BusinessExceptionBuilder.build(ResponseCode.NOT_EMPTY, loginName);
}
if(roleCodeList == null || roleCodeList.isEmpty()){
throw BusinessExceptionBuilder.build(ResponseCode.NOT_EMPTY, roleCodeList);
}
// 先清除该用户已保存的角色
LambdaQueryWrapper<AccessUserRole> wrapper = Wrappers.lambdaQuery();
wrapper.eq(AccessUserRole::getLoginName, loginName);
accessUserRoleMapper.delete(wrapper);
// 保存勾选的角色
roleCodeList.stream().forEach(roleCode -> {
AccessUserRole accessUserRole = new AccessUserRole();
accessUserRole.setLoginName(loginName);
accessUserRole.setRoleCode(roleCode);
accessUserRoleMapper.insert(accessUserRole);
});
return true;
}
@Override
public Boolean resetPassword(GaeaUserDto gaeaUserDto) {
String loginName = gaeaUserDto.getLoginName();
if (GaeaConstant.SUPER_USER_NAME.equalsIgnoreCase(loginName)) {
throw BusinessExceptionBuilder.build("admin不允许重置密码");
}
// 1.判断用户是否存在
LambdaQueryWrapper<AccessUser> wrapper = Wrappers.lambdaQuery();
wrapper.eq(AccessUser::getLoginName, loginName);
AccessUser accessUser = accessUserMapper.selectOne(wrapper);
if (accessUser == null) {
throw BusinessExceptionBuilder.build("用户不存在");
}
//默认密码
accessUser.setPassword(MD5Util.encrypt(MD5Util.encrypt(defaultPassword.concat("gaea"))));
accessUserMapper.updateById(accessUser);
return true;
}
@Override
public GaeaUserDto login(GaeaUserDto gaeaUserDto) {
String loginName = gaeaUserDto.getLoginName();
String password = gaeaUserDto.getPassword();
// 1.判断用户是否存在
LambdaQueryWrapper<AccessUser> wrapper = Wrappers.lambdaQuery();
wrapper.eq(AccessUser::getLoginName, loginName);
AccessUser accessUser = accessUserMapper.selectOne(wrapper);
if (null == accessUser) {
throw BusinessExceptionBuilder.build(ResponseCode.LOGIN_ERROR);
}
// 2.密码错误
if (!accessUser.getPassword().equals(MD5Util.encrypt(password))) {
throw BusinessExceptionBuilder.build(ResponseCode.USER_PASSWORD_ERROR);
}
// 3.如果该用户登录未过期这里允许一个用户在多个终端登录
String tokenKey = String.format(BusinessConstant.GAEA_SECURITY_LOGIN_TOKEN, loginName);
String token = "";
GaeaUserDto gaeaUser = new GaeaUserDto();
if (cacheHelper.exist(tokenKey)) {
token = cacheHelper.stringGet(tokenKey);
} else {
// 生成用户token
String uuid = GaeaUtils.UUID();
token = jwtBean.createToken(loginName, uuid, 0, GaeaConstant.TENANT_CODE);
cacheHelper.stringSetExpire(tokenKey, token, 3600);
}
// 4.读取用户最新人权限主信息
String userKey = String.format(BusinessConstant.GAEA_SECURITY_LOGIN_USER, loginName);
//为了兼容底层其他数据库不再写自定义sql
// List<String> authorities = accessUserMapper.queryAuthoritiesByLoginName(loginName);
//当前用户的roleCode集合
LambdaQueryWrapper<AccessUserRole> accessUserWrapper = Wrappers.lambdaQuery();
accessUserWrapper.select(AccessUserRole::getRoleCode);
accessUserWrapper.eq(AccessUserRole::getLoginName, loginName);
List<AccessUserRole> accessUserRoles = accessUserRoleMapper.selectList(accessUserWrapper);
Set<String> roleCodeSet = accessUserRoles.stream().map(AccessUserRole::getRoleCode).collect(Collectors.toSet());
if (roleCodeSet.size() < 1) {
gaeaUser.setAuthorities(new ArrayList<>());
}else {
LambdaQueryWrapper<AccessRoleAuthority> accessRoleAuthorityWrapper = Wrappers.lambdaQuery();
accessRoleAuthorityWrapper.select(AccessRoleAuthority::getTarget, AccessRoleAuthority::getAction);
accessRoleAuthorityWrapper.in(AccessRoleAuthority::getRoleCode, roleCodeSet);
List<AccessRoleAuthority> accessRoleAuthorities = accessRoleAuthorityMapper.selectList(accessRoleAuthorityWrapper);
List<String> authorities = accessRoleAuthorities.stream()
.map(accessRoleAuthority -> accessRoleAuthority.getTarget().concat(":").concat(accessRoleAuthority.getAction())).distinct().collect(Collectors.toList());
gaeaUser.setAuthorities(authorities);
}
gaeaUser.setLoginName(loginName);
gaeaUser.setRealName(accessUser.getRealName());
gaeaUser.setToken(token);
String gaeaUserStr = JSONObject.toJSONString(gaeaUser);
cacheHelper.stringSetExpire(userKey, gaeaUserStr, 3600);
return gaeaUser;
}
/**
* 修改密码
*
* @param dto
* @return
*/
@Override
public Boolean updatePassword(UpdatePasswordDto dto) {
if (!dto.getConfirmPassword().equals(dto.getPassword())) {
//密码和确认密码不一致
throw BusinessExceptionBuilder.build(ResponseCode.USER_INCONSISTENT_PASSWORD_ERROR);
}
//新密码不能与老密码一样
if(StringUtils.equals(dto.getOldPassword(), dto.getPassword())){
throw BusinessExceptionBuilder.build(ResponseCode.USER_PASSWORD_CONFIG_PASSWORD_CANOT_EQUAL);
}
String username = UserContentHolder.getUsername();
LambdaQueryWrapper<AccessUser> wrapper = Wrappers.lambdaQuery();
wrapper.eq(AccessUser::getLoginName, username);
AccessUser accessUser = selectOne(wrapper);
String password = accessUser.getPassword();
if (!MD5Util.encrypt(dto.getOldPassword()).equals(password)) {
throw BusinessExceptionBuilder.build(ResponseCode.USER_OLD_PASSWORD_ERROR);
}
accessUser.setPassword(MD5Util.encrypt(dto.getPassword()));
accessUserMapper.updateById(accessUser);
return true;
}
/**
* 操作前处理
*
* @param entity 前端传递的对象
* @param operationEnum 操作类型
* @throws BusinessException 阻止程序继续执行或回滚事务
*/
@Override
public void processBeforeOperation(AccessUser entity, BaseOperationEnum operationEnum) throws BusinessException {
//过滤密码
switch (operationEnum) {
case INSERT:
//gaea是为了和前端加密保持一致
entity.setPassword(MD5Util.encrypt(MD5Util.encrypt(defaultPassword.concat("gaea"))));
break;
case UPDATE:
//更新用户不允许修改密码
entity.setPassword(null);
break;
default:
break;
}
}
}

View File

@ -0,0 +1,109 @@
package com.anjiplus.template.gaea.business.modules.dashboard.controller;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.annotation.log.GaeaAuditLog;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ReportDashboardService;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ReportDashboardObjectDto;
import com.anjiplus.template.gaea.business.modules.reportshare.controller.dto.ReportShareDto;
import com.anjiplus.template.gaea.business.modules.reportshare.service.ReportShareService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @desc 大屏设计 controller
* @website https://gitee.com/anji-plus/gaea
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@RestController
@Api(tags = "大屏设计管理")
@Permission(code = "bigScreenManage", name = "大屏报表")
@RequestMapping("/reportDashboard")
public class ReportDashboardController {
@Autowired
private ReportDashboardService reportDashboardService;
@Autowired
private ReportShareService reportShareService;
/**
* 预览查询大屏详情
* @param reportCode
* @return
*/
@GetMapping({"/{reportCode}"})
@Permission(code = "view", name = "查看大屏")
public ResponseBean detail(@PathVariable("reportCode") String reportCode) {
return ResponseBean.builder().data(reportDashboardService.getDetail(reportCode)).build();
}
/**
* 保存大屏设计
* @param dto
* @return
*/
@PostMapping
@Permission(code = "design", name = "设计大屏")
@GaeaAuditLog(pageTitle = "新增")
public ResponseBean insert(@RequestBody ReportDashboardObjectDto dto) {
reportDashboardService.insertDashboard(dto);
return ResponseBean.builder().build();
}
/**
* 获取去单个图层数据
* @param dto
* @return
*/
@PostMapping("/getData")
@Permission(code = "view", name = "查看大屏")
public ResponseBean getData(@RequestBody ChartDto dto) {
return ResponseBean.builder().data(reportDashboardService.getChartData(dto)).build();
}
/**
* 导出大屏
* @param reportCode
* @return
*/
@GetMapping("/export")
@Permission(code = "export", name = "导出大屏")
public ResponseEntity<byte[]> exportDashboard(HttpServletRequest request, HttpServletResponse response,
@RequestParam("reportCode") String reportCode, @RequestParam(value = "showDataSet",required = false, defaultValue = "1") Integer showDataSet) {
return reportDashboardService.exportDashboard(request, response, reportCode, showDataSet);
}
/**
* 导入大屏
* @param file 导入的zip文件
* @param reportCode
* @return
*/
@PostMapping("/import/{reportCode}")
@Permission(code = "import", name = "导入大屏")
public ResponseBean importDashboard(@RequestParam("file") MultipartFile file, @PathVariable("reportCode") String reportCode) {
reportDashboardService.importDashboard(file, reportCode);
return ResponseBean.builder().build();
}
@PostMapping("/share")
@GaeaAuditLog(pageTitle = "分享")
@Permission(code = "share", name = "分享报表")
public ResponseBean share(@Validated @RequestBody ReportShareDto dto) {
return ResponseBean.builder().data(reportShareService.insertShare(dto)).build();
}
}

View File

@ -0,0 +1,51 @@
package com.anjiplus.template.gaea.business.modules.dashboard.controller.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Map;
/**
*
* @description 大屏设计 dto
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@Data
public class ChartDto implements Serializable {
private String chartType;
/**数据集编码*/
private String setCode;
/** 传入的自定义参数*/
private Map<String, Object> contextData;
/**图表属性*/
private Map<String, String> chartProperties;
/**时间字段*/
private String timeLineFiled;
/**时间颗粒度*/
private String particles;
/**时间格式化*/
private String dataTimeFormat;
/**时间展示层*/
private String timeLineFormat;
private int timeUnit;
/**时间区间*/
private String startTime;
/**时间区间*/
private String endTime;
}

View File

@ -0,0 +1,55 @@
package com.anjiplus.template.gaea.business.modules.dashboard.controller.dto;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetDto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* @description 大屏设计 dto
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@Data
public class ReportDashboardDto extends GaeaBaseDTO implements Serializable {
/** 报表编码 */
private String reportCode;
/** 看板标题 */
private String title;
/** 宽度px */
private Long width;
/** 高度px */
private Long height;
/** 背景色 */
private String backgroundColor;
/** 背景图片 */
private String backgroundImage;
/** 工作台中的辅助线 */
private String presetLine;
/** 自动刷新间隔秒数据字典REFRESH_TYPE */
private Integer refreshSeconds;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
private Integer deleteFlag;
/** 排序,降序 */
private Integer sort;
private List<ReportDashboardWidgetDto> widgets;
}

View File

@ -0,0 +1,32 @@
package com.anjiplus.template.gaea.business.modules.dashboard.controller.dto;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetDto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* @description 大屏设计 dto
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@Data
public class ReportDashboardObjectDto implements Serializable {
/** 报表编码 */
private String reportCode;
/**
* 报表编码
*/
private ReportDashboardDto dashboard;
/**
* 大屏画布中的组件
*/
private List<ReportDashboardWidgetDto> widgets;
}

View File

@ -0,0 +1,20 @@
/**/
package com.anjiplus.template.gaea.business.modules.dashboard.controller.param;
import lombok.Data;
import java.io.Serializable;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import java.util.List;
/**
* @desc ReportDashboard 大屏设计查询输入类
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@Data
public class ReportDashboardParam extends PageParam implements Serializable{
}

View File

@ -0,0 +1,16 @@
package com.anjiplus.template.gaea.business.modules.dashboard.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.dashboard.dao.entity.ReportDashboard;
/**
* ReportDashboard Mapper
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@Mapper
public interface ReportDashboardMapper extends GaeaBaseMapper<ReportDashboard> {
}

View File

@ -0,0 +1,54 @@
package com.anjiplus.template.gaea.business.modules.dashboard.dao.entity;
import com.anji.plus.gaea.annotation.Unique;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description 大屏设计 entity
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
@TableName(keepGlobalPrefix=true, value="gaea_report_dashboard")
@Data
public class ReportDashboard extends GaeaBaseEntity {
@ApiModelProperty(value = "报表编码")
@Unique(code = ResponseCode.REPORT_CODE_ISEXIST)
private String reportCode;
@ApiModelProperty(value = "看板标题")
private String title;
@ApiModelProperty(value = "宽度px")
private Long width;
@ApiModelProperty(value = "高度px")
private Long height;
@ApiModelProperty(value = "背景色")
private String backgroundColor;
@ApiModelProperty(value = "背景图片")
private String backgroundImage;
@ApiModelProperty(value = "工作台中的辅助线")
private String presetLine;
@ApiModelProperty(value = "自动刷新间隔秒数据字典REFRESH_TYPE")
private Integer refreshSeconds;
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
private Integer enableFlag;
@ApiModelProperty(value = " 0--未删除 1--已删除 DIC_NAME=DEL_FLAG")
private Integer deleteFlag;
@ApiModelProperty(value = "排序,降序")
private Integer sort;
}

View File

@ -0,0 +1,26 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service;
import com.alibaba.fastjson.JSONObject;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import java.util.List;
/**
* Created by raodeming on 2021/4/26.
*/
public interface ChartStrategy {
/**
* 图表类型
* @return
*/
String type();
/**
* 针对每种图表类型做单独的数据转换解析
*
* @param dto
* @return
*/
Object transform(ChartDto dto, List<JSONObject> data);
}

View File

@ -0,0 +1,61 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ReportDashboardObjectDto;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.param.ReportDashboardParam;
import com.anjiplus.template.gaea.business.modules.dashboard.dao.entity.ReportDashboard;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @desc ReportDashboard 大屏设计服务接口
* @author Raod
* @date 2021-04-12 14:52:21.761
**/
public interface ReportDashboardService extends GaeaBaseService<ReportDashboardParam, ReportDashboard> {
/***
* 查询详情
*
* @param reportCode
*/
ReportDashboardObjectDto getDetail(String reportCode);
/***
* 保存大屏设计
*
* @param dto
*/
void insertDashboard(ReportDashboardObjectDto dto);
/**
* 获取单个图表数据
* @param dto
* @return
*/
Object getChartData(ChartDto dto);
/**
* 导出大屏zip文件
* @param request
* @param response
* @param reportCode
* @return
*/
ResponseEntity<byte[]> exportDashboard(HttpServletRequest request, HttpServletResponse response, String reportCode, Integer showDataSet);
/**
* 导入大屏zip
* @param file
* @param reportCode
* @return
*/
void importDashboard(MultipartFile file, String reportCode);
}

View File

@ -0,0 +1,79 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 柱状体或者折线图
* Created by raodeming on 2021/4/26.
*/
@Component
public class BarChartServiceImpl implements ChartStrategy {
/**
* 图表类型
*
* @return
*/
@Override
public String type() {
return "widget-barchart|widget-linechart";
}
/**
* 针对每种图表类型做单独的数据转换解析
*
* @param dto
* @param data
* @return
*/
@Override
public Object transform(ChartDto dto, List<JSONObject> data) {
// JSONObject json = new JSONObject();
// List<Object> xAxis = new ArrayList<>();
// List<Object> series = new ArrayList<>();
// data.forEach(jsonObject -> {
// jsonObject.forEach((s, o) -> {
// if ("xAxis".equals(s)) {
// xAxis.add(o);
// } else {
// series.add(o);
// }
// });
// });
//
// json.put("xAxis", xAxis);
// JSONArray objects = new JSONArray();
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("data", series);
// objects.add(jsonObject);
// json.put("series", objects);
// return json.toJSONString();
return data;
}
/* {
"xAxis": [
"哈哈",
"洗洗",
"来了",
"问问",
"天天"
],
"series": [
{
"data": [
1,
2,
3,
4,
5
]
}
]
}*/
}

View File

@ -0,0 +1,105 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 折柱图
* Created by raodeming on 2021/4/26.
*/
@Component
public class BarLineChartServiceImpl implements ChartStrategy {
/**
* 图表类型
*
* @return
*/
@Override
public String type() {
return "widget-barlinechart";
}
/**
* 针对每种图表类型做单独的数据转换解析
*
* @param dto
* @param data
* @return
*/
@Override
public Object transform(ChartDto dto, List<JSONObject> data) {
// JSONObject json = new JSONObject();
// List<Object> xAxis = new ArrayList<>();
// Map<String, List<Object>> series = new HashMap<>();
// data.forEach(jsonObject -> {
// jsonObject.forEach((s, o) -> {
// if ("xAxis".equals(s)) {
// xAxis.add(o);
// } else {
// List<Object> objects;
// if (series.containsKey(s)) {
// objects = series.get(s);
// } else {
// objects = new ArrayList<>();
//
// }
// objects.add(o);
// series.put(s, objects);
//
// }
// });
// });
//
// json.put("xAxis", xAxis);
// List<JSONObject> result = new ArrayList<>();
// series.forEach((s, objects) -> {
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("name", s);
// if (s.endsWith("bar")) {
// jsonObject.put("type", "bar");
// } else {
// jsonObject.put("type", "line");
// }
// jsonObject.put("data", objects);
// result.add(jsonObject);
// });
// json.put("series", result);
// return json.toJSONString();
return data;
}
/*{
"xAxis": [
"1月",
"2月",
"3月"
],
"series": [
{
"name": "指标1", //暂时用不上
"type": "bar", //需要处理
"data": [
2,
49,
2
]
},
{
"name": "指标2",
"type": "line",
"yAxisIndex": 1,
"data": [
2,
32,
4
]
}
]
}*/
}

View File

@ -0,0 +1,43 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 饼图或者空心饼图或者漏斗图
* Created by raodeming on 2021/4/26.
*/
@Component
public class GaugeChartServiceImpl implements ChartStrategy {
/**
* 图表类型
*
* @return
*/
@Override
public String type() {
return "widget-gauge";
}
/**
* 针对每种图表类型做单独的数据转换解析
*
* @param dto
* @param data
* @return
*/
@Override
public Object transform(ChartDto dto, List<JSONObject> data) {
// return "{\"value\": 50, \"name\": \"名称1\", \"unit\": \"%\"}";
return data;
}
}

View File

@ -0,0 +1,52 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 饼图或者空心饼图或者漏斗图
* Created by raodeming on 2021/4/26.
*/
@Component
public class PieChartServiceImpl implements ChartStrategy {
/**
* 图表类型
*
* @return
*/
@Override
public String type() {
return "widget-piechart|widget-hollow-piechart|widget-funnel";
}
/**
* 针对每种图表类型做单独的数据转换解析
*
* @param dto
* @param data
* @return
*/
@Override
public Object transform(ChartDto dto, List<JSONObject> data) {
return data;
}
/* [
{
"value": 11,
"name": "指标1"
},
{
"value": 10,
"name": "指标2"
}
]*/
}

View File

@ -0,0 +1,561 @@
package com.anjiplus.template.gaea.business.modules.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anji.plus.gaea.utils.GaeaAssert;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ChartDto;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ReportDashboardDto;
import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.ReportDashboardObjectDto;
import com.anjiplus.template.gaea.business.modules.dashboard.dao.ReportDashboardMapper;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy;
import com.anjiplus.template.gaea.business.modules.dashboard.service.ReportDashboardService;
import com.anjiplus.template.gaea.business.modules.file.entity.GaeaFile;
import com.anjiplus.template.gaea.business.modules.file.service.GaeaFileService;
import com.anjiplus.template.gaea.business.modules.file.util.FileUtils;
import com.anjiplus.template.gaea.business.modules.report.service.ReportService;
import com.anjiplus.template.gaea.business.util.DateUtil;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetDto;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetValueDto;
import com.anjiplus.template.gaea.business.modules.dashboard.dao.entity.ReportDashboard;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.entity.ReportDashboardWidget;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.service.ReportDashboardWidgetService;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.DataSetDto;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.OriginalDataDto;
import com.anjiplus.template.gaea.business.modules.dataset.service.DataSetService;
import com.anjiplus.template.gaea.business.util.FileUtil;
import com.anjiplus.template.gaea.business.util.RequestUtil;
import com.anjiplus.template.gaea.business.util.UuidUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
/**
* @author Raod
* @desc ReportDashboard 大屏设计服务实现
* @date 2021-04-12 14:52:21.761
**/
@Service
@Slf4j
//@RequiredArgsConstructor
public class ReportDashboardServiceImpl implements ReportDashboardService, InitializingBean, ApplicationContextAware {
@Autowired
private ReportDashboardMapper reportDashboardMapper;
@Autowired
private ReportDashboardWidgetService reportDashboardWidgetService;
@Autowired
private DataSetService dataSetService;
@Autowired
private GaeaFileService gaeaFileService;
@Autowired
private ReportService reportService;
@Value("${spring.gaea.subscribes.oss.downloadPath:}")
private String fileDownloadPath;
@Value("${customer.file.tmp-path:.}")
private String dictPath;
private final static String ZIP_PATH = "/tmp_zip/";
private final static String JSON_PATH = "dashboard.json";
private Map<String, ChartStrategy> queryServiceImplMap = new HashMap<>();
private ApplicationContext applicationContext;
@Override
public GaeaBaseMapper<ReportDashboard> getMapper() {
return reportDashboardMapper;
}
@Override
public ReportDashboardObjectDto getDetail(String reportCode) {
ReportDashboardObjectDto result = new ReportDashboardObjectDto();
ReportDashboardDto reportDashboardDto = new ReportDashboardDto();
ReportDashboard reportDashboard = this.selectOne("report_code", reportCode);
if (null == reportDashboard) {
return new ReportDashboardObjectDto();
}
GaeaBeanUtils.copyAndFormatter(reportDashboard, reportDashboardDto);
List<ReportDashboardWidget> list = reportDashboardWidgetService.list(
new QueryWrapper<ReportDashboardWidget>().lambda()
.eq(ReportDashboardWidget::getReportCode, reportCode)
.orderByAsc(ReportDashboardWidget::getSort)
);
List<ReportDashboardWidgetDto> reportDashboardWidgetDtoList = new ArrayList<>();
list.forEach(reportDashboardWidget -> {
ReportDashboardWidgetDto reportDashboardWidgetDto = new ReportDashboardWidgetDto();
ReportDashboardWidgetValueDto value = new ReportDashboardWidgetValueDto();
value.setSetup(StringUtils.isNotBlank(reportDashboardWidget.getSetup()) ? JSONObject.parseObject(reportDashboardWidget.getSetup()) : new JSONObject());
value.setData(StringUtils.isNotBlank(reportDashboardWidget.getData()) ? JSONObject.parseObject(reportDashboardWidget.getData()) : new JSONObject());
value.setPosition(StringUtils.isNotBlank(reportDashboardWidget.getPosition()) ? JSONObject.parseObject(reportDashboardWidget.getPosition()) : new JSONObject());
value.setCollapse(StringUtils.isNotBlank(reportDashboardWidget.getCollapse()) ? JSONObject.parseObject(reportDashboardWidget.getCollapse()) : new JSONObject());
//实时数据的替换
analysisData(value);
reportDashboardWidgetDto.setType(reportDashboardWidget.getType());
reportDashboardWidgetDto.setValue(value);
reportDashboardWidgetDto.setOptions(JSONObject.parseObject(reportDashboardWidget.getOptions()));
reportDashboardWidgetDtoList.add(reportDashboardWidgetDto);
});
reportDashboardDto.setWidgets(reportDashboardWidgetDtoList);
result.setDashboard(reportDashboardDto);
result.setReportCode(reportCode);
return result;
}
/***
* 保存大屏设计
*
* @param dto
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void insertDashboard(ReportDashboardObjectDto dto) {
String reportCode = dto.getReportCode();
GaeaAssert.notEmpty(reportCode, ResponseCode.PARAM_IS_NULL, "reportCode");
//查询ReportDashboard
ReportDashboard reportDashboard = this.selectOne("report_code", reportCode);
ReportDashboard dashboard = new ReportDashboard();
GaeaBeanUtils.copyAndFormatter(dto.getDashboard(), dashboard);
BeanUtils.copyProperties(dto.getDashboard(), dashboard);
dashboard.setReportCode(reportCode);
if (null == reportDashboard) {
//新增
this.insert(dashboard);
} else {
//更新
dashboard.setId(reportDashboard.getId());
dashboard.setVersion(null);
this.update(dashboard);
}
//删除reportDashboardWidget
reportDashboardWidgetService.delete(new QueryWrapper<ReportDashboardWidget>()
.lambda().eq(ReportDashboardWidget::getReportCode, reportCode));
List<ReportDashboardWidgetDto> widgets = dto.getWidgets();
// List<ReportDashboardWidget> reportDashboardWidgetList = new ArrayList<>();
for (int i = 0; i < widgets.size(); i++) {
ReportDashboardWidget reportDashboardWidget = new ReportDashboardWidget();
ReportDashboardWidgetDto reportDashboardWidgetDto = widgets.get(i);
String type = reportDashboardWidgetDto.getType();
ReportDashboardWidgetValueDto value = reportDashboardWidgetDto.getValue();
reportDashboardWidget.setReportCode(reportCode);
reportDashboardWidget.setType(type);
reportDashboardWidget.setSetup(value.getSetup() != null ? JSONObject.toJSONString(value.getSetup()) : "");
reportDashboardWidget.setData(value.getData() != null ? JSONObject.toJSONString(value.getData()) : "");
reportDashboardWidget.setPosition(value.getPosition() != null ? JSONObject.toJSONString(value.getPosition()) : "");
reportDashboardWidget.setCollapse(value.getCollapse() != null ? JSONObject.toJSONString(value.getCollapse()) : "");
reportDashboardWidget.setOptions(reportDashboardWidgetDto.getOptions() != null ? JSONObject.toJSONString(reportDashboardWidgetDto.getOptions()) : "");
reportDashboardWidget.setEnableFlag(1);
reportDashboardWidget.setDeleteFlag(0);
reportDashboardWidget.setSort((long) (i + 1));
//兼容底层不采用批量插入
reportDashboardWidgetService.insert(reportDashboardWidget);
// reportDashboardWidgetList.add(reportDashboardWidget);
}
// reportDashboardWidgetService.insertBatch(reportDashboardWidgetList);
}
@Override
public Object getChartData(ChartDto dto) {
// String chartType = dto.getChartType();
DataSetDto setDto = new DataSetDto();
setDto.setSetCode(dto.getSetCode());
setDto.setContextData(dto.getContextData());
OriginalDataDto result = dataSetService.getData(setDto);
List<JSONObject> data = result.getData();
//处理时间轴
List<JSONObject> resultData = buildTimeLine(data, dto);
return resultData;
// return getTarget(chartType).transform(dto, result.getData());
}
/**
* 导出大屏zip文件
*
* @param request
* @param response
* @param reportCode
* @return
*/
@Override
public ResponseEntity<byte[]> exportDashboard(HttpServletRequest request, HttpServletResponse response, String reportCode, Integer showDataSet) {
String userAgent = request.getHeader("User-Agent");
boolean isIeBrowser = userAgent.indexOf("MSIE") > 0;
ReportDashboardObjectDto detail = getDetail(reportCode);
List<ReportDashboardWidgetDto> widgets = detail.getDashboard().getWidgets();
detail.setWidgets(widgets);
detail.getDashboard().setWidgets(null);
//1.组装临时目录,/app/disk/upload/zip/临时文件夹
String path = dictPath + ZIP_PATH + UuidUtil.generateShortUuid();
//将涉及到的图片保存下来1.背景图2.组件为图片的
String backgroundImage = detail.getDashboard().getBackgroundImage();
zipLoadImage(backgroundImage, path);
detail.getWidgets().stream()
.filter(reportDashboardWidgetDto -> "widget-image".equals(reportDashboardWidgetDto.getType()))
.forEach(reportDashboardWidgetDto -> {
String imageAddress = reportDashboardWidgetDto.getValue().getSetup().getString("imageAdress");
zipLoadImage(imageAddress, path);
});
//showDataSet == 0 代表不包含数据集
if (0 == showDataSet) {
detail.getWidgets().forEach(reportDashboardWidgetDto -> {
ReportDashboardWidgetValueDto value = reportDashboardWidgetDto.getValue();
JSONObject data = value.getData();
if (null != data && data.containsKey("dataType")) {
reportDashboardWidgetDto.getValue().getData().put("dataType", "staticData");
}
});
}
//2.将大屏设计到的json文件保存
String jsonPath = path + "/" + JSON_PATH;
FileUtil.WriteStringToFile(jsonPath, JSONObject.toJSONString(detail));
//将path文件夹打包zip
String zipPath = path + ".zip";
FileUtil.compress(path, zipPath);
File file = new File(zipPath);
ResponseEntity.BodyBuilder builder = ResponseEntity.ok();
builder.contentLength(file.length());
//application/octet-stream 二进制数据流最常见的文件下载
builder.contentType(MediaType.APPLICATION_OCTET_STREAM);
if (isIeBrowser) {
builder.header("Content-Disposition", "attachment; filename=" + reportCode + ".zip");
} else {
builder.header("Content-Disposition", "attacher; filename*=UTF-8''" + reportCode + ".zip");
}
ResponseEntity<byte[]> body = builder.body(FileUtils.readFileToByteArray(file));
//删除zip文件
file.delete();
//删除path临时文件夹
FileUtil.delete(path);
log.info("删除临时文件:{}{}", zipPath, path);
//异步统计下载次数
CompletableFuture.runAsync(() -> {
log.info("=======>ip:{} 下载模板:{}", RequestUtil.getIpAddr(request), reportCode);
reportService.downloadStatistics(reportCode);
});
return body;
}
/**
* 导入大屏zip
*
* @param file
* @param reportCode
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void importDashboard(MultipartFile file, String reportCode) {
log.info("导入开始,{}", reportCode);
//1.组装临时目录,/app/disk/upload/zip/临时文件夹
String path = dictPath + ZIP_PATH + UuidUtil.generateShortUuid();
//2.解压
FileUtil.decompress(file, path);
// path/uuid/
File parentPath = new File(path);
//获取打包的第一层目录
File firstFile = parentPath.listFiles()[0];
File[] files = firstFile.listFiles();
//定义map
Map<String, String> fileMap = new HashMap<>();
String content = "";
for (int i = 0; i < files.length; i++) {
File childFile = files[i];
if (JSON_PATH.equals(childFile.getName())) {
//json文件
content = FileUtil.readFile(childFile);
} else if ("image".equals(childFile.getName())) {
File[] imageFiles = childFile.listFiles();
//所有需要上传的图片
for (File imageFile : imageFiles) {
//查看是否存在此image
String fileName = imageFile.getName().split("\\.")[0];
//根据fileId从gaea_file中读出filePath
LambdaQueryWrapper<GaeaFile> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(GaeaFile::getFileId, fileName);
GaeaFile gaeaFile = gaeaFileService.selectOne(queryWrapper);
String uploadPath;
if (null == gaeaFile) {
GaeaFile upload = gaeaFileService.upload(imageFile);
log.info("存入图片: {}", upload.getFilePath());
uploadPath = upload.getUrlPath();
}else {
uploadPath = gaeaFile.getUrlPath();
}
fileMap.put(fileName, uploadPath);
}
}
}
//解析cotent
ReportDashboardObjectDto detail = JSONObject.parseObject(content, ReportDashboardObjectDto.class);
//将涉及到的图片路径替换1.背景图2.组件为图片的
String backgroundImage = detail.getDashboard().getBackgroundImage();
detail.getDashboard().setBackgroundImage(replaceUrl(backgroundImage, fileMap));
detail.getWidgets().stream()
.filter(reportDashboardWidgetDto -> "widget-image".equals(reportDashboardWidgetDto.getType()))
.forEach(reportDashboardWidgetDto -> {
String imageAddress = reportDashboardWidgetDto.getValue().getSetup().getString("imageAdress");
String address = replaceUrl(imageAddress, fileMap);
reportDashboardWidgetDto.getValue().getSetup().put("imageAdress", address);
reportDashboardWidgetDto.getOptions().getJSONArray("setup").getJSONObject(4).put("value", address);
});
//将新的大屏编码赋值
detail.setReportCode(reportCode);
//解析结束删除临时文件夹
FileUtil.delete(path);
log.info("解析成功,开始存入数据库...");
insertDashboard(detail);
}
private String replaceUrl(String imageAddress, Map<String, String> fileMap) {
if (StringUtils.isBlank(imageAddress)) {
return "";
}
String fileId = imageAddress.substring(imageAddress.trim().length() - 36);
String orDefault = fileMap.getOrDefault(fileId, null);
if (StringUtils.isBlank(orDefault)) {
return imageAddress;
}
return orDefault;
}
/**
* 将大屏涉及到的图片存入指定文件夹
* @param imageAddress
* @param path
*/
private void zipLoadImage(String imageAddress, String path) {
//http://10.108.26.197:9095/file/download/1d9bcd35-82a1-4f08-9465-b66b930b6a8d
if (imageAddress.trim().startsWith(fileDownloadPath)) {
//以fileDownloadPath为前缀的代表为上传的图片
String fileName = imageAddress.substring(fileDownloadPath.length() + 1);
//根据fileId从gaea_file中读出filePath
LambdaQueryWrapper<GaeaFile> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(GaeaFile::getFileId, fileName);
GaeaFile gaeaFile = gaeaFileService.selectOne(queryWrapper);
if (null != gaeaFile) {
byte[] file = gaeaFileService.getFile(gaeaFile.getFileId());
path = path + "/image/";
FileUtil.byte2File(file, path, gaeaFile.getFileId().concat(".").concat(gaeaFile.getFileType()));
}
}
}
public ChartStrategy getTarget(String type) {
for (String s : queryServiceImplMap.keySet()) {
if (s.contains(type)) {
return queryServiceImplMap.get(s);
}
}
throw BusinessExceptionBuilder.build(ResponseCode.RULE_CONTENT_NOT_EXIST);
}
@Override
public void afterPropertiesSet() {
Map<String, ChartStrategy> beanMap = applicationContext.getBeansOfType(ChartStrategy.class);
//遍历该接口的所有实现将其放入map中
for (ChartStrategy serviceImpl : beanMap.values()) {
queryServiceImplMap.put(serviceImpl.type(), serviceImpl);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 解析图层数据
*
* @param dto
*/
public void analysisData(ReportDashboardWidgetValueDto dto) {
// if (StringUtils.isBlank(reportDashboardWidgetDto.getSetCode())) {
// return;
// }
// DataSetDto dto = new DataSetDto();
// dto.setSetCode(reportDashboardWidgetDto.getSetCode());
// if (reportDashboardWidgetDto.getContextData() != null && reportDashboardWidgetDto.getContextData().size() > 0) {
// dto.setContextData(reportDashboardWidgetDto.getContextData());
// }
// OriginalDataDto data = dataSetService.getData(dto);
// reportDashboardWidgetDto.setData(JSONObject.toJSONString(data.getData()));
}
public List<JSONObject> buildTimeLine(List<JSONObject> data, ChartDto dto) {
Map<String, String> chartProperties = dto.getChartProperties();
if (null == chartProperties || chartProperties.size() < 1) {
return data;
}
Map<String, Object> contextData = dto.getContextData();
if (null == contextData || contextData.size() < 1) {
return data;
}
if (contextData.containsKey("startTime") && contextData.containsKey("endTime")) {
dto.setStartTime(contextData.get("startTime").toString());
dto.setEndTime(contextData.get("endTime").toString());
}
if (StringUtils.isBlank(dto.getStartTime()) || StringUtils.isBlank(dto.getEndTime())) {
return data;
}
//获取时间轴字段和解析时间颗粒度
for (Map.Entry<String, String> entry : chartProperties.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
dto.setParticles(value);
setTimeLineFormat(dto);
if (StringUtils.isNotBlank(dto.getDataTimeFormat())) {
dto.setTimeLineFiled(key);
break;
}
}
if (StringUtils.isBlank(dto.getDataTimeFormat())) {
return data;
}
Date beginTime = DateUtil.parseHmsTime(dto.getStartTime());
Date endTime = DateUtil.parseHmsTime(dto.getEndTime());
SimpleDateFormat showFormat = new SimpleDateFormat(dto.getTimeLineFormat());
SimpleDateFormat dataFormat = new SimpleDateFormat(dto.getDataTimeFormat());
Calendar calendar = Calendar.getInstance();
calendar.setTime(beginTime);
Calendar calendarEnd = Calendar.getInstance();
calendarEnd.setTime(endTime);
List<String> timeLine = new ArrayList<>();
List<String> dataTimeline = new ArrayList<>();
timeLine.add(showFormat.format(calendar.getTime()));
dataTimeline.add(dataFormat.format(calendar.getTime()));
//添加时间轴数据
while (true) {
calendar.add(dto.getTimeUnit(), 1);
timeLine.add(showFormat.format(calendar.getTime()));
dataTimeline.add(dataFormat.format(calendar.getTime()));
if (showFormat.format(calendar.getTime()).equals(showFormat.format(calendarEnd.getTime()))) {
break;
}
}
//根据时间轴生成对应的时间线数据不存在补数据
List<JSONObject> result = new ArrayList<>();
JSONObject jsonDemo = data.get(0);
String timeLineFiled = dto.getTimeLineFiled();
for (String dateFormat : dataTimeline) {
boolean flag = true;
for (JSONObject datum : data) {
if (datum.containsKey(timeLineFiled) && datum.getString(timeLineFiled).equals(dateFormat)) {
result.add(datum);
flag = false;
}
}
if (flag) {
//补数据
JSONObject json = new JSONObject();
jsonDemo.forEach((s, o) -> {
if (s.equals(timeLineFiled)) {
json.put(timeLineFiled, dateFormat);
} else {
json.put(s, 0);
}
});
result.add(json);
}
}
return result;
}
//设置时间格式
private void setTimeLineFormat(ChartDto dto) {
String particles = dto.getParticles();
if ("xAxis-hour".equals(particles)) {
dto.setDataTimeFormat("yyyy-MM-dd HH");
dto.setTimeLineFormat("MM-dd HH");
dto.setTimeUnit(Calendar.HOUR);
} else if ("xAxis-day".equals(particles)) {
dto.setDataTimeFormat("yyyy-MM-dd");
dto.setTimeLineFormat("yyyy-MM-dd");
dto.setTimeUnit(Calendar.DATE);
} else if ("xAxis-month".equals(particles)) {
dto.setDataTimeFormat("yyyy-MM");
dto.setTimeLineFormat("yyyy-MM");
dto.setTimeUnit(Calendar.MONTH);
} else if ("xAxis-year".equals(particles)) {
dto.setDataTimeFormat("yyyy");
dto.setTimeLineFormat("yyyy");
dto.setTimeUnit(Calendar.YEAR);
}
}
}

View File

@ -0,0 +1,34 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.io.Serializable;
/**
*
* @description 大屏看板数据渲染 dto
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@Data
public class ReportDashboardWidgetDto implements Serializable {
/**
* 组件类型参考字典DASHBOARD_PANEL_TYPE
*/
private String type;
/**
* value
*/
private ReportDashboardWidgetValueDto value;
/**
* options
*/
private JSONObject options;
}

View File

@ -0,0 +1,47 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.io.Serializable;
/**
*
* @description 大屏看板数据渲染 dto已弃用
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@Data
public class ReportDashboardWidgetValueDto implements Serializable {
/** 报表编码 */
private String reportCode;
/** 组件的渲染属性json */
private JSONObject setup;
/** 组件的数据属性json */
private JSONObject data;
/** 组件的配置属性json */
private JSONObject collapse;
/** 组件的大小位置属性json */
private JSONObject position;
private String options;
/** 自动刷新间隔秒 */
private Integer refreshSeconds;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DEL_FLAG */
private Integer deleteFlag;
/** 排序,图层的概念 */
private Long sort;
}

View File

@ -0,0 +1,20 @@
/**/
package com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.param;
import lombok.Data;
import java.io.Serializable;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import java.util.List;
/**
* @desc ReportDashboardWidget 大屏看板数据渲染查询输入类
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@Data
public class ReportDashboardWidgetParam extends PageParam implements Serializable{
}

View File

@ -0,0 +1,16 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.entity.ReportDashboardWidget;
/**
* ReportDashboardWidget Mapper
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@Mapper
public interface ReportDashboardWidgetMapper extends GaeaBaseMapper<ReportDashboardWidget> {
}

View File

@ -0,0 +1,50 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.entity;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description 大屏看板数据渲染 entity
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@TableName(keepGlobalPrefix=true, value="gaea_report_dashboard_widget")
@Data
public class ReportDashboardWidget extends GaeaBaseEntity {
@ApiModelProperty(value = "报表编码")
private String reportCode;
@ApiModelProperty(value = "组件类型参考字典DASHBOARD_PANEL_TYPE")
private String type;
@ApiModelProperty(value = "组件的渲染属性json")
private String setup;
@ApiModelProperty(value = "组件的数据属性json")
private String data;
@ApiModelProperty(value = "组件的配置属性json")
private String collapse;
@ApiModelProperty(value = "组件的大小位置属性json")
private String position;
private String options;
@ApiModelProperty(value = "自动刷新间隔秒")
private Integer refreshSeconds;
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
private Integer enableFlag;
@ApiModelProperty(value = " 0--未删除 1--已删除 DIC_NAME=DEL_FLAG")
private Integer deleteFlag;
@ApiModelProperty(value = "排序,图层的概念")
private Long sort;
}

View File

@ -0,0 +1,21 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.service;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.param.ReportDashboardWidgetParam;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.entity.ReportDashboardWidget;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
/**
* @desc ReportDashboardWidget 大屏看板数据渲染服务接口
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
public interface ReportDashboardWidgetService extends GaeaBaseService<ReportDashboardWidgetParam, ReportDashboardWidget> {
/***
* 查询详情
*
* @param id
*/
ReportDashboardWidget getDetail(Long id);
}

View File

@ -0,0 +1,34 @@
package com.anjiplus.template.gaea.business.modules.dashboardwidget.service.impl;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.entity.ReportDashboardWidget;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.service.ReportDashboardWidgetService;
import com.anjiplus.template.gaea.business.modules.dashboardwidget.dao.ReportDashboardWidgetMapper;
/**
* @desc ReportDashboardWidget 大屏看板数据渲染服务实现
* @author Raod
* @date 2021-04-12 15:12:43.724
**/
@Service
//@RequiredArgsConstructor
public class ReportDashboardWidgetServiceImpl implements ReportDashboardWidgetService {
@Autowired
private ReportDashboardWidgetMapper reportDashboardWidgetMapper;
@Override
public GaeaBaseMapper<ReportDashboardWidget> getMapper() {
return reportDashboardWidgetMapper;
}
@Override
public ReportDashboardWidget getDetail(Long id) {
ReportDashboardWidget reportDashboardWidget = this.selectOne(id);
return reportDashboardWidget;
}
}

View File

@ -0,0 +1,145 @@
package com.anjiplus.template.gaea.business.modules.dataset.controller;
import com.anji.plus.gaea.annotation.AccessKey;
import com.anji.plus.gaea.annotation.Permission;
import com.anji.plus.gaea.annotation.log.GaeaAuditLog;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anji.plus.gaea.holder.UserContentHolder;
import com.anji.plus.gaea.utils.GaeaUtils;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.DataSetDto;
import com.anjiplus.template.gaea.business.modules.dataset.controller.param.DataSetParam;
import com.anjiplus.template.gaea.business.modules.dataset.controller.param.DataSetTestTransformParam;
import com.anjiplus.template.gaea.business.modules.dataset.dao.entity.DataSet;
import com.anjiplus.template.gaea.business.modules.dataset.service.DataSetService;
import io.swagger.annotations.Api;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* @desc 数据集 controller
* @website https://gitee.com/anji-plus/gaea
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@RestController
@Api(tags = "数据集管理")
@Permission(code = "resultsetManage", name = "数据集管理")
@RequestMapping("/dataSet")
public class DataSetController extends GaeaBaseController<DataSetParam, DataSet, DataSetDto> {
@Autowired
private DataSetService dataSetService;
@Override
public GaeaBaseService<DataSetParam, DataSet> getService() {
return dataSetService;
}
@Override
public DataSet getEntity() {
return new DataSet();
}
@Override
public DataSetDto getDTO() {
return new DataSetDto();
}
@GetMapping("/detailBysetId/{id}")
@Permission( code = "query", name = "明细" )
public ResponseBean detailBysetId(@PathVariable("id") Long id) {
this.logger.info("{}根据ID查询服务开始id为{}", this.getClass().getSimpleName(), id);
ResponseBean responseBean = this.responseSuccessWithData(dataSetService.detailSet(id));
this.logger.info("{}根据ID查询结束结果{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(responseBean));
return responseBean;
}
@GetMapping({"/detailBysetCode/{setCode}"})
@Permission( code = "query", name = "明细" )
@AccessKey
public ResponseBean detailBysetCode(@PathVariable("setCode") String setCode) {
this.logger.info("{}根据setCode查询服务开始setCode为{}", this.getClass().getSimpleName(), setCode);
ResponseBean responseBean = this.responseSuccessWithData(dataSetService.detailSet(setCode));
this.logger.info("{}根据setCode查询结束结果{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(responseBean));
return responseBean;
}
@PostMapping
@Permission(
code = "insert",
name = "新增"
)
@GaeaAuditLog(
pageTitle = "新增"
)
@Override
public ResponseBean insert(@RequestBody DataSetDto dto) {
this.logger.info("{}新增服务开始,参数:{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(dto));
DataSetDto dataSetDto = dataSetService.insertSet(dto);
this.logger.info("{}新增服务结束,结果:{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(dataSetDto));
return ResponseBean.builder().data(dataSetDto).build();
}
@PutMapping
@Permission(
code = "update",
name = "更新"
)
@GaeaAuditLog(
pageTitle = "修改"
)
@Override
public ResponseBean update(@RequestBody DataSetDto dto) {
String username = UserContentHolder.getContext().getUsername();
this.logger.info("{}更新服务开始,更新人:{},参数:{}", this.getClass().getSimpleName(), username, GaeaUtils.toJSONString(dto));
ResponseBean responseBean = this.responseSuccess();
dataSetService.updateSet(dto);
this.logger.info("{}更新服务结束,结果:{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(responseBean));
return this.responseSuccess();
}
@DeleteMapping({"/{id}"})
@Permission(
code = "delete",
name = "删除"
)
@GaeaAuditLog(
pageTitle = "删除"
)
@Override
public ResponseBean deleteById(@PathVariable("id") Long id) {
this.logger.info("{}删除服务开始参数ID{}", this.getClass().getSimpleName(), id);
dataSetService.deleteSet(id);
this.logger.info("{}删除服务结束", this.getClass().getSimpleName());
return this.responseSuccess();
}
/**
* 测试 数据转换是否正确
* @param param
* @return
*/
@PostMapping("/testTransform")
@Permission( code = "query", name = "明细" )
public ResponseBean testTransform(@Validated @RequestBody DataSetTestTransformParam param) {
DataSetDto dto = new DataSetDto();
BeanUtils.copyProperties(param, dto);
return responseSuccessWithData(dataSetService.testTransform(dto));
}
/**
* 获取所有数据集
* @return
*/
@GetMapping("/queryAllDataSet")
public ResponseBean queryAllDataSet() {
return responseSuccessWithData(dataSetService.queryAllDataSet());
}
}

View File

@ -0,0 +1,65 @@
package com.anjiplus.template.gaea.business.modules.dataset.controller.dto;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto.DataSetParamDto;
import com.anjiplus.template.gaea.business.modules.datasettransform.controller.dto.DataSetTransformDto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
*
* @description 数据集 dto
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@Data
public class DataSetDto extends GaeaBaseDTO implements Serializable {
/** 数据集编码 */
private String setCode;
/** 数据集名称 */
private String setName;
/** 数据集描述 */
private String setDesc;
/** 数据集类型 */
private String setType;
/** 数据源编码 */
private String sourceCode;
/** 动态查询sql或者接口中的请求体 */
private String dynSentence;
/** 结果案例 */
private String caseResult;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DELETE_FLAG */
private Integer deleteFlag;
/** 请求参数集合 */
private List<DataSetParamDto> dataSetParamDtoList;
/** 数据转换集合 */
private List<DataSetTransformDto> dataSetTransformDtoList;
/** 传入的自定义参数*/
private Map<String, Object> contextData;
private Set<String> setParamList;
/**指定字段*/
private String fieldLabel;
}

View File

@ -0,0 +1,32 @@
package com.anjiplus.template.gaea.business.modules.dataset.controller.dto;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* Created by raodeming on 2021/3/26.
*/
@Data
public class OriginalDataDto implements Serializable {
/**总数*/
private long total;
/**获取的数据详情*/
private List<JSONObject> data;
public OriginalDataDto(List<JSONObject> data) {
this.data = data;
}
public OriginalDataDto(long total, List<JSONObject> data) {
this.total = total;
this.data = data;
}
public OriginalDataDto() {
}
}

View File

@ -0,0 +1,34 @@
/**/
package com.anjiplus.template.gaea.business.modules.dataset.controller.param;
import com.anji.plus.gaea.annotation.Query;
import com.anji.plus.gaea.constant.QueryEnum;
import com.anji.plus.gaea.curd.params.PageParam;
import lombok.Data;
import java.io.Serializable;
/**
* @desc DataSet 数据集查询输入类
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@Data
public class DataSetParam extends PageParam implements Serializable{
/** 数据集编码 */
@Query(QueryEnum.LIKE)
private String setCode;
/** 数据集名称 */
@Query(QueryEnum.LIKE)
private String setName;
/** 数据源编码 */
@Query(QueryEnum.EQ)
private String sourceCode;
/** 数据集类型 */
@Query(QueryEnum.EQ)
private String setType;
}

View File

@ -0,0 +1,36 @@
/**/
package com.anjiplus.template.gaea.business.modules.dataset.controller.param;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto.DataSetParamDto;
import com.anjiplus.template.gaea.business.modules.datasettransform.controller.dto.DataSetTransformDto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.List;
/**
* @desc DataSet 数据集查询输入类
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@Data
public class DataSetTestTransformParam implements Serializable{
/** 数据源编码 */
private String sourceCode;
/** 动态查询sql或者接口中的请求体 */
private String dynSentence;
/** 数据集类型 */
private String setType;
/** 请求参数集合 */
private List<DataSetParamDto> dataSetParamDtoList;
/** 数据转换集合 */
private List<DataSetTransformDto> dataSetTransformDtoList;
}

View File

@ -0,0 +1,16 @@
package com.anjiplus.template.gaea.business.modules.dataset.dao;
import org.apache.ibatis.annotations.Mapper;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.dataset.dao.entity.DataSet;
/**
* DataSet Mapper
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@Mapper
public interface DataSetMapper extends GaeaBaseMapper<DataSet> {
}

View File

@ -0,0 +1,48 @@
package com.anjiplus.template.gaea.business.modules.dataset.dao.entity;
import com.anji.plus.gaea.annotation.Unique;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description 数据集 entity
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@TableName(keepGlobalPrefix=true, value="gaea_report_data_set")
@Data
public class DataSet extends GaeaBaseEntity {
@ApiModelProperty(value = "数据集编码")
@Unique(code = ResponseCode.SET_CODE_ISEXIST)
private String setCode;
@ApiModelProperty(value = "数据集名称")
private String setName;
@ApiModelProperty(value = "数据集描述")
private String setDesc;
@ApiModelProperty(value = "数据集类型")
private String setType;
@ApiModelProperty(value = "数据源编码")
private String sourceCode;
@ApiModelProperty(value = "动态查询sql或者接口中的请求体")
private String dynSentence;
@ApiModelProperty(value = "结果案例")
private String caseResult;
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
private Integer enableFlag;
@ApiModelProperty(value = "0--未删除 1--已删除 DIC_NAME=DELETE_FLAG")
private Integer deleteFlag;
}

View File

@ -0,0 +1,70 @@
package com.anjiplus.template.gaea.business.modules.dataset.service;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.DataSetDto;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.OriginalDataDto;
import com.anjiplus.template.gaea.business.modules.dataset.controller.param.DataSetParam;
import com.anjiplus.template.gaea.business.modules.dataset.dao.entity.DataSet;
import java.util.List;
/**
* @desc DataSet 数据集服务接口
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
public interface DataSetService extends GaeaBaseService<DataSetParam, DataSet> {
/**
* 单条详情
* @param id
* @return
*/
DataSetDto detailSet(Long id);
/**
* 单条详情
* @param setCode
* @return
*/
DataSetDto detailSet(String setCode);
/**
* 新增数据集添加查询参数数据转换
* @param dto
*/
DataSetDto insertSet(DataSetDto dto);
/**
* 更新数据集添加查询参数数据转换
* @param dto
*/
void updateSet(DataSetDto dto);
/**
* 删除数据集添加查询参数数据转换
* @param id
*/
void deleteSet(Long id);
/**
* 获取数据
* @param dto
* @return
*/
OriginalDataDto getData(DataSetDto dto);
/**
*
* @param dto
* @return
*/
OriginalDataDto testTransform(DataSetDto dto);
/**
* 获取所有数据集
* @return
*/
List<DataSet> queryAllDataSet();
}

View File

@ -0,0 +1,439 @@
package com.anjiplus.template.gaea.business.modules.dataset.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.anjiplus.template.gaea.business.enums.SetTypeEnum;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.OriginalDataDto;
import com.anjiplus.template.gaea.business.modules.dataset.controller.dto.DataSetDto;
import com.anjiplus.template.gaea.business.modules.dataset.dao.DataSetMapper;
import com.anjiplus.template.gaea.business.modules.dataset.dao.entity.DataSet;
import com.anjiplus.template.gaea.business.modules.dataset.service.DataSetService;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto.DataSetParamDto;
import com.anjiplus.template.gaea.business.modules.datasetparam.dao.entity.DataSetParam;
import com.anjiplus.template.gaea.business.modules.datasetparam.service.DataSetParamService;
import com.anjiplus.template.gaea.business.modules.datasettransform.controller.dto.DataSetTransformDto;
import com.anjiplus.template.gaea.business.modules.datasettransform.dao.entity.DataSetTransform;
import com.anjiplus.template.gaea.business.modules.datasettransform.service.DataSetTransformService;
import com.anjiplus.template.gaea.business.modules.datasource.controller.dto.DataSourceDto;
import com.anjiplus.template.gaea.business.modules.datasource.dao.entity.DataSource;
import com.anjiplus.template.gaea.business.modules.datasource.service.DataSourceService;
import com.anjiplus.template.gaea.business.util.JdbcConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Raod
* @desc DataSet 数据集服务实现
* @date 2021-03-18 12:11:31.150755900
**/
@Service
//@RequiredArgsConstructor
@Slf4j
public class DataSetServiceImpl implements DataSetService {
@Autowired
private DataSetMapper dataSetMapper;
@Autowired
private DataSetParamService dataSetParamService;
@Autowired
private DataSetTransformService dataSetTransformService;
@Autowired
private DataSourceService dataSourceService;
@Override
public GaeaBaseMapper<DataSet> getMapper() {
return dataSetMapper;
}
/**
* 单条详情
*
* @param id
* @return
*/
@Override
public DataSetDto detailSet(Long id) {
DataSetDto dto = new DataSetDto();
DataSet result = selectOne(id);
String setCode = result.getSetCode();
GaeaBeanUtils.copyAndFormatter(result, dto);
return getDetailSet(dto, setCode);
}
/**
* 单条详情
*
* @param setCode
* @return
*/
@Override
public DataSetDto detailSet(String setCode) {
DataSetDto dto = new DataSetDto();
DataSet result = selectOne("set_code", setCode);
GaeaBeanUtils.copyAndFormatter(result, dto);
return getDetailSet(dto, setCode);
}
public DataSetDto getDetailSet(DataSetDto dto, String setCode) {
//查询参数
List<DataSetParam> dataSetParamList = dataSetParamService.list(
new QueryWrapper<DataSetParam>()
.lambda()
.eq(DataSetParam::getSetCode, setCode)
);
List<DataSetParamDto> dataSetParamDtoList = new ArrayList<>();
dataSetParamList.forEach(dataSetParam -> {
DataSetParamDto dataSetParamDto = new DataSetParamDto();
GaeaBeanUtils.copyAndFormatter(dataSetParam, dataSetParamDto);
dataSetParamDtoList.add(dataSetParamDto);
});
dto.setDataSetParamDtoList(dataSetParamDtoList);
//数据转换
List<DataSetTransform> dataSetTransformList = dataSetTransformService.list(
new QueryWrapper<DataSetTransform>()
.lambda()
.eq(DataSetTransform::getSetCode, setCode)
.orderByAsc(DataSetTransform::getOrderNum)
);
List<DataSetTransformDto> dataSetTransformDtoList = new ArrayList<>();
dataSetTransformList.forEach(dataSetTransform -> {
DataSetTransformDto dataSetTransformDto = new DataSetTransformDto();
GaeaBeanUtils.copyAndFormatter(dataSetTransform, dataSetTransformDto);
dataSetTransformDtoList.add(dataSetTransformDto);
});
dto.setDataSetTransformDtoList(dataSetTransformDtoList);
if (StringUtils.isNotBlank(dto.getCaseResult())) {
try {
JSONArray jsonArray = JSONArray.parseArray(dto.getCaseResult());
JSONObject jsonObject = jsonArray.getJSONObject(0);
dto.setSetParamList(jsonObject.keySet());
} catch (Exception e) {
log.error("error", e);
}
}
return dto;
}
/**
* 新增数据集添加查询参数数据转换
*
* @param dto
*/
@Override
@Transactional
public DataSetDto insertSet(DataSetDto dto) {
List<DataSetParamDto> dataSetParamDtoList = dto.getDataSetParamDtoList();
List<DataSetTransformDto> dataSetTransformDtoList = dto.getDataSetTransformDtoList();
//1.新增数据集
DataSet dataSet = new DataSet();
BeanUtils.copyProperties(dto, dataSet);
if (StringUtils.isNotBlank(dataSet.getCaseResult())) {
try {
JSONArray objects = JSONObject.parseArray(dataSet.getCaseResult());
if (objects.size() > 1) {
Object o = objects.get(0);
objects = new JSONArray();
objects.add(o);
dataSet.setCaseResult(JSON.toJSONString(objects, SerializerFeature.WriteMapNullValue));
}
} catch (Exception e) {
log.info("结果集只保留一行数据失败...{}", e.getMessage());
}
}
insert(dataSet);
//2.更新查询参数
dataSetParamBatch(dataSetParamDtoList, dto.getSetCode());
//3.更新数据转换
dataSetTransformBatch(dataSetTransformDtoList, dto.getSetCode());
return dto;
}
/**
* 更新数据集添加查询参数数据转换
*
* @param dto
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSet(DataSetDto dto) {
List<DataSetParamDto> dataSetParamDtoList = dto.getDataSetParamDtoList();
List<DataSetTransformDto> dataSetTransformDtoList = dto.getDataSetTransformDtoList();
//1.更新数据集
DataSet dataSet = new DataSet();
BeanUtils.copyProperties(dto, dataSet);
if (StringUtils.isNotBlank(dataSet.getCaseResult())) {
try {
JSONArray objects = JSONObject.parseArray(dataSet.getCaseResult());
if (objects.size() > 1) {
Object o = objects.get(0);
objects = new JSONArray();
objects.add(o);
dataSet.setCaseResult(JSON.toJSONString(objects, SerializerFeature.WriteMapNullValue));
}
} catch (Exception e) {
log.info("结果集只保留一行数据失败...{}", e.getMessage());
}
}
update(dataSet);
//2.更新查询参数
dataSetParamBatch(dataSetParamDtoList, dto.getSetCode());
//3.更新数据转换
dataSetTransformBatch(dataSetTransformDtoList, dto.getSetCode());
}
/**
* 删除数据集添加查询参数数据转换
*
* @param id
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteSet(Long id) {
DataSet dataSet = selectOne(id);
String setCode = dataSet.getSetCode();
//1.删除数据集
deleteById(id);
//2.删除查询参数
dataSetParamService.delete(
new QueryWrapper<DataSetParam>()
.lambda()
.eq(DataSetParam::getSetCode, setCode)
);
//3.删除数据转换
dataSetTransformService.delete(
new QueryWrapper<DataSetTransform>()
.lambda()
.eq(DataSetTransform::getSetCode, setCode)
);
}
/**
* 获取数据
*
* @param dto
* @return
*/
@Override
public OriginalDataDto getData(DataSetDto dto) {
OriginalDataDto originalDataDto = new OriginalDataDto();
String setCode = dto.getSetCode();
if (StringUtils.isBlank(setCode)) {
return new OriginalDataDto(new ArrayList<>());
}
//1.获取数据集参数替换数据转换
DataSetDto dataSetDto = detailSet(setCode);
String dynSentence = dataSetDto.getDynSentence();
//2.获取数据源
DataSource dataSource;
if (StringUtils.isNotBlank(dataSetDto.getSetType())
&& dataSetDto.getSetType().equals(SetTypeEnum.HTTP.getCodeValue())) {
//http不需要数据源兼容已有的逻辑将http所需要的数据塞进DataSource
dataSource = new DataSource();
dataSource.setSourceConfig(dynSentence);
dataSource.setSourceType(JdbcConstants.HTTP);
String body = JSONObject.parseObject(dynSentence).getString("body");
if (StringUtils.isNotBlank(body)) {
dynSentence = body;
} else {
dynSentence = "{}";
}
} else {
dataSource = dataSourceService.selectOne("source_code", dataSetDto.getSourceCode());
}
//3.参数替换
//3.1参数校验
log.debug("参数校验替换前:{}", dto.getContextData());
boolean verification = dataSetParamService.verification(dataSetDto.getDataSetParamDtoList(), dto.getContextData());
if (!verification) {
throw BusinessExceptionBuilder.build(ResponseCode.RULE_FIELDS_CHECK_ERROR);
}
dynSentence = dataSetParamService.transform(dto.getContextData(), dynSentence);
log.debug("参数校验替换后:{}", dto.getContextData());
//4.获取数据
DataSourceDto dataSourceDto = new DataSourceDto();
BeanUtils.copyProperties(dataSource, dataSourceDto);
dataSourceDto.setDynSentence(dynSentence);
dataSourceDto.setContextData(dto.getContextData());
//获取total,判断contextData中是否传入分页参数
if (null != dto.getContextData()
&& dto.getContextData().containsKey("pageNumber")
&& dto.getContextData().containsKey("pageSize")) {
long total = dataSourceService.total(dataSourceDto, dto);
originalDataDto.setTotal(total);
}
List<JSONObject> data = dataSourceService.execute(dataSourceDto);
//5.数据转换
List<JSONObject> transform = dataSetTransformService.transform(dataSetDto.getDataSetTransformDtoList(), data);
originalDataDto.setData(transform);
return originalDataDto;
}
/**
* @param dto
* @return
*/
@Override
public OriginalDataDto testTransform(DataSetDto dto) {
String dynSentence = dto.getDynSentence();
OriginalDataDto originalDataDto = new OriginalDataDto();
String sourceCode = dto.getSourceCode();
//1.获取数据源
DataSource dataSource;
if (dto.getSetType().equals(SetTypeEnum.HTTP.getCodeValue())) {
//http不需要数据源兼容已有的逻辑将http所需要的数据塞进DataSource
dataSource = new DataSource();
dataSource.setSourceConfig(dynSentence);
dataSource.setSourceType(JdbcConstants.HTTP);
String body = JSONObject.parseObject(dynSentence).getString("body");
if (StringUtils.isNotBlank(body)) {
dynSentence = body;
} else {
dynSentence = "{}";
}
} else {
dataSource = dataSourceService.selectOne("source_code", sourceCode);
}
//3.参数替换
//3.1参数校验
boolean verification = dataSetParamService.verification(dto.getDataSetParamDtoList(), null);
if (!verification) {
throw BusinessExceptionBuilder.build(ResponseCode.RULE_FIELDS_CHECK_ERROR);
}
dynSentence = dataSetParamService.transform(dto.getDataSetParamDtoList(), dynSentence);
//4.获取数据
DataSourceDto dataSourceDto = new DataSourceDto();
BeanUtils.copyProperties(dataSource, dataSourceDto);
dataSourceDto.setDynSentence(dynSentence);
dataSourceDto.setContextData(setContextData(dto.getDataSetParamDtoList()));
//获取total,判断DataSetParamDtoList中是否传入分页参数
Map<String, Object> collect = dto.getDataSetParamDtoList().stream().collect(Collectors.toMap(DataSetParamDto::getParamName, DataSetParamDto::getSampleItem));
if (collect.containsKey("pageNumber") && collect.containsKey("pageSize")) {
dto.setContextData(collect);
long total = dataSourceService.total(dataSourceDto, dto);
originalDataDto.setTotal(total);
}
List<JSONObject> data = dataSourceService.execute(dataSourceDto);
//5.数据转换
List<JSONObject> transform = dataSetTransformService.transform(dto.getDataSetTransformDtoList(), data);
originalDataDto.setData(transform);
return originalDataDto;
}
/**
* 获取所有数据集
*
* @return
*/
@Override
public List<DataSet> queryAllDataSet() {
LambdaQueryWrapper<DataSet> wrapper = Wrappers.lambdaQuery();
wrapper.select(DataSet::getSetCode, DataSet::getSetName, DataSet::getSetDesc, DataSet::getId)
.eq(DataSet::getEnableFlag, Enabled.YES.getValue());
wrapper.orderByDesc(DataSet::getUpdateTime);
return dataSetMapper.selectList(wrapper);
}
public void dataSetParamBatch(List<DataSetParamDto> dataSetParamDtoList, String setCode) {
dataSetParamService.delete(
new QueryWrapper<DataSetParam>()
.lambda()
.eq(DataSetParam::getSetCode, setCode)
);
if (null == dataSetParamDtoList || dataSetParamDtoList.size() <= 0) {
return;
}
// List<DataSetParam> dataSetParamList = new ArrayList<>();
dataSetParamDtoList.forEach(dataSetParamDto -> {
DataSetParam dataSetParam = new DataSetParam();
BeanUtils.copyProperties(dataSetParamDto, dataSetParam);
dataSetParam.setSetCode(setCode);
//不采用批量
dataSetParamService.insert(dataSetParam);
// dataSetParamList.add(dataSetParam);
});
// dataSetParamService.insertBatch(dataSetParamList);
}
public void dataSetTransformBatch(List<DataSetTransformDto> dataSetTransformDtoList, String setCode) {
dataSetTransformService.delete(
new QueryWrapper<DataSetTransform>()
.lambda()
.eq(DataSetTransform::getSetCode, setCode)
);
if (null == dataSetTransformDtoList || dataSetTransformDtoList.size() <= 0) {
return;
}
// List<DataSetTransform> dataSetTransformList = new ArrayList<>();
for (int i = 0; i < dataSetTransformDtoList.size(); i++) {
DataSetTransform dataSetTransform = new DataSetTransform();
BeanUtils.copyProperties(dataSetTransformDtoList.get(i), dataSetTransform);
dataSetTransform.setOrderNum(i + 1);
dataSetTransform.setSetCode(setCode);
//不采用批量
dataSetTransformService.insert(dataSetTransform);
// dataSetTransformList.add(dataSetTransform);
}
// dataSetTransformService.insertBatch(dataSetTransformList);
}
/**
* dataSetParamDtoList转map
*
* @param dataSetParamDtoList
* @return
*/
public Map<String, Object> setContextData(List<DataSetParamDto> dataSetParamDtoList) {
Map<String, Object> map = new HashMap<>();
if (null != dataSetParamDtoList && dataSetParamDtoList.size() > 0) {
dataSetParamDtoList.forEach(dataSetParamDto -> map.put(dataSetParamDto.getParamName(), dataSetParamDto.getSampleItem()));
}
return map;
}
}

View File

@ -0,0 +1,61 @@
package com.anjiplus.template.gaea.business.modules.datasetparam.controller;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.curd.controller.GaeaBaseController;
import com.anji.plus.gaea.curd.service.GaeaBaseService;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto.DataSetParamDto;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.param.DataSetParamParam;
import com.anjiplus.template.gaea.business.modules.datasetparam.controller.param.DataSetParamValidationParam;
import com.anjiplus.template.gaea.business.modules.datasetparam.dao.entity.DataSetParam;
import com.anjiplus.template.gaea.business.modules.datasetparam.service.DataSetParamService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc 数据集动态参数 controller
* @website https://gitee.com/anji-plus/gaea
* @author Raod
* @date 2021-03-18 12:12:33.108033200
**/
@RestController
@Api(tags = "数据集动态参数管理")
@RequestMapping("/dataSetParam")
public class DataSetParamController extends GaeaBaseController<DataSetParamParam, DataSetParam, DataSetParamDto> {
@Autowired
private DataSetParamService dataSetParamService;
@Override
public GaeaBaseService<DataSetParamParam, DataSetParam> getService() {
return dataSetParamService;
}
@Override
public DataSetParam getEntity() {
return new DataSetParam();
}
@Override
public DataSetParamDto getDTO() {
return new DataSetParamDto();
}
/**
* 测试 查询参数是否正确
* @param param
* @return
*/
@PostMapping("/verification")
public ResponseBean verification(@Validated @RequestBody DataSetParamValidationParam param) {
DataSetParamDto dto = new DataSetParamDto();
dto.setSampleItem(param.getSampleItem());
dto.setValidationRules(param.getValidationRules());
return responseSuccessWithData(dataSetParamService.verification(dto));
}
}

View File

@ -0,0 +1,48 @@
package com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto;
import com.anji.plus.gaea.curd.dto.GaeaBaseDTO;
import lombok.Data;
import java.io.Serializable;
/**
*
* @description 数据集动态参数 dto
* @author Raod
* @date 2021-03-18 12:12:33.108033200
**/
@Data
public class DataSetParamDto extends GaeaBaseDTO implements Serializable {
/** 数据集编码 */
private String setCode;
/** 参数名 */
private String paramName;
/** 参数描述 */
private String paramDesc;
/** 参数类型,字典= */
private String paramType;
/** 参数示例项 */
private String sampleItem;
/** 0--非必填 1--必填 DIC_NAME=REQUIRED_FLAG */
private Integer requiredFlag;
/** js校验字段值规则满足校验返回 true */
private String validationRules;
/** 排序 */
private Integer orderNum;
/** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */
private Integer enableFlag;
/** 0--未删除 1--已删除 DIC_NAME=DELETE_FLAG */
private Integer deleteFlag;
}

View File

@ -0,0 +1,17 @@
/**/
package com.anjiplus.template.gaea.business.modules.datasetparam.controller.param;
import com.anji.plus.gaea.curd.params.PageParam;
import lombok.Data;
import java.io.Serializable;
/**
* @desc DataSetParam 数据集动态参数查询输入类
* @author Raod
* @date 2021-03-18 12:12:33.108033200
**/
@Data
public class DataSetParamParam extends PageParam implements Serializable{
}

View File

@ -0,0 +1,22 @@
package com.anjiplus.template.gaea.business.modules.datasetparam.controller.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* Created by raodeming on 2021/3/24.
*/
@Data
public class DataSetParamValidationParam implements Serializable {
/** 参数示例项 */
@NotBlank(message = "sampleItem not empty")
private String sampleItem;
/** js校验字段值规则满足校验返回 true */
@NotBlank(message = "validationRules not empty")
private String validationRules;
}

View File

@ -0,0 +1,15 @@
package com.anjiplus.template.gaea.business.modules.datasetparam.dao;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.business.modules.datasetparam.dao.entity.DataSetParam;
import org.apache.ibatis.annotations.Mapper;
/**
* DataSetParam Mapper
* @author Raod
* @date 2021-03-18 12:12:33.108033200
**/
@Mapper
public interface DataSetParamMapper extends GaeaBaseMapper<DataSetParam> {
}

View File

@ -0,0 +1,48 @@
package com.anjiplus.template.gaea.business.modules.datasetparam.dao.entity;
import com.anji.plus.gaea.curd.entity.GaeaBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @description 数据集动态参数 entity
* @author Raod
* @date 2021-03-18 12:12:33.108033200
**/
@TableName(keepGlobalPrefix=true, value="gaea_report_data_set_param")
@Data
public class DataSetParam extends GaeaBaseEntity {
@ApiModelProperty(value = "数据集编码")
private String setCode;
@ApiModelProperty(value = "参数名")
private String paramName;
@ApiModelProperty(value = "参数描述")
private String paramDesc;
@ApiModelProperty(value = "参数类型,字典=")
private String paramType;
@ApiModelProperty(value = "参数示例项")
private String sampleItem;
@ApiModelProperty(value = "0--非必填 1--必填 DIC_NAME=REQUIRED_FLAG")
private Integer requiredFlag;
@ApiModelProperty(value = "js校验字段值规则满足校验返回 true")
private String validationRules;
@ApiModelProperty(value = "排序")
private Integer orderNum;
@ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG")
private Integer enableFlag;
@ApiModelProperty(value = "0--未删除 1--已删除 DIC_NAME=DELETE_FLAG")
private Integer deleteFlag;
}

Some files were not shown because too many files have changed in this diff Show More