Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	backend/src/main/resources/db/migration/V27__de1.4.sql
This commit is contained in:
wangjiahao 2021-10-28 17:05:50 +08:00
commit 1a5159f40d
75 changed files with 1965 additions and 585 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>dataease-server</artifactId>
<groupId>io.dataease</groupId>
<version>1.3.0</version>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -201,7 +201,7 @@
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-interface</artifactId>
<version>1.3</version>
<version>1.4</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>

View File

@ -5,6 +5,9 @@ import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.auth.api.dto.LoginDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import springfox.documentation.annotations.ApiIgnore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -49,4 +52,12 @@ public interface AuthApi {
@PostMapping("/isOpenOidc")
boolean isOpenOidc();
@ApiIgnore
@PostMapping("/isPluginLoaded")
boolean isPluginLoaded();
@ApiIgnore
@GetMapping("/getPublicKey")
String getPublicKey();
}

View File

@ -10,10 +10,7 @@ import io.dataease.auth.entity.TokenInfo;
import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.util.JWTUtils;
import io.dataease.auth.util.RsaUtil;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.commons.utils.CodingUtil;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.commons.utils.*;
import io.dataease.controller.sys.request.LdapAddRequest;
import io.dataease.exception.DataEaseException;
import io.dataease.i18n.Translator;
@ -55,10 +52,9 @@ public class AuthServer implements AuthApi {
@Override
public Object login(@RequestBody LoginDto loginDto) throws Exception {
String username = loginDto.getUsername();
String password = loginDto.getPassword();
String username = RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, loginDto.getUsername());;
String pwd = RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, loginDto.getPassword());
String pwd = RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, password);
// 增加ldap登录方式
Integer loginType = loginDto.getLoginType();
boolean isSupportLdap = authUserService.supportLdap();
@ -184,6 +180,18 @@ public class AuthServer implements AuthApi {
return authUserService.supportOidc();
}
@Override
public boolean isPluginLoaded() {
Boolean licValid = PluginUtils.licValid();
if(!licValid) return false;
return authUserService.pluginLoaded();
}
@Override
public String getPublicKey() {
return RsaProperties.publicKey;
}
/*@Override

View File

@ -29,6 +29,8 @@ public interface AuthUserService {
Boolean supportOidc();
Boolean pluginLoaded();
}

View File

@ -8,6 +8,7 @@ import io.dataease.base.mapper.ext.AuthMapper;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.utils.LogUtil;
import io.dataease.plugins.common.service.PluginCommonService;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.ldap.service.LdapXpackService;
import io.dataease.plugins.xpack.oidc.service.OidcXpackService;
@ -137,5 +138,16 @@ public class AuthUserServiceImpl implements AuthUserService {
return oidcXpackService.isSuuportOIDC();
}
@Override
public Boolean pluginLoaded() {
Map<String, PluginCommonService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((PluginCommonService.class));
if(beansOfType.keySet().size() == 0) return false;
PluginCommonService pluginCommonService = SpringContextUtil.getBean(PluginCommonService.class);
if(ObjectUtils.isEmpty(pluginCommonService)) return false;
return pluginCommonService.isPluginLoaded();
}
}

View File

@ -56,10 +56,11 @@ public class ShiroServiceImpl implements ShiroService {
// filterChainDefinitionMap.put("/axios.map", ANON);
filterChainDefinitionMap.put("/api/auth/login", ANON);
// filterChainDefinitionMap.put("/api/auth/logout", ANON);
filterChainDefinitionMap.put("/system/requestTimeOut", ANON);
filterChainDefinitionMap.put("/api/auth/validateName", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenLdap", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenOidc", ANON);
filterChainDefinitionMap.put("/api/auth/getPublicKey", ANON);
filterChainDefinitionMap.put("/api/pluginCommon/component/*", ANON);
filterChainDefinitionMap.put("/plugin/oidc/authInfo", ANON);
filterChainDefinitionMap.put("/sso/callBack*", ANON);

View File

@ -109,6 +109,18 @@ public interface ParamConstants {
}
}
enum BASIC implements ParamConstants {
FRONT_TIME_OUT("basic.frontTimeOut"),
MSG_TIME_OUT("basic.msgTimeOut");
private String value;
public String getValue() {
return this.value;
}
private BASIC(String value) {
this.value = value;
}
}
enum BASE implements ParamConstants {
URL("base.url");

View File

@ -7,22 +7,26 @@ import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -42,11 +46,15 @@ public class HttpClientUtil {
private static CloseableHttpClient buildHttpClient(String url) {
try {
if (url.startsWith(HTTPS)) {
// https 增加信任设置
TrustStrategy trustStrategy = new TrustSelfSignedStrategy();
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStrategy).build();
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
return HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier(hostnameVerifier).build();
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, (X509Certificate[] x509Certificates, String s) -> true);
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), new String[]{"TLSv1.1", "TLSv1.2", "SSLv3"}, null, NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", socketFactory).build();
HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).build();
return httpClient;
} else {
// http
return HttpClientBuilder.create().build();

View File

@ -42,8 +42,9 @@ public class MsgController {
List<SysMsgType> sysMsgTypes = sysMsgService.queryMsgTypes();
typeIds = sysMsgTypes.stream().filter(sysMsgType -> msgRequest.getType() == sysMsgType.getPid()).map(SysMsgType::getMsgTypeId).collect(Collectors.toList());
}
Long overTime = sysMsgService.overTime();
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
Pager<List<MsgGridDto>> listPager = PageUtils.setPageInfo(page, sysMsgService.queryGrid(userId, msgRequest, typeIds));
Pager<List<MsgGridDto>> listPager = PageUtils.setPageInfo(page, sysMsgService.queryGrid(userId, msgRequest, typeIds, overTime));
return listPager;
}

View File

@ -2,9 +2,13 @@ package io.dataease.controller.sys;
import io.dataease.base.domain.SystemParameter;
import io.dataease.commons.constants.ParamConstants;
import io.dataease.controller.sys.response.BasicInfo;
import io.dataease.controller.sys.response.MailInfo;
import io.dataease.dto.SystemParameterDTO;
import io.dataease.service.FileService;
import io.dataease.service.system.SystemParameterService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@ -28,11 +32,33 @@ public class SystemParameterController {
@Resource
private FileService fileService;
@GetMapping("/mail/info")
public MailInfo mailInfo() {
return systemParameterService.mailInfo(ParamConstants.Classify.MAIL.getValue());
}
@GetMapping("/basic/info")
public BasicInfo basicInfo() {
return systemParameterService.basicInfo();
}
@GetMapping("/requestTimeOut")
public Integer RequestTimeOut() {
BasicInfo basicInfo = systemParameterService.basicInfo();
return StringUtils.isNotBlank(basicInfo.getFrontTimeOut()) ? Integer.parseInt(basicInfo.getFrontTimeOut()) : 10;
}
@PostMapping("/edit/email")
public void editMail(@RequestBody List<SystemParameter> systemParameter) {
systemParameterService.editMail(systemParameter);
}
@PostMapping("/edit/basic")
public void editBasic(@RequestBody List<SystemParameter> systemParameter) {
systemParameterService.editBasic(systemParameter);
}
@PostMapping("/testConnection")
public void testConnection(@RequestBody HashMap<String, String> hashMap) {
systemParameterService.testConnection(hashMap);
@ -70,4 +96,6 @@ public class SystemParameterController {
}
}

View File

@ -0,0 +1,16 @@
package io.dataease.controller.sys.response;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BasicInfo implements Serializable{
@ApiModelProperty("请求超时时间")
private String frontTimeOut;
@ApiModelProperty("消息保留时间")
private String msgTimeOut;
}

View File

@ -0,0 +1,18 @@
package io.dataease.controller.sys.response;
import java.io.Serializable;
import lombok.Data;
@Data
public class MailInfo implements Serializable{
private String host;
private String port;
private String account;
private String password;
private String ssl;
private String tls;
private String recipient;
}

View File

@ -9,6 +9,7 @@ public enum DatasourceTypes {
sqlServer("sqlServer", "sqlServer", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "\"", "\"", "\"", "\""),
de_doris("de_doris", "de_doris", "com.mysql.jdbc.Driver", "`", "`", "", ""),
oracle("oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "\"", "\"", "\"", "\""),
mongo("mongo", "mongodb", "com.mongodb.jdbc.MongoDriver", "`", "`", "\"", "\""),
ck("ch", "ch", "ru.yandex.clickhouse.ClickHouseDriver", "`", "`", "'", "'"),
es("es", "es", "", "\"", "\"", "\"", "\"");

View File

@ -0,0 +1,19 @@
package io.dataease.datasource.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MongodbConfiguration extends JdbcConfiguration {
private String driver = "mongodb.jdbc.MongoDriver";
private String connectionType;
public String getJdbc() {
return "jdbc:mongodb://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())
.replace("PORT", getPort().toString().trim())
.replace("DATABASE", getDataBase().trim());
}
}

View File

@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@Service("es")
public class EsProvider extends DatasourceProvider {
@ -177,6 +178,7 @@ public class EsProvider extends DatasourceProvider {
try {
String response = exexQuery(datasourceRequest, "show tables", "?format=json");
tables = fetchTables(response);
tables = tables.stream().filter(table -> !table.startsWith(".")).collect(Collectors.toList());
} catch (Exception e) {
DataEaseException.throwException(e);
}

View File

@ -1,6 +1,8 @@
package io.dataease.datasource.provider;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallFilter;
import com.google.gson.Gson;
import io.dataease.datasource.constants.DatasourceTypes;
import io.dataease.datasource.dto.*;
@ -10,7 +12,6 @@ import io.dataease.i18n.Translator;
import io.dataease.provider.QueryProvider;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.beans.PropertyVetoException;
import java.io.File;
@ -18,12 +19,16 @@ import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service("jdbc")
public class JdbcProvider extends DatasourceProvider {
private static Map<String, DruidDataSource> jdbcConnection = new HashMap<>();
public ExtendedJdbcClassLoader extendedJdbcClassLoader;
static private String FILE_PATH = "/opt/dataease/drivers";
private static final String REG_WITH_SQL_FRAGMENT = "((?i)WITH[\\s\\S]+(?i)AS?\\s*\\([\\s\\S]+\\))\\s*(?i)SELECT";
public static final Pattern WITH_SQL_FRAGMENT = Pattern.compile(REG_WITH_SQL_FRAGMENT);
@PostConstruct
public void init() throws Exception{
@ -62,8 +67,10 @@ public class JdbcProvider extends DatasourceProvider {
@Override
public List<String[]> getData(DatasourceRequest dsr) throws Exception {
List<String[]> list = new LinkedList<>();
try (Connection connection = getConnectionFromPool(dsr); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(dsr.getQuery())){
try (Connection connection = getConnectionFromPool(dsr); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(rebuildSqlWithFragment(dsr.getQuery()) )){
list = fetchResult(rs);
if(dsr.isPageable() && dsr.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())){
Integer realSize = dsr.getPage() * dsr.getPageSize() < list.size() ? dsr.getPage() * dsr.getPageSize(): list.size();
list = list.subList((dsr.getPage() - 1) * dsr.getPageSize(), realSize);
@ -89,7 +96,7 @@ public class JdbcProvider extends DatasourceProvider {
@Override
public List<String[]> fetchResult(DatasourceRequest datasourceRequest) throws Exception {
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(datasourceRequest.getQuery())){
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(rebuildSqlWithFragment(datasourceRequest.getQuery()))){
return fetchResult(rs);
} catch (SQLException e) {
DataEaseException.throwException(e);
@ -125,7 +132,7 @@ public class JdbcProvider extends DatasourceProvider {
@Override
public List<TableFiled> fetchResultField(DatasourceRequest datasourceRequest) throws Exception {
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(datasourceRequest.getQuery())){
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(rebuildSqlWithFragment(datasourceRequest.getQuery()))){
return fetchResultField(rs, datasourceRequest);
} catch (SQLException e) {
DataEaseException.throwException(e);
@ -140,7 +147,7 @@ public class JdbcProvider extends DatasourceProvider {
Map<String, List> result = new HashMap<>();
List<String[]> dataList = new LinkedList<>();
List<TableFiled> fieldList = new ArrayList<>();
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(datasourceRequest.getQuery())){
try (Connection connection = getConnectionFromPool(datasourceRequest); Statement stat = connection.createStatement(); ResultSet rs = stat.executeQuery(rebuildSqlWithFragment(datasourceRequest.getQuery()))){
dataList = fetchResult(rs);
fieldList = fetchResultField(rs, datasourceRequest);
result.put("dataList", dataList);
@ -195,13 +202,16 @@ public class JdbcProvider extends DatasourceProvider {
}
String queryView = getViewSql(datasourceRequest);
try (Connection con = getConnectionFromPool(datasourceRequest); Statement statement = con.createStatement(); ResultSet resultSet = statement.executeQuery(queryView)){
while (resultSet.next()) {
tables.add(resultSet.getString(1));
if(queryView != null){
try (Connection con = getConnectionFromPool(datasourceRequest); Statement statement = con.createStatement(); ResultSet resultSet = statement.executeQuery(queryView)){
while (resultSet.next()) {
tables.add(resultSet.getString(1));
}
} catch (Exception e) {
DataEaseException.throwException(e);
}
} catch (Exception e) {
DataEaseException.throwException(e);
}
return tables;
}
@ -318,6 +328,13 @@ public class JdbcProvider extends DatasourceProvider {
driver = chConfiguration.getDriver();
jdbcurl = chConfiguration.getJdbc();
break;
case mongo:
MongodbConfiguration mongodbConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MongodbConfiguration.class);
username = mongodbConfiguration.getUsername();
password = mongodbConfiguration.getPassword();
driver = mongodbConfiguration.getDriver();
jdbcurl = mongodbConfiguration.getJdbc();
break;
default:
break;
}
@ -332,13 +349,19 @@ public class JdbcProvider extends DatasourceProvider {
return conn;
}
private void addToPool(DatasourceRequest datasourceRequest) throws PropertyVetoException {
DruidDataSource dataSource = new DruidDataSource();
JdbcConfiguration jdbcConfiguration = setCredential(datasourceRequest, dataSource);
dataSource.setInitialSize(jdbcConfiguration.getInitialPoolSize());// 初始连接数
dataSource.setMinIdle(jdbcConfiguration.getMinPoolSize()); // 最小连接数
dataSource.setMaxActive(jdbcConfiguration.getMaxPoolSize()); // 最大连接数
jdbcConnection.put(datasourceRequest.getDatasource().getId(), dataSource);
private void addToPool(DatasourceRequest datasourceRequest) throws PropertyVetoException, SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
JdbcConfiguration jdbcConfiguration = setCredential(datasourceRequest, druidDataSource);
druidDataSource.setInitialSize(jdbcConfiguration.getInitialPoolSize());// 初始连接数
druidDataSource.setMinIdle(jdbcConfiguration.getMinPoolSize()); // 最小连接数
druidDataSource.setMaxActive(jdbcConfiguration.getMaxPoolSize()); // 最大连接数
if(datasourceRequest.getDatasource().getType().equals(DatasourceTypes.mongo.name())){
WallFilter wallFilter = new WallFilter();
wallFilter.setDbType(DatasourceTypes.mysql.name());
druidDataSource.setProxyFilters(Arrays.asList(new Filter[]{wallFilter}));
}
druidDataSource.init();
jdbcConnection.put(datasourceRequest.getDatasource().getId(), druidDataSource);
}
@ -351,47 +374,51 @@ public class JdbcProvider extends DatasourceProvider {
case de_doris:
case ds_doris:
MysqlConfiguration mysqlConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfiguration.class);
dataSource.setUsername(mysqlConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(mysqlConfiguration.getPassword());
dataSource.setUrl(mysqlConfiguration.getJdbc());
dataSource.setDriverClassName(mysqlConfiguration.getDriver());
dataSource.setValidationQuery("select 1");
jdbcConfiguration = mysqlConfiguration;
break;
case sqlServer:
SqlServerConfiguration sqlServerConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfiguration.class);
dataSource.setUsername(sqlServerConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(sqlServerConfiguration.getPassword());
dataSource.setDriverClassName(sqlServerConfiguration.getDriver());
dataSource.setUrl(sqlServerConfiguration.getJdbc());
dataSource.setValidationQuery("select 1");
jdbcConfiguration = sqlServerConfiguration;
break;
case oracle:
OracleConfiguration oracleConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfiguration.class);
dataSource.setUsername(oracleConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(oracleConfiguration.getPassword());
dataSource.setDriverClassName(oracleConfiguration.getDriver());
dataSource.setUrl(oracleConfiguration.getJdbc());
dataSource.setValidationQuery("select 1 from dual");
jdbcConfiguration = oracleConfiguration;
break;
case pg:
PgConfiguration pgConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfiguration.class);
dataSource.setUsername(pgConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(pgConfiguration.getPassword());
dataSource.setDriverClassName(pgConfiguration.getDriver());
dataSource.setUrl(pgConfiguration.getJdbc());
jdbcConfiguration = pgConfiguration;
break;
case ck:
CHConfiguration chConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), CHConfiguration.class);
dataSource.setUsername(chConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(chConfiguration.getPassword());
dataSource.setDriverClassName(chConfiguration.getDriver());
dataSource.setUrl(chConfiguration.getJdbc());
jdbcConfiguration = chConfiguration;
break;
case mongo:
MongodbConfiguration mongodbConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MongodbConfiguration.class);
dataSource.setDriverClassName(mongodbConfiguration.getDriver());
dataSource.setUrl(mongodbConfiguration.getJdbc());
jdbcConfiguration = mongodbConfiguration;
break;
default:
break;
}
dataSource.setUsername(jdbcConfiguration.getUsername());
dataSource.setDriverClassLoader(extendedJdbcClassLoader);
dataSource.setPassword(jdbcConfiguration.getPassword());
return jdbcConfiguration;
}
@ -479,4 +506,23 @@ public class JdbcProvider extends DatasourceProvider {
}
}
private static String rebuildSqlWithFragment(String sql) {
if (!sql.toLowerCase().startsWith("with")) {
Matcher matcher = WITH_SQL_FRAGMENT.matcher(sql);
if (matcher.find()) {
String withFragment = matcher.group();
if (!com.alibaba.druid.util.StringUtils.isEmpty(withFragment)) {
if (withFragment.length() > 6) {
int lastSelectIndex = withFragment.length() - 6;
sql = sql.replace(withFragment, withFragment.substring(lastSelectIndex));
withFragment = withFragment.substring(0, lastSelectIndex);
}
sql = withFragment + " " + sql;
sql = sql.replaceAll(" " + "{2,}", " ");
}
}
}
return sql;
}
}

View File

@ -48,6 +48,8 @@ public class ProviderFactory implements ApplicationContextAware {
return context.getBean("esQuery", QueryProvider.class);
case ck:
return context.getBean("ckQuery", QueryProvider.class);
case mongo:
return context.getBean("mongoQuery", QueryProvider.class);
default:
return context.getBean("mysqlQuery", QueryProvider.class);
}

View File

@ -0,0 +1,44 @@
package io.dataease.provider.mongodb;
import io.dataease.provider.SQLConstants;
import static io.dataease.datasource.constants.DatasourceTypes.mongo;
import static io.dataease.datasource.constants.DatasourceTypes.oracle;
/**
* @Author gin
* @Date 2021/7/8 7:22 下午
*/
public class MongoConstants extends SQLConstants {
public static final String KEYWORD_TABLE = "%s";
public static final String KEYWORD_FIX = "%s." + mongo.getKeywordPrefix() + "%s" + mongo.getKeywordSuffix();
public static final String ALIAS_FIX = mongo.getAliasPrefix() + "%s" + oracle.getAliasSuffix();
public static final String toInt32 = "toInt32(%s)";
public static final String toDateTime = "toDateTime(%s)";
public static final String toInt64 = "toInt64(%s)";
public static final String toFloat64 = "toFloat64(%s)";
public static final String formatDateTime = "formatDateTime(%s,'%s')";
public static final String toDecimal = "toDecimal64(%s,2)";
public static final String DEFAULT_DATE_FORMAT = "%Y-%m-%d %H:%M:%S";
public static final String WHERE_VALUE_NULL = "(NULL,'')";
public static final String WHERE_VALUE_VALUE = "'%s'";
public static final String AGG_COUNT = "COUNT(*)";
public static final String AGG_FIELD = "%s(%s)";
public static final String WHERE_BETWEEN = "'%s' AND '%s'";
public static final String BRACKETS = "(%s)";
}

View File

@ -0,0 +1,995 @@
package io.dataease.provider.mongodb;
import io.dataease.base.domain.DatasetTableField;
import io.dataease.base.domain.DatasetTableFieldExample;
import io.dataease.base.domain.Datasource;
import io.dataease.base.mapper.DatasetTableFieldMapper;
import io.dataease.commons.constants.DeTypeConstants;
import io.dataease.controller.request.chart.ChartExtFilterRequest;
import io.dataease.dto.chart.ChartCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.provider.QueryProvider;
import io.dataease.provider.SQLConstants;
import io.dataease.provider.oracle.OracleConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupFile;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.dataease.provider.SQLConstants.TABLE_ALIAS_PREFIX;
/**
* @Author gin
* @Date 2021/5/17 2:43 下午
*/
@Service("mongoQuery")
public class MongoQueryProvider extends QueryProvider {
@Resource
private DatasetTableFieldMapper datasetTableFieldMapper;
@Override
public Integer transFieldType(String field) {
System.out.println(field);
field = field.toUpperCase();
switch (field) {
case "CHAR":
case "VARCHAR":
case "TEXT":
case "TINYTEXT":
case "MEDIUMTEXT":
case "LONGTEXT":
case "STRING":
return 0;// 文本
case "DATE":
case "TIME":
case "YEAR":
case "DATETIME":
case "TIMESTAMP":
return 1;// 时间
case "INT":
case "SMALLINT":
case "MEDIUMINT":
case "INTEGER":
case "BIGINT":
return 2;// 整型
case "FLOAT":
case "DOUBLE":
case "DECIMAL":
return 3;// 浮点
case "BIT":
case "TINYINT":
return 4;// 布尔
default:
return 0;
}
}
@Override
public String createSQLPreview(String sql, String orderBy) {
return "SELECT * FROM (" + sqlFix(sql) + ") AS tmp " + " LIMIT 0,1000";
}
@Override
public String createQuerySQL(String table, List<DatasetTableField> fields, boolean isGroup, Datasource ds) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> xFields = new ArrayList<>();
if (CollectionUtils.isNotEmpty(fields)) {
for (int i = 0; i < fields.size(); i++) {
DatasetTableField f = fields.get(i);
String originField;
if (ObjectUtils.isNotEmpty(f.getExtField()) && f.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(f.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(f.getExtField()) && f.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), f.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), f.getOriginName());
}
String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
String fieldName = "";
fieldName = originField;
xFields.add(SQLObj.builder()
.fieldName(fieldName)
.fieldAlias(fieldAlias)
.build());
}
}
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("previewSql");
st_sql.add("isGroup", isGroup);
if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
return st_sql.render();
}
@Override
public String createQuerySQLAsTmp(String sql, List<DatasetTableField> fields, boolean isGroup) {
return createQuerySQL("(" + sqlFix(sql) + ")", fields, isGroup, null);
}
@Override
public String createQueryTableWithPage(String table, List<DatasetTableField> fields, Integer page, Integer pageSize, Integer realSize, boolean isGroup, Datasource ds) {
return createQuerySQL(table, fields, isGroup, null) + " LIMIT " + (page - 1) * pageSize + "," + realSize;
}
@Override
public String createQueryTableWithLimit(String table, List<DatasetTableField> fields, Integer limit, boolean isGroup, Datasource ds) {
return createQuerySQL(table, fields, isGroup, null) + " LIMIT 0," + limit;
}
@Override
public String createQuerySqlWithLimit(String sql, List<DatasetTableField> fields, Integer limit, boolean isGroup) {
return createQuerySQLAsTmp(sql, fields, isGroup) + " LIMIT 0," + limit;
}
@Override
public String createQuerySQLWithPage(String sql, List<DatasetTableField> fields, Integer page, Integer pageSize, Integer realSize, boolean isGroup) {
return createQuerySQLAsTmp(sql, fields, isGroup) + " LIMIT " + (page - 1) * pageSize + "," + realSize;
}
@Override
public String getSQL(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> xFields = new ArrayList<>();
List<SQLObj> xWheres = new ArrayList<>();
List<SQLObj> xOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(xAxis)) {
for (int i = 0; i < xAxis.size(); i++) {
ChartViewFieldDTO x = xAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(x.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
}
String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
// 处理横轴字段
xFields.add(getXFields(x, originField, fieldAlias));
// 处理横轴过滤
// xWheres.addAll(getXWheres(x, originField, fieldAlias));
// 处理横轴排序
if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) {
xOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(x.getSort())
.build());
}
}
}
List<SQLObj> yFields = new ArrayList<>();
List<SQLObj> yWheres = new ArrayList<>();
List<SQLObj> yOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(yAxis)) {
for (int i = 0; i < yAxis.size(); i++) {
ChartViewFieldDTO y = yAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(y.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
}
String fieldAlias = String.format(MongoConstants.ALIAS_FIX, String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i));
// 处理纵轴字段
yFields.add(getYFields(y, originField, fieldAlias));
// 处理纵轴过滤
yWheres.addAll(getYWheres(y, originField, fieldAlias));
// 处理纵轴排序
if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) {
yOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(y.getSort())
.build());
}
}
}
// 处理视图中字段过滤
List<SQLObj> customWheres = transCustomFilterList(tableObj, customFilter);
// 处理仪表板字段过滤
List<SQLObj> extWheres = transExtFilterList(tableObj, extFilterRequestList);
// 构建sql所有参数
List<SQLObj> fields = new ArrayList<>();
fields.addAll(xFields);
fields.addAll(yFields);
List<SQLObj> wheres = new ArrayList<>();
wheres.addAll(xWheres);
if (customWheres != null) wheres.addAll(customWheres);
if (extWheres != null) wheres.addAll(extWheres);
List<SQLObj> groups = new ArrayList<>();
groups.addAll(xFields);
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(xOrders);
orders.addAll(yOrders);
List<SQLObj> aggWheres = new ArrayList<>();
aggWheres.addAll(yWheres);
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("querySql");
if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields);
if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields);
if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
String sql = st_sql.render();
ST st = stg.getInstanceOf("querySql");
SQLObj tableSQL = SQLObj.builder()
.tableName(String.format(MongoConstants.BRACKETS, sql))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 1))
.build();
if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres);
if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders);
if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL);
return st.render();
}
@Override
public String getSQLTableInfo(String table, List<ChartViewFieldDTO> xAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> xFields = new ArrayList<>();
List<SQLObj> xWheres = new ArrayList<>();
List<SQLObj> xOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(xAxis)) {
for (int i = 0; i < xAxis.size(); i++) {
ChartViewFieldDTO x = xAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(x.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
}
String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
// 处理横轴字段
xFields.add(getXFields(x, originField, fieldAlias));
// 处理横轴过滤
// xWheres.addAll(getXWheres(x, originField, fieldAlias));
// 处理横轴排序
if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) {
xOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(x.getSort())
.build());
}
}
}
// 处理视图中字段过滤
List<SQLObj> customWheres = transCustomFilterList(tableObj, customFilter);
// 处理仪表板字段过滤
List<SQLObj> extWheres = transExtFilterList(tableObj, extFilterRequestList);
// 构建sql所有参数
List<SQLObj> fields = new ArrayList<>();
fields.addAll(xFields);
List<SQLObj> wheres = new ArrayList<>();
wheres.addAll(xWheres);
if (customWheres != null) wheres.addAll(customWheres);
if (extWheres != null) wheres.addAll(extWheres);
List<SQLObj> groups = new ArrayList<>();
groups.addAll(xFields);
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(xOrders);
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("previewSql");
st_sql.add("isGroup", false);
if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields);
if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
String sql = st_sql.render();
ST st = stg.getInstanceOf("previewSql");
st.add("isGroup", false);
SQLObj tableSQL = SQLObj.builder()
.tableName(String.format(MongoConstants.BRACKETS, sql))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 1))
.build();
if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders);
if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL);
return st.render();
}
@Override
public String getSQLAsTmpTableInfo(String sql, List<ChartViewFieldDTO> xAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds) {
return getSQLTableInfo("(" + sqlFix(sql) + ")", xAxis, customFilter, extFilterRequestList, null);
}
@Override
public String getSQLAsTmp(String sql, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList) {
return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList, null);
}
@Override
public String getSQLStack(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, List<ChartViewFieldDTO> extStack, Datasource ds) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> xFields = new ArrayList<>();
List<SQLObj> xWheres = new ArrayList<>();
List<SQLObj> xOrders = new ArrayList<>();
List<ChartViewFieldDTO> xList = new ArrayList<>();
xList.addAll(xAxis);
xList.addAll(extStack);
if (CollectionUtils.isNotEmpty(xList)) {
for (int i = 0; i < xList.size(); i++) {
ChartViewFieldDTO x = xList.get(i);
String originField;
if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(x.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
}
String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
// 处理横轴字段
xFields.add(getXFields(x, originField, fieldAlias));
// 处理横轴过滤
// xWheres.addAll(getXWheres(x, originField, fieldAlias));
// 处理横轴排序
if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) {
xOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(x.getSort())
.build());
}
}
}
List<SQLObj> yFields = new ArrayList<>();
List<SQLObj> yWheres = new ArrayList<>();
List<SQLObj> yOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(yAxis)) {
for (int i = 0; i < yAxis.size(); i++) {
ChartViewFieldDTO y = yAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(y.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
}
String fieldAlias = String.format(MongoConstants.ALIAS_FIX, String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i));
// 处理纵轴字段
yFields.add(getYFields(y, originField, fieldAlias));
// 处理纵轴过滤
yWheres.addAll(getYWheres(y, originField, fieldAlias));
// 处理纵轴排序
if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) {
yOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(y.getSort())
.build());
}
}
}
// 处理视图中字段过滤
List<SQLObj> customWheres = transCustomFilterList(tableObj, customFilter);
// 处理仪表板字段过滤
List<SQLObj> extWheres = transExtFilterList(tableObj, extFilterRequestList);
// 构建sql所有参数
List<SQLObj> fields = new ArrayList<>();
fields.addAll(xFields);
fields.addAll(yFields);
List<SQLObj> wheres = new ArrayList<>();
wheres.addAll(xWheres);
if (customWheres != null) wheres.addAll(customWheres);
if (extWheres != null) wheres.addAll(extWheres);
List<SQLObj> groups = new ArrayList<>();
groups.addAll(xFields);
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(xOrders);
orders.addAll(yOrders);
List<SQLObj> aggWheres = new ArrayList<>();
aggWheres.addAll(yWheres);
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("querySql");
if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields);
if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields);
if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
String sql = st_sql.render();
ST st = stg.getInstanceOf("querySql");
SQLObj tableSQL = SQLObj.builder()
.tableName(String.format(MongoConstants.BRACKETS, sql))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 1))
.build();
if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres);
if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders);
if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL);
return st.render();
}
@Override
public String getSQLAsTmpStack(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, List<ChartViewFieldDTO> extStack) {
return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null);
}
@Override
public String getSQLScatter(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, List<ChartViewFieldDTO> extBubble, Datasource ds) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> xFields = new ArrayList<>();
List<SQLObj> xWheres = new ArrayList<>();
List<SQLObj> xOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(xAxis)) {
for (int i = 0; i < xAxis.size(); i++) {
ChartViewFieldDTO x = xAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(x.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName());
}
String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
// 处理横轴字段
xFields.add(getXFields(x, originField, fieldAlias));
// 处理横轴过滤
// xWheres.addAll(getXWheres(x, originField, fieldAlias));
// 处理横轴排序
if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) {
xOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(x.getSort())
.build());
}
}
}
List<SQLObj> yFields = new ArrayList<>();
List<SQLObj> yWheres = new ArrayList<>();
List<SQLObj> yOrders = new ArrayList<>();
List<ChartViewFieldDTO> yList = new ArrayList<>();
yList.addAll(yAxis);
yList.addAll(extBubble);
if (CollectionUtils.isNotEmpty(yList)) {
for (int i = 0; i < yList.size(); i++) {
ChartViewFieldDTO y = yList.get(i);
String originField;
if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(y.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
}
String fieldAlias = String.format(MongoConstants.ALIAS_FIX, String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i));
// 处理纵轴字段
yFields.add(getYFields(y, originField, fieldAlias));
// 处理纵轴过滤
yWheres.addAll(getYWheres(y, originField, fieldAlias));
// 处理纵轴排序
if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) {
yOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(y.getSort())
.build());
}
}
}
// 处理视图中字段过滤
List<SQLObj> customWheres = transCustomFilterList(tableObj, customFilter);
// 处理仪表板字段过滤
List<SQLObj> extWheres = transExtFilterList(tableObj, extFilterRequestList);
// 构建sql所有参数
List<SQLObj> fields = new ArrayList<>();
fields.addAll(xFields);
fields.addAll(yFields);
List<SQLObj> wheres = new ArrayList<>();
wheres.addAll(xWheres);
if (customWheres != null) wheres.addAll(customWheres);
if (extWheres != null) wheres.addAll(extWheres);
List<SQLObj> groups = new ArrayList<>();
groups.addAll(xFields);
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(xOrders);
orders.addAll(yOrders);
List<SQLObj> aggWheres = new ArrayList<>();
aggWheres.addAll(yWheres);
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("querySql");
if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields);
if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields);
if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
String sql = st_sql.render();
ST st = stg.getInstanceOf("querySql");
SQLObj tableSQL = SQLObj.builder()
.tableName(String.format(MongoConstants.BRACKETS, sql))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 1))
.build();
if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres);
if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders);
if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL);
return st.render();
}
@Override
public String getSQLAsTmpScatter(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList, List<ChartViewFieldDTO> extBubble) {
return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null);
}
@Override
public String searchTable(String table) {
return "SELECT table_name FROM information_schema.TABLES WHERE table_name ='" + table + "'";
}
@Override
public String getSQLSummary(String table, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList) {
// 字段汇总 排序等
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MongoConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
.build();
List<SQLObj> yFields = new ArrayList<>();
List<SQLObj> yWheres = new ArrayList<>();
List<SQLObj> yOrders = new ArrayList<>();
if (CollectionUtils.isNotEmpty(yAxis)) {
for (int i = 0; i < yAxis.size(); i++) {
ChartViewFieldDTO y = yAxis.get(i);
String originField;
if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originField = calcFieldRegex(y.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == DeTypeConstants.DE_TIME) {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
} else {
originField = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName());
}
String fieldAlias = String.format(MongoConstants.ALIAS_FIX, String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i));
// 处理纵轴字段
yFields.add(getYFields(y, originField, fieldAlias));
// 处理纵轴过滤
yWheres.addAll(getYWheres(y, originField, fieldAlias));
// 处理纵轴排序
if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) {
yOrders.add(SQLObj.builder()
.orderField(originField)
.orderAlias(fieldAlias)
.orderDirection(y.getSort())
.build());
}
}
}
// 处理视图中字段过滤
List<SQLObj> customWheres = transCustomFilterList(tableObj, customFilter);
// 处理仪表板字段过滤
List<SQLObj> extWheres = transExtFilterList(tableObj, extFilterRequestList);
// 构建sql所有参数
List<SQLObj> fields = new ArrayList<>();
fields.addAll(yFields);
List<SQLObj> wheres = new ArrayList<>();
if (customWheres != null) wheres.addAll(customWheres);
if (extWheres != null) wheres.addAll(extWheres);
List<SQLObj> groups = new ArrayList<>();
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(yOrders);
List<SQLObj> aggWheres = new ArrayList<>();
aggWheres.addAll(yWheres);
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
ST st_sql = stg.getInstanceOf("querySql");
if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields);
if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres);
if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj);
String sql = st_sql.render();
ST st = stg.getInstanceOf("querySql");
SQLObj tableSQL = SQLObj.builder()
.tableName(String.format(MongoConstants.BRACKETS, sql))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 1))
.build();
if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres);
if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders);
if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL);
return st.render();
}
@Override
public String getSQLSummaryAsTmp(String sql, List<ChartViewFieldDTO> yAxis, List<ChartCustomFilterDTO> customFilter, List<ChartExtFilterRequest> extFilterRequestList) {
return getSQLSummary("(" + sqlFix(sql) + ")", yAxis, customFilter, extFilterRequestList);
}
@Override
public String wrapSql(String sql) {
sql = sql.trim();
if (sql.lastIndexOf(";") == (sql.length() - 1)) {
sql = sql.substring(0, sql.length() - 1);
}
String tmpSql = "SELECT * FROM (" + sql + ") AS tmp " + " LIMIT 0";
return tmpSql;
}
@Override
public String createRawQuerySQL(String table, List<DatasetTableField> fields, Datasource ds) {
String[] array = fields.stream().map(f -> {
StringBuilder stringBuilder = new StringBuilder();
if (f.getDeExtractType() == 4) { // 处理 tinyint
stringBuilder.append("concat(`").append(f.getOriginName()).append("`,'') AS ").append(f.getDataeaseName());
} else {
stringBuilder.append("`").append(f.getOriginName()).append("` AS ").append(f.getDataeaseName());
}
return stringBuilder.toString();
}).toArray(String[]::new);
return MessageFormat.format("SELECT {0} FROM {1}", StringUtils.join(array, ","), table);
}
@Override
public String createRawQuerySQLAsTmp(String sql, List<DatasetTableField> fields) {
return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields, null);
}
@Override
public String convertTableToSql(String tableName, Datasource ds) {
return createSQLPreview("SELECT * FROM " + String.format(MongoConstants.KEYWORD_TABLE, tableName), null);
}
public String transMysqlFilterTerm(String term) {
switch (term) {
case "eq":
return " = ";
case "not_eq":
return " <> ";
case "lt":
return " < ";
case "le":
return " <= ";
case "gt":
return " > ";
case "ge":
return " >= ";
case "in":
return " IN ";
case "not in":
return " NOT IN ";
case "like":
return " LIKE ";
case "not like":
return " NOT LIKE ";
case "null":
return " IS NULL ";
case "not_null":
return " IS NOT NULL ";
case "empty":
return " = ";
case "not_empty":
return " <> ";
case "between":
return " BETWEEN ";
default:
return "";
}
}
public List<SQLObj> transCustomFilterList(SQLObj tableObj, List<ChartCustomFilterDTO> requestList) {
if (CollectionUtils.isEmpty(requestList)) {
return null;
}
List<SQLObj> list = new ArrayList<>();
for (ChartCustomFilterDTO request : requestList) {
DatasetTableField field = request.getField();
if (ObjectUtils.isEmpty(field)) {
continue;
}
String value = request.getValue();
String whereName = "";
String whereTerm = transMysqlFilterTerm(request.getTerm());
String whereValue = "";
String originName;
if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originName = calcFieldRegex(field.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == DeTypeConstants.DE_TIME) {
originName = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName());
} else {
originName = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName());
}
// if (field.getDeType() == DeTypeConstants.DE_TIME) {
// if (field.getDeExtractType() == DeTypeConstants.DE_STRING || field.getDeExtractType() == 5) {
// whereName = String.format(MongoConstants.STR_TO_DATE, originName, MongoConstants.DEFAULT_DATE_FORMAT);
// }
// if (field.getDeExtractType() == DeTypeConstants.DE_INT || field.getDeExtractType() == DeTypeConstants.DE_FLOAT || field.getDeExtractType() == 4) {
// String cast = String.format(MongoConstants.CAST, originName, MongoConstants.DEFAULT_INT_FORMAT) + "/1000";
// whereName = String.format(MongoConstants.FROM_UNIXTIME, cast, MongoConstants.DEFAULT_DATE_FORMAT);
// }
// if (field.getDeExtractType() == DeTypeConstants.DE_TIME) {
// whereName = originName;
// }
// } else {
// whereName = originName;
// }
whereName = originName;
if (StringUtils.equalsIgnoreCase(request.getTerm(), "null")) {
// whereValue = MongoConstants.WHERE_VALUE_NULL;
whereValue = "";
} else if (StringUtils.equalsIgnoreCase(request.getTerm(), "not_null")) {
// whereTerm = String.format(whereTerm, originName);
whereValue = "";
} else if (StringUtils.equalsIgnoreCase(request.getTerm(), "empty")) {
whereValue = "''";
} else if (StringUtils.equalsIgnoreCase(request.getTerm(), "not_empty")) {
whereValue = "''";
} else if (StringUtils.containsIgnoreCase(request.getTerm(), "in")) {
whereValue = "('" + StringUtils.join(value, "','") + "')";
} else if (StringUtils.containsIgnoreCase(request.getTerm(), "like")) {
whereValue = "'%" + value + "%'";
} else {
whereValue = String.format(MongoConstants.WHERE_VALUE_VALUE, value);
}
list.add(SQLObj.builder()
.whereField(whereName)
.whereTermAndValue(whereTerm + whereValue)
.build());
}
return list;
}
public List<SQLObj> transExtFilterList(SQLObj tableObj, List<ChartExtFilterRequest> requestList) {
if (CollectionUtils.isEmpty(requestList)) {
return null;
}
List<SQLObj> list = new ArrayList<>();
for (ChartExtFilterRequest request : requestList) {
List<String> value = request.getValue();
DatasetTableField field = request.getDatasetTableField();
if (CollectionUtils.isEmpty(value) || ObjectUtils.isEmpty(field)) {
continue;
}
String whereName = "";
String whereTerm = transMysqlFilterTerm(request.getOperator());
String whereValue = "";
String originName;
if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == DeTypeConstants.DE_INT) {
// 解析origin name中有关联的字段生成sql表达式
originName = calcFieldRegex(field.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == DeTypeConstants.DE_TIME) {
originName = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName());
} else {
originName = String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName());
}
// if (field.getDeType() == DeTypeConstants.DE_TIME) {
// if (field.getDeExtractType() == DeTypeConstants.DE_STRING || field.getDeExtractType() == 5) {
// whereName = String.format(MongoConstants.STR_TO_DATE, originName, MongoConstants.DEFAULT_DATE_FORMAT);
// }
// if (field.getDeExtractType() == DeTypeConstants.DE_INT || field.getDeExtractType() == DeTypeConstants.DE_FLOAT || field.getDeExtractType() == 4) {
// String cast = String.format(MongoConstants.CAST, originName, MongoConstants.DEFAULT_INT_FORMAT) + "/1000";
// whereName = String.format(MongoConstants.FROM_UNIXTIME, cast, MongoConstants.DEFAULT_DATE_FORMAT);
// }
// if (field.getDeExtractType() == DeTypeConstants.DE_TIME) {
// whereName = originName;
// }
// } else {
// whereName = originName;
// }
whereName = originName;
if (StringUtils.containsIgnoreCase(request.getOperator(), "in")) {
whereValue = "('" + StringUtils.join(value, "','") + "')";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
whereValue = "'%" + value.get(0) + "%'";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String startTime = simpleDateFormat.format(new Date(Long.parseLong(value.get(0))));
String endTime = simpleDateFormat.format(new Date(Long.parseLong(value.get(1))));
whereValue = String.format(MongoConstants.WHERE_BETWEEN, startTime, endTime);
} else {
whereValue = String.format(MongoConstants.WHERE_BETWEEN, value.get(0), value.get(1));
}
} else {
whereValue = String.format(MongoConstants.WHERE_VALUE_VALUE, value.get(0));
}
list.add(SQLObj.builder()
.whereField(whereName)
.whereTermAndValue(whereTerm + whereValue)
.build());
}
return list;
}
private String sqlFix(String sql) {
if (sql.lastIndexOf(";") == (sql.length() - 1)) {
sql = sql.substring(0, sql.length() - 1);
}
return sql;
}
private String transDateFormat(String dateStyle, String datePattern) {
String split = "-";
if (StringUtils.equalsIgnoreCase(datePattern, "date_sub")) {
split = "-";
} else if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
split = "/";
} else {
split = "-";
}
if (StringUtils.isEmpty(dateStyle)) {
return "%Y-%m-%d %H:%i:%S";
}
switch (dateStyle) {
case "y":
return "%Y";
case "y_M":
return "%Y" + split + "%m";
case "y_M_d":
return "%Y" + split + "%m" + split + "%d";
case "H_m_s":
return "%H:%i:%S";
case "y_M_d_H_m":
return "%Y" + split + "%m" + split + "%d" + " %H:%i";
case "y_M_d_H_m_s":
return "%Y" + split + "%m" + split + "%d" + " %H:%i:%S";
default:
return "%Y-%m-%d %H:%i:%S";
}
}
private SQLObj getXFields(ChartViewFieldDTO x, String originField, String fieldAlias) {
String fieldName = "";
if (x.getDeExtractType() == DeTypeConstants.DE_TIME) {
// if (x.getDeType() == DeTypeConstants.DE_INT || x.getDeType() == DeTypeConstants.DE_FLOAT) {
// fieldName = String.format(MongoConstants.UNIX_TIMESTAMP, originField) + "*1000";
// } else if (x.getDeType() == DeTypeConstants.DE_TIME) {
// String format = transDateFormat(x.getDateStyle(), x.getDatePattern());
// fieldName = String.format(MongoConstants.DATE_FORMAT, originField, format);
// } else {
// fieldName = originField;
// }
fieldName = originField;
} else {
// if (x.getDeType() == DeTypeConstants.DE_TIME) {
// String format = transDateFormat(x.getDateStyle(), x.getDatePattern());
// if (x.getDeExtractType() == DeTypeConstants.DE_STRING) {
// fieldName = String.format(MongoConstants.DATE_FORMAT, originField, format);
// } else {
// String cast = String.format(MongoConstants.CAST, originField, MongoConstants.DEFAULT_INT_FORMAT) + "/1000";
// String from_unixtime = String.format(MongoConstants.FROM_UNIXTIME, cast, MongoConstants.DEFAULT_DATE_FORMAT);
// fieldName = String.format(MongoConstants.DATE_FORMAT, from_unixtime, format);
// }
// } else {
// fieldName = originField;
// }
fieldName = originField;
}
return SQLObj.builder()
.fieldName(fieldName)
.fieldAlias(fieldAlias)
.build();
}
private SQLObj getYFields(ChartViewFieldDTO y, String originField, String fieldAlias) {
String fieldName = "";
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = MongoConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), originField);
} else {
// if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
// String cast = String.format(MongoConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? MongoConstants.DEFAULT_INT_FORMAT : MongoConstants.DEFAULT_FLOAT_FORMAT);
// String agg = String.format(MongoConstants.AGG_FIELD, y.getSummary(), cast);
// fieldName = String.format(MongoConstants.CAST, agg, MongoConstants.DEFAULT_FLOAT_FORMAT);
// } else {
// String cast = String.format(MongoConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? MongoConstants.DEFAULT_INT_FORMAT : MongoConstants.DEFAULT_FLOAT_FORMAT);
// fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), cast);
// }
fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), originField);
}
return SQLObj.builder()
.fieldName(fieldName)
.fieldAlias(fieldAlias)
.build();
}
private List<SQLObj> getYWheres(ChartViewFieldDTO y, String originField, String fieldAlias) {
List<SQLObj> list = new ArrayList<>();
if (CollectionUtils.isNotEmpty(y.getFilter()) && y.getFilter().size() > 0) {
y.getFilter().forEach(f -> {
String whereTerm = transMysqlFilterTerm(f.getTerm());
String whereValue = "";
// 原始类型不是时间在de中被转成时间的字段做处理
if (StringUtils.equalsIgnoreCase(f.getTerm(), "null")) {
// whereValue = MongoConstants.WHERE_VALUE_NULL;
whereValue = "";
} else if (StringUtils.equalsIgnoreCase(f.getTerm(), "not_null")) {
// whereTerm = String.format(whereTerm, originField);
whereValue = "";
} else if (StringUtils.equalsIgnoreCase(f.getTerm(), "empty")) {
whereValue = "''";
} else if (StringUtils.equalsIgnoreCase(f.getTerm(), "not_empty")) {
whereValue = "''";
} else if (StringUtils.containsIgnoreCase(f.getTerm(), "in")) {
whereValue = "('" + StringUtils.join(f.getValue(), "','") + "')";
} else if (StringUtils.containsIgnoreCase(f.getTerm(), "like")) {
whereValue = "'%" + f.getValue() + "%'";
} else {
whereValue = String.format(MongoConstants.WHERE_VALUE_VALUE, f.getValue());
}
list.add(SQLObj.builder()
.whereField(fieldAlias)
.whereAlias(fieldAlias)
.whereTermAndValue(whereTerm + whereValue)
.build());
});
}
return list;
}
private String calcFieldRegex(String originField, SQLObj tableObj) {
originField = originField.replaceAll("[\\t\\n\\r]]", "");
// 正则提取[xxx]
String regex = "\\[(.*?)]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(originField);
Set<String> ids = new HashSet<>();
while (matcher.find()) {
String id = matcher.group(1);
ids.add(id);
}
if (CollectionUtils.isEmpty(ids)) {
return originField;
}
DatasetTableFieldExample datasetTableFieldExample = new DatasetTableFieldExample();
datasetTableFieldExample.createCriteria().andIdIn(new ArrayList<>(ids));
List<DatasetTableField> calcFields = datasetTableFieldMapper.selectByExample(datasetTableFieldExample);
for (DatasetTableField ele : calcFields) {
originField = originField.replaceAll("\\[" + ele.getId() + "]",
String.format(MongoConstants.KEYWORD_FIX, tableObj.getTableAlias(), ele.getOriginName()));
}
return originField;
}
}

View File

@ -1037,6 +1037,7 @@ public class DataSetTableService {
if (CollectionUtils.isNotEmpty(fields)) {
for (int i = 0; i < fields.size(); i++) {
TableFiled filed = fields.get(i);
System.out.println(new Gson().toJson(filed));
DatasetTableField datasetTableField = DatasetTableField.builder().build();
datasetTableField.setTableId(datasetTable.getId());
datasetTableField.setOriginName(filed.getFieldName());

View File

@ -16,14 +16,16 @@ import io.dataease.controller.sys.request.MsgSettingRequest;
import io.dataease.controller.sys.response.MsgGridDto;
import io.dataease.controller.sys.response.SettingTreeNode;
import io.dataease.controller.sys.response.SubscribeNode;
import io.dataease.service.system.SystemParameterService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -31,7 +33,7 @@ import java.util.stream.Collectors;
@Service
public class SysMsgService {
private static final long overDays = 30;
private static int overDays = 30;
@Resource
private SysMsgMapper sysMsgMapper;
@ -50,7 +52,10 @@ public class SysMsgService {
@Resource
private SysMsgSettingMapper sysMsgSettingMapper;
public List<SysMsg> query(Long userId, MsgRequest msgRequest) {
@Autowired
private SystemParameterService systemParameterService;
/* public List<SysMsg> query(Long userId, MsgRequest msgRequest) {
String orderClause = " create_time desc";
SysMsgExample example = new SysMsgExample();
SysMsgExample.Criteria criteria = example.createCriteria();
@ -76,8 +81,8 @@ public class SysMsgService {
List<SysMsg> sysMsgs = sysMsgMapper.selectByExample(example);
return sysMsgs;
}
public List<MsgGridDto> queryGrid(Long userId, MsgRequest msgRequest, List<Long> typeIds) {
*/
public List<MsgGridDto> queryGrid(Long userId, MsgRequest msgRequest, List<Long> typeIds, Long startTime) {
String orderClause = " create_time desc";
SysMsgExample example = new SysMsgExample();
SysMsgExample.Criteria criteria = example.createCriteria();
@ -105,7 +110,8 @@ public class SysMsgService {
criteria.andStatusEqualTo(msgRequest.getStatus());
}
criteria.andCreateTimeGreaterThanOrEqualTo(overTime());
criteria.andCreateTimeGreaterThanOrEqualTo(startTime);
/* criteria.andCreateTimeGreaterThanOrEqualTo(overTime()); */
example.setOrderByClause(orderClause);
List<MsgGridDto> msgGridDtos = extSysMsgMapper.queryGrid(example);
@ -330,6 +336,10 @@ public class SysMsgService {
public Long overTime() {
String msgTimeOut = systemParameterService.basicInfo().getMsgTimeOut();
if(StringUtils.isNotBlank(msgTimeOut)) {
overDays = Integer.parseInt(msgTimeOut);
}
Long currentTime = System.currentTimeMillis();
long oneDayTime = 24 * 60 * 60 * 1000;
@ -340,11 +350,6 @@ public class SysMsgService {
}
/* public static void main(String[] args) {
Long overTime = overTime();
System.out.println(overTime);
} */
}

View File

@ -1,6 +1,5 @@
package io.dataease.service.system;
import com.alibaba.fastjson.JSON;
import io.dataease.base.domain.FileMetadata;
import io.dataease.base.domain.SystemParameter;
import io.dataease.base.domain.SystemParameterExample;
@ -11,6 +10,8 @@ import io.dataease.commons.exception.DEException;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.commons.utils.EncryptUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.controller.sys.response.BasicInfo;
import io.dataease.controller.sys.response.MailInfo;
import io.dataease.dto.SystemParameterDTO;
import io.dataease.i18n.Translator;
import io.dataease.service.FileService;
@ -47,6 +48,52 @@ public class SystemParameterService {
return extSystemParameterMapper.email();
}
public BasicInfo basicInfo() {
List<SystemParameter> paramList = this.getParamList("basic");
BasicInfo result = new BasicInfo();
if (!CollectionUtils.isEmpty(paramList)) {
for (SystemParameter param : paramList) {
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.FRONT_TIME_OUT.getValue())) {
/* result.setFrontTimeOut(StringUtils.isBlank(param.getParamValue()) ? 0 : Integer.parseInt(param.getParamValue())); */
result.setFrontTimeOut(param.getParamValue());
}
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.MSG_TIME_OUT.getValue())) {
/* result.setMsgTimeOut(StringUtils.isBlank(param.getParamValue()) ? 0 : Integer.parseInt(param.getParamValue())); */
result.setMsgTimeOut(param.getParamValue());
}
}
}
return result;
}
public MailInfo mailInfo(String type) {
List<SystemParameter> paramList = this.getParamList(type);
MailInfo mailInfo = new MailInfo();
if (!CollectionUtils.isEmpty(paramList)) {
for (SystemParameter param : paramList) {
if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.SERVER.getValue())) {
mailInfo.setHost(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.PORT.getValue())) {
mailInfo.setPort(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.ACCOUNT.getValue())) {
mailInfo.setAccount(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.PASSWORD.getValue())) {
String password = EncryptUtils.aesDecrypt(param.getParamValue()).toString();
mailInfo.setPassword(password);
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.SSL.getValue())) {
mailInfo.setSsl(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.TLS.getValue())) {
mailInfo.setTls(param.getParamValue());
} else if (StringUtils.equals(param.getParamKey(), ParamConstants.MAIL.RECIPIENTS.getValue())) {
mailInfo.setRecipient(param.getParamValue());
}
}
}
return mailInfo;
}
public String getSystemLanguage() {
String result = StringUtils.EMPTY;
SystemParameterExample example = new SystemParameterExample();
@ -61,6 +108,8 @@ public class SystemParameterService {
return result;
}
public void editMail(List<SystemParameter> parameters) {
List<SystemParameter> paramList = this.getParamList(ParamConstants.Classify.MAIL.getValue());
boolean empty = paramList.size() <= 0;
@ -84,6 +133,21 @@ public class SystemParameterService {
});
}
public void editBasic(List<SystemParameter> parameters) {
parameters.forEach(parameter -> {
SystemParameterExample example = new SystemParameterExample();
example.createCriteria().andParamKeyEqualTo(parameter.getParamKey());
if (systemParameterMapper.countByExample(example) > 0) {
systemParameterMapper.updateByPrimaryKey(parameter);
} else {
systemParameterMapper.insert(parameter);
}
example.clear();
});
}
public List<SystemParameter> getParamList(String type) {
SystemParameterExample example = new SystemParameterExample();
example.createCriteria().andParamKeyLike(type + "%");
@ -120,7 +184,7 @@ public class SystemParameterService {
try {
helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(javaMailSender.getUsername());
helper.setSubject("MeterSphere测试邮件 " );
helper.setSubject("DataEase测试邮件 " );
helper.setText("这是一封测试邮件,邮件发送成功", true);
helper.setTo(recipients);
javaMailSender.send(mimeMessage);

View File

@ -35,3 +35,7 @@ CREATE TABLE `panel_link_jump_target_view_info` (
`target_field_id` varchar(50) DEFAULT NULL,
PRIMARY KEY (`target_id`) USING BTREE
) ENGINE=InnoDB ;
BEGIN;
INSERT INTO `sys_menu` VALUES (6, 1, 0, 1, '系统参数', 'system-param', 'system/SysParam/index', 6, 'sys-tools', 'system-param', b'0', b'0', b'0', 'sysparam:read', NULL, NULL, NULL, NULL);
COMMIT;

Binary file not shown.

View File

@ -6,7 +6,7 @@
<parent>
<artifactId>dataease-server</artifactId>
<groupId>io.dataease</groupId>
<version>1.3.0</version>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,11 +5,12 @@
</template>
<script>
export default {
name: 'App',
beforeCreate() {
// document.body.className = 'blackTheme'
}
}
</script>

View File

@ -0,0 +1,19 @@
import request from '@/utils/request'
export function basicInfo() {
return request({
url: '/system/basic/info',
method: 'get',
loading: true
})
}
export function updateInfo(data) {
return request({
url: '/system/edit/basic',
method: 'post',
loading: true,
data
})
}

View File

@ -0,0 +1,30 @@
import request from '@/utils/request'
export function validate(data) {
return request({
url: '/system/testConnection',
method: 'post',
timeout: 30000,
loading: true,
data
})
}
export function emailInfo() {
return request({
url: '/system/mail/info',
method: 'get',
loading: true
})
}
export function updateInfo(data) {
return request({
url: '/system/edit/email',
method: 'post',
loading: true,
data
})
}

View File

@ -64,3 +64,17 @@ export function oidcStatus() {
method: 'post'
})
}
export function pluginLoaded() {
return request({
url: '/api/auth/isPluginLoaded',
method: 'post'
})
}
export function getPublicKey() {
return request({
url: '/api/auth/getPublicKey',
method: 'get'
})
}

View File

@ -70,6 +70,22 @@
<el-input v-model="styleInfo.letterSpacing" type="number" size="mini" min="0" max="99" @change="styleChange" />
</div>
<el-tooltip v-if="attrShow('margin')" :content="$t('panel.margin')">
<i style="float: left;margin-top: 3px;margin-left: 2px;" class="icon iconfont icon-margin" />
</el-tooltip>
<div v-if="attrShow('margin')" style="width: 70px;float: left;margin-top: 2px;margin-left: 2px;">
<el-input v-model="styleInfo.margin" type="number" size="mini" min="0" max="99" @change="styleChange" />
</div>
<el-tooltip v-if="attrShow('time_margin')" :content="$t('panel.margin')">
<i style="float: left;margin-top: 3px;margin-left: 2px;" class="icon iconfont icon-margin" />
</el-tooltip>
<div v-if="attrShow('time_margin')" style="width: 70px;float: left;margin-top: 2px;margin-left: 2px;">
<el-input v-model="styleInfo.time_margin" type="number" size="mini" min="0" max="99" @change="styleChange" />
</div>
<el-tooltip v-if="attrShow('opacity')" :content="$t('panel.opacity')">
<i style="float: left;margin-top: 3px;margin-left: 2px;" class="icon iconfont icon-touming" />
</el-tooltip>
@ -121,7 +137,7 @@
</el-tooltip>
</div>
<div v-if="attrShow('date-format')" style="width: 20px;float: left;margin-top: 2px;margin-left: 2px;">
<div v-if="attrShow('date-format')" style="width: 20px;float: left;margin-top: 2px;margin-left: 10px;">
<el-tooltip content="日期格式">
<date-format :format-info="curComponent.formatInfo" />
</el-tooltip>
@ -242,7 +258,9 @@ export default {
'borderRadius',
'color',
'backgroundColor',
'date-format'
'date-format',
'time_margin'
/* 'margin' */
],
//
'v-text': [

View File

@ -1,7 +1,8 @@
<template>
<de-container>
<de-aside-container v-if="!chart.type.includes('table')" :style="customStyle">
<chart-component v-if="!chart.type.includes('text')" class="chart-class" :chart="chart" />
<chart-component v-if="!chart.type.includes('text') && renderComponent() === 'echarts'" class="chart-class" :chart="chart" />
<chart-component-g2 v-if="!chart.type.includes('text') && renderComponent() === 'antv'" class="chart-class" :chart="chart" />
<label-normal v-if="chart.type.includes('text')" :chart="chart" class="table-class" />
</de-aside-container>
<de-main-container>
@ -20,10 +21,11 @@ import DeContainer from '@/components/dataease/DeContainer'
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import { export_json_to_excel } from '@/plugins/Export2Excel'
import { mapState } from 'vuex'
import ChartComponentG2 from '@/views/chart/components/ChartComponentG2'
export default {
name: 'UserView',
components: { DeMainContainer, DeContainer, DeAsideContainer, ChartComponent, TableNormal, LabelNormal },
components: { ChartComponentG2, DeMainContainer, DeContainer, DeAsideContainer, ChartComponent, TableNormal, LabelNormal },
props: {
chart: {
type: Object,
@ -72,6 +74,10 @@ export default {
const excelData = JSON.parse(JSON.stringify(this.chart.data.tableRow)).map(item => excelHeaderKeys.map(i => item[i]))
const excelName = this.chart.name
export_json_to_excel(excelHeader, excelData, excelName)
},
renderComponent() {
return this.chart.render
}
}
}

View File

@ -243,7 +243,9 @@ const list = [
borderStyle: 'solid',
borderWidth: 1,
borderColor: '#000000',
borderRadius: 0
borderRadius: 0,
/* margin: 10, */
time_margin: 10
},
formatInfo: {
openMode: '0',

View File

@ -9,7 +9,8 @@ export function getStyle(style, filter = []) {
'left',
'borderWidth',
'letterSpacing',
'borderRadius'
'borderRadius',
'margin'
]
const result = {}

View File

@ -24,6 +24,16 @@ export default {
default: null
}
},
data() {
return {
// time_margin: 0
}
},
computed: {
timeMargin() {
return this.element.style.time_margin
}
},
methods: {
chartResize() {

View File

@ -1,5 +1,9 @@
<template>
<span>{{ nowDate }}</span>
<div style="display: flex;align-items: center;" :style="{ 'height': containerHeight, 'margin':timeMargin +'px'}">
<p style="width:100%;margin:auto;">{{ nowDate }}</p>
</div>
</template>
<script>
@ -17,6 +21,14 @@ export default {
timer: null
}
},
computed: {
timeMargin() {
return this.element.style.time_margin
},
containerHeight() {
return 'calc(100% - ' + this.element.style.time_margin * 2 + 'px)'
}
},
mounted() {
this.currentTime()
},

View File

@ -32,6 +32,12 @@ export default {
return val
}
return ''
},
timeMargin() {
return this.element.style.time_margin
},
containerHeight() {
return 'calc(100% - ' + this.element.style.time_margin * 2 + 'px)'
}
},
created() {

View File

@ -1,10 +1,16 @@
<template>
<div style="height: 100%">
<div class="time-s-class" style="height: calc(100% - 100px);">
<canvas id="canvas" class="de-canvas" :width="element.style.width" :height="element.style.height - 100" />
<div :style="{ 'height': containerHeight}">
<div ref="canvasContainer" class="time-s-class" style="height: calc(100% - 50px);" :style="{'margin':timeMargin +'px'}">
<canvas
id="canvas"
class="de-canvas"
:width="canvas_width"
:height="canvas_height"
/>
<!-- <canvas id="canvas" class="de-canvas" :width="$refs.canvasContainer.clientWidth" :height="$refs.canvasContainer.clientHeight" /> -->
</div>
<div style="height: 100px;">
<p id="fulltime" :style="{'fontSize': (parseInt(element.style.fontSize) * 2) + 'px', 'color':element.style.color}" style="width:100%;margin:auto;" />
<div style="height: 50px;display: flex;align-items: center;">
<p id="fulltime" :style="{'fontSize': (parseInt(element.style.fontSize) * 1) + 'px', 'color':element.style.color}" style="width:100%;margin:auto;" />
</div>
</div>
</template>
@ -25,12 +31,26 @@ export default {
week: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
canvas: null,
draw: null,
timer: null
timer: null,
canvas_width: null,
canvas_height: null,
padding: 0
}
},
computed: {
timeMargin() {
return this.element.style.time_margin
},
containerHeight() {
return 'calc(100% - ' + this.element.style.time_margin * 2 + 'px)'
}
},
mounted() {
this.canvas = document.getElementById('canvas')
this.draw = this.canvas.getContext('2d')
this.canvas_width = this.element.style.width
this.canvas_height = this.element.style.height
this.currentTime()
},
beforeDestroy() {
@ -51,9 +71,16 @@ export default {
const showWeek = this.element.formatInfo.showWeek
const showDate = this.element.formatInfo.showDate
const canvas_w = this.element.style.width
const canvas_w = this.$refs.canvasContainer.clientWidth || this.element.style.width
if (canvas_w !== this.canvas_width) {
this.canvas_width = canvas_w
}
const canvas_h = this.element.style.height - 100
const canvas_h = this.$refs.canvasContainer.clientHeight || (this.element.style.height - 50)
if (canvas_h !== this.canvas_height) {
this.canvas_height = canvas_h
}
const side_length = Math.min(canvas_w, canvas_h)
@ -112,8 +139,10 @@ export default {
draw.beginPath()
draw.moveTo(0, side_length / 2 - 70)
draw.lineTo(0, side_length / 2 - 50)
draw.moveTo(0, side_length / 2 - 0)
/* draw.moveTo(0, side_length / 2 - 70)
draw.lineTo(0, side_length / 2 - 50) */
draw.lineTo(0, side_length / 2 - 20)
draw.closePath()
draw.stroke()
draw.restore()
@ -121,17 +150,16 @@ export default {
//
for (let i = 0; i < 60; i++) {
draw.save()
// draw.translate(250, 250)
draw.translate(this.element.style.width / 2, (this.element.style.height - 100) / 2)
draw.translate(canvas_w / 2, canvas_h / 2)
draw.rotate(i * 6 * Math.PI / 180)
draw.lineWidth = 2
draw.strokeStyle = this.element.style.color
draw.beginPath()
// draw.moveTo(0, 190)
draw.lineTo(0, side_length / 2 - 50)
// draw.lineTo(0, 180)
draw.lineTo(0, side_length / 2 - 60)
draw.moveTo(0, side_length / 2 - 0)
// draw.lineTo(0, side_length / 2 - 50)
// draw.lineTo(0, side_length / 2 - 60)
draw.lineTo(0, side_length / 2 - 10)
draw.closePath()
draw.stroke()
@ -142,7 +170,7 @@ export default {
draw.save()
draw.strokeStyle = this.element.style.color
// draw.translate(250, 250)
draw.translate(this.element.style.width / 2, (this.element.style.height - 100) / 2)
draw.translate(canvas_w / 2, canvas_h / 2)
const hourzs = h + min / 60//
draw.rotate(hourzs * 30 * Math.PI / 180)
draw.lineWidth = 6
@ -155,7 +183,7 @@ export default {
//
draw.save()
// draw.translate(250, 250)
draw.translate(this.element.style.width / 2, (this.element.style.height - 100) / 2)
draw.translate(canvas_w / 2, canvas_h / 2)
draw.rotate(min * 6 * Math.PI / 180)
draw.strokeStyle = this.element.style.color
@ -169,7 +197,7 @@ export default {
//
draw.save()
// draw.translate(250, 250)
draw.translate(this.element.style.width / 2, (this.element.style.height - 100) / 2)
draw.translate(canvas_w / 2, canvas_h / 2)
draw.rotate(s * 6 * Math.PI / 180)
draw.strokeStyle = this.element.style.color
draw.lineWidth = 1
@ -186,7 +214,7 @@ export default {
draw.lineWidth = 2
draw.beginPath()
// draw.arc(250, 250, 4, 0, 360, false)
draw.arc(this.element.style.width / 2, (this.element.style.height - 100) / 2, 4, 0, 360, false)
draw.arc(canvas_w / 2, canvas_h / 2, 4, 0, 360, false)
draw.closePath()
draw.fill()
}

View File

@ -606,6 +606,11 @@ export default {
mailbox_service_settings: 'Mail Settings',
test_connection: 'Test connection',
SMTP_host: 'SMTP Host',
basic_setting: 'Basic setting',
front_time_out: 'Request timeOut(unit: second, Attention: Refresh browser takes effect after saving)',
msg_time_out: 'Message retention time(unit: day)',
empty_front: 'If empty then default value is 10s',
empty_msg: 'If empty then default value is 30 days',
SMTP_port: 'SMTP Port',
SMTP_account: 'SMTP Account',
SMTP_password: 'SMTP Password',
@ -933,7 +938,11 @@ export default {
liquid_shape_rect: 'Rect',
dimension_or_quota: 'Dimension Or Quota',
axis_value_split_count: 'Tick Count',
chart_waterfall: 'Waterfall'
chart_waterfall: 'Waterfall',
pie_inner_radius_percent: 'Inner Radius(%)',
pie_outer_radius_size: 'Outer Radius',
table_page_size: 'Page Size',
table_page_size_unit: 'Item/Page'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',

View File

@ -608,6 +608,11 @@ export default {
mailbox_service_settings: '郵件設置',
test_connection: '測試連接',
SMTP_host: 'SMTP主機',
basic_setting: '基礎設置',
front_time_out: '請求超時時間(單位:秒, 注意:保存後刷新瀏覽器生效)',
msg_time_out: '消息保留時間(單位:天)',
empty_front: '為空則默認取值10秒',
empty_msg: '為空則默認取值30天',
SMTP_port: 'SMTP端口',
SMTP_account: 'SMTP賬戶',
SMTP_password: 'SMTP密碼',
@ -934,7 +939,11 @@ export default {
liquid_shape_rect: '矩形',
dimension_or_quota: '維度或指標',
axis_value_split_count: '刻度數',
chart_waterfall: '瀑布圖'
chart_waterfall: '瀑布圖',
pie_inner_radius_percent: '內徑占比',
pie_outer_radius_size: '外徑大小',
table_page_size: '分頁',
table_page_size_unit: '條/頁'
},
dataset: {
sheet_warn: '有多個 Sheet 頁,默認抽取第一個',

View File

@ -608,6 +608,13 @@ export default {
mailbox_service_settings: '邮件设置',
test_connection: '测试连接',
SMTP_host: 'SMTP主机',
basic_setting: '基础设置',
front_time_out: '请求超时时间(单位:秒, 注意:保存后刷新浏览器生效)',
msg_time_out: '消息保留时间(单位:天)',
empty_front: '为空则默认取10秒',
empty_msg: '为空则默认取30天',
front_error: '请填写0-100正整数',
msg_error: '请填写正整数',
SMTP_port: 'SMTP端口',
SMTP_account: 'SMTP账户',
SMTP_password: 'SMTP密码',
@ -934,7 +941,11 @@ export default {
liquid_shape_rect: '矩形',
dimension_or_quota: '维度或指标',
axis_value_split_count: '刻度数',
chart_waterfall: '瀑布图'
chart_waterfall: '瀑布图',
pie_inner_radius_percent: '内径占比',
pie_outer_radius_size: '外径大小',
table_page_size: '分页',
table_page_size_unit: '条/页'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
@ -1297,6 +1308,8 @@ export default {
fontWeight: '字体粗细',
lineHeight: '行高',
letterSpacing: '字间距',
padding: '内间距',
margin: '外间距',
textAlign: '左右对齐',
opacity: '不透明度',
verticalAlign: '上下对齐',
@ -1497,7 +1510,8 @@ export default {
i18n_msg_type_dataset_sync_faild: '数据集同步失败',
i18n_msg_type_ds_invalid: '数据源失效',
i18n_msg_type_all: '全部类型',
channel_inner_msg: '站内消息'
channel_inner_msg: '站内消息',
channel_email_msg: '邮件'
},
denumberrange: {
label: '数值区间',

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2459092 */
src: url('iconfont.woff2?t=1634625523445') format('woff2'),
url('iconfont.woff?t=1634625523445') format('woff'),
url('iconfont.ttf?t=1634625523445') format('truetype');
src: url('iconfont.woff2?t=1634802523514') format('woff2'),
url('iconfont.woff?t=1634802523514') format('woff'),
url('iconfont.ttf?t=1634802523514') format('truetype');
}
.iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-margin:before {
content: "\e902";
}
.icon-padding:before {
content: "\e91b";
}
.icon-tabs:before {
content: "\e9a8";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,20 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "924440",
"name": "margin",
"font_class": "margin",
"unicode": "e902",
"unicode_decimal": 59650
},
{
"icon_id": "924475",
"name": "padding",
"font_class": "padding",
"unicode": "e91b",
"unicode_decimal": 59675
},
{
"icon_id": "11982148",
"name": "tabs",

View File

@ -670,5 +670,12 @@ div:focus {
color: var(--Main, #0000ff);
}
.link-date-picker-class > .el-picker-panel__footer > .el-button--text:first-child{
display: none;
}
.tablepanel-i {
margin-right: 4px;
}

View File

@ -48,3 +48,8 @@ export function getSysUI() {
return json ? JSON.parse(json) : null
}
export function getTimeOut() {
const val = Cookies.get('request-time-out')
return val
}

View File

@ -12,11 +12,42 @@ import { getLinkToken, setLinkToken } from '@/utils/auth'
const TokenKey = Config.TokenKey
const RefreshTokenKey = Config.RefreshTokenKey
const LinkTokenKey = Config.LinkTokenKey
import Cookies from 'js-cookie'
// create an axios instance
const service = axios.create({
const getTimeOut = () => {
let time = 10
const url = '/system/requestTimeOut'
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
if (xhr.responseText) {
try {
const response = JSON.parse(xhr.responseText)
if (response.success) {
Cookies.set('request-time-out', response.data)
time = response.data
} else {
$error('系统异常,请联系管理员')
}
} catch (e) {
$error('系统异常,请联系管理员')
}
} else {
$error('网络异常,请联系网管')
}
}
}
xhr.open('get', url, false)
xhr.send()
return time
}
const time = getTimeOut()
let service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 10000 // request timeout
timeout: time ? time * 1000 : 10000
})
// request interceptor
@ -60,13 +91,36 @@ service.interceptors.request.use(
}
)
// const defaultOptions = {
// confirmButtonText: i18n.t('login.re_login')
// }
service.setTimeOut = time => {
service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: time
})
}
// 请根据实际需求修改
service.interceptors.response.use(response => {
response.config.loading && tryHideLoading(store.getters.currentPath)
checkAuth(response)
return response.data
}, error => {
const config = error.response && error.response.config || error.config
const headers = error.response && error.response.headers || error.response || config.headers
config.loading && tryHideLoading(store.getters.currentPath)
let msg
if (error.response) {
checkAuth(error.response)
// checkPermission(error.response)
msg = error.response.data.message || error.response.data
} else {
msg = error.message
}
!config.hideMsg && (!headers['authentication-status']) && $error(msg)
return Promise.reject(error)
})
const checkAuth = response => {
// 请根据实际需求修改
if (response.headers['authentication-status'] === 'login_expire') {
const message = i18n.t('login.expires')
// store.dispatch('user/setLoginMsg', message)
@ -103,31 +157,5 @@ const checkAuth = response => {
setLinkToken(linkToken)
store.dispatch('user/setLinkToken', linkToken)
}
// 许可状态改变 刷新页面
// if (response.headers['lic-status']) {
// location.reload()
// }
}
// 请根据实际需求修改
service.interceptors.response.use(response => {
response.config.loading && tryHideLoading(store.getters.currentPath)
checkAuth(response)
return response.data
}, error => {
const config = error.response && error.response.config || error.config
const headers = error.response && error.response.headers || error.response || config.headers
config.loading && tryHideLoading(store.getters.currentPath)
let msg
if (error.response) {
checkAuth(error.response)
// checkPermission(error.response)
msg = error.response.data.message || error.response.data
} else {
msg = error.message
}
!config.hideMsg && (!headers['authentication-status']) && $error(msg)
return Promise.reject(error)
})
export default service

View File

@ -16,6 +16,7 @@ const privateKey = 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdb
// 加密
export function encrypt(txt) {
let publicKey = localStorage.getItem("publicKey");
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对需要加密的数据进行加密
@ -28,3 +29,4 @@ export function decrypt(txt) {
return encryptor.decrypt(txt)
}

View File

@ -15,7 +15,7 @@ export const DEFAULT_SIZE = {
barGap: 0.4,
lineWidth: 1,
lineType: 'solid',
lineSymbol: 'emptyCircle',
lineSymbol: 'circle',
lineSymbolSize: 4,
lineSmooth: false,
lineArea: false,
@ -30,6 +30,7 @@ export const DEFAULT_SIZE = {
tableItemFontSize: 12,
tableTitleHeight: 36,
tableItemHeight: 36,
tablePageSize: '10',
gaugeMin: 0,
gaugeMax: 100,
gaugeStartAngle: 225,

View File

@ -36,6 +36,13 @@ export function baseLineOption(chart_option, chart) {
type: customAttr.size.lineType
}
y.smooth = customAttr.size.lineSmooth
if (customAttr.size.lineArea) {
y.areaStyle = {
opacity: 0.6
}
} else {
delete y.areaStyle
}
}
// label
if (customAttr.label) {

View File

@ -43,7 +43,7 @@ export function baseWaterfallOptionAntV(plot, container, chart, action) {
appendPadding: getPadding(chart),
label: label,
tooltip: tooltip,
legend: false,
legend: {},
xAxis: xAxis,
yAxis: yAxis,
risingFill: theme.styleSheet.paletteQualitative10[0],

View File

@ -100,6 +100,16 @@
<el-form-item :label="$t('chart.table_item_height')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.tableItemHeight" :min="36" :max="100" show-input :show-input-controls="false" input-size="mini" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item v-show="chart.type && chart.type === 'table-info'" :label="$t('chart.table_page_size')" class="form-item">
<el-select v-model="sizeForm.tablePageSize" :placeholder="$t('chart.table_page_size')" @change="changeBarSizeCase">
<el-option
v-for="item in pageSizeOptions"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
<el-form v-show="chart.type && chart.type.includes('gauge')" ref="sizeFormGauge" :disabled="param && !hasDataPermission('manage',param.privileges)" :model="sizeForm" label-width="100px" size="mini">
@ -289,6 +299,12 @@ export default {
{ name: this.$t('chart.liquid_shape_pin'), value: 'pin' },
{ name: this.$t('chart.liquid_shape_rect'), value: 'rect' }
],
pageSizeOptions: [
{ name: '10' + this.$t('chart.table_page_size_unit'), value: '10' },
{ name: '20' + this.$t('chart.table_page_size_unit'), value: '20' },
{ name: '50' + this.$t('chart.table_page_size_unit'), value: '50' },
{ name: '100' + this.$t('chart.table_page_size_unit'), value: '100' }
],
fontSize: []
}
},
@ -326,6 +342,8 @@ export default {
this.sizeForm.liquidOutlineDistance = (this.sizeForm.liquidOutlineDistance || this.sizeForm.liquidOutlineDistance === 0) ? this.sizeForm.liquidOutlineDistance : DEFAULT_SIZE.liquidOutlineDistance
this.sizeForm.liquidWaveLength = this.sizeForm.liquidWaveLength ? this.sizeForm.liquidWaveLength : DEFAULT_SIZE.liquidWaveLength
this.sizeForm.liquidWaveCount = this.sizeForm.liquidWaveCount ? this.sizeForm.liquidWaveCount : DEFAULT_SIZE.liquidWaveCount
this.sizeForm.tablePageSize = this.sizeForm.tablePageSize ? this.sizeForm.tablePageSize : DEFAULT_SIZE.tablePageSize
}
}
},

View File

@ -42,10 +42,10 @@
</el-form>
<el-form v-show="chart.type && chart.type.includes('pie')" ref="sizeFormPie" :disabled="param && !hasDataPermission('manage',param.privileges)" :model="sizeForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.pie_inner_radius')" class="form-item form-item-slider">
<el-form-item :label="$t('chart.pie_inner_radius_percent')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.pieInnerRadius" show-input :show-input-controls="false" input-size="mini" :min="0" :max="100" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item :label="$t('chart.pie_outer_radius')" class="form-item form-item-slider">
<el-form-item :label="$t('chart.pie_outer_radius_size')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.pieOuterRadius" show-input :show-input-controls="false" input-size="mini" :min="0" :max="100" @change="changeBarSizeCase" />
</el-form-item>
@ -97,6 +97,16 @@
<el-form-item :label="$t('chart.table_item_height')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.tableItemHeight" :min="36" :max="100" show-input :show-input-controls="false" input-size="mini" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item v-show="chart.type && chart.type === 'table-info'" :label="$t('chart.table_page_size')" class="form-item">
<el-select v-model="sizeForm.tablePageSize" :placeholder="$t('chart.table_page_size')" @change="changeBarSizeCase">
<el-option
v-for="item in pageSizeOptions"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
<el-form v-show="chart.type && chart.type.includes('gauge')" ref="sizeFormGauge" :disabled="param && !hasDataPermission('manage',param.privileges)" :model="sizeForm" label-width="100px" size="mini">
@ -282,6 +292,12 @@ export default {
{ name: this.$t('chart.liquid_shape_pin'), value: 'pin' },
{ name: this.$t('chart.liquid_shape_rect'), value: 'rect' }
],
pageSizeOptions: [
{ name: '10' + this.$t('chart.table_page_size_unit'), value: '10' },
{ name: '20' + this.$t('chart.table_page_size_unit'), value: '20' },
{ name: '50' + this.$t('chart.table_page_size_unit'), value: '50' },
{ name: '100' + this.$t('chart.table_page_size_unit'), value: '100' }
],
fontSize: []
}
},
@ -319,6 +335,8 @@ export default {
this.sizeForm.liquidOutlineDistance = (this.sizeForm.liquidOutlineDistance || this.sizeForm.liquidOutlineDistance === 0) ? this.sizeForm.liquidOutlineDistance : DEFAULT_SIZE.liquidOutlineDistance
this.sizeForm.liquidWaveLength = this.sizeForm.liquidWaveLength ? this.sizeForm.liquidWaveLength : DEFAULT_SIZE.liquidWaveLength
this.sizeForm.liquidWaveCount = this.sizeForm.liquidWaveCount ? this.sizeForm.liquidWaveCount : DEFAULT_SIZE.liquidWaveCount
this.sizeForm.tablePageSize = this.sizeForm.tablePageSize ? this.sizeForm.tablePageSize : DEFAULT_SIZE.tablePageSize
}
}
},

View File

@ -42,7 +42,7 @@
:page-sizes="[10,20,50,100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="sizes, prev, pager, next"
layout="prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@ -163,6 +163,8 @@ export default {
let datas = []
if (this.chart.data) {
this.fields = JSON.parse(JSON.stringify(this.chart.data.fields))
const attr = JSON.parse(this.chart.customAttr)
this.currentPage.pageSize = parseInt(attr.size.tablePageSize ? attr.size.tablePageSize : 10)
datas = JSON.parse(JSON.stringify(this.chart.data.tableRow))
if (this.chart.type === 'table-info') {
//
@ -283,10 +285,11 @@ export default {
const that = this
const means = [] //
columns.forEach((column, columnIndex) => {
if (columnIndex === 0) {
const x = JSON.parse(that.chart.xaxis)
if (columnIndex === 0 && x.length > 0) {
means.push('合计')
} else {
if (columnIndex >= that.chart.data.fields.length - that.chart.data.series.length) {
if (columnIndex >= x.length) {
const values = data.map(item => Number(item[column.property]))
//
if (!values.every(value => isNaN(value))) {

View File

@ -31,6 +31,7 @@
value-format="timestamp"
:picker-options="pickerOptions"
default-time="23:59:59"
popper-class="link-date-picker-class"
@change="resetOverTime"
/>
</el-form-item>
@ -241,4 +242,5 @@ export default {
margin: 15px 0px 5px;
text-align: right;
}
</style>

View File

@ -63,10 +63,11 @@
<script>
import { encrypt } from '@/utils/rsaEncrypt'
import { ldapStatus, oidcStatus } from '@/api/user'
import { ldapStatus, oidcStatus, getPublicKey } from '@/api/user'
import { getSysUI } from '@/utils/auth'
import PluginCom from '@/views/system/plugin/PluginCom'
import Cookies from 'js-cookie'
import store from "@/store";
export default {
name: 'Login',
components: { PluginCom },
@ -116,6 +117,12 @@ export default {
this.loginTypes.push(2)
}
})
getPublicKey().then(res => {
if (res.success && res.data) {
//
localStorage.setItem('publicKey', res.data)
}
})
},
created() {
this.$store.dispatch('user/getUI').then(() => {
@ -162,11 +169,12 @@ export default {
if (valid) {
this.loading = true
const user = {
username: this.loginForm.username,
password: this.loginForm.password,
username: encrypt(this.loginForm.username),
password: encrypt(this.loginForm.password),
loginType: this.loginForm.loginType
}
user.password = encrypt(user.password)
let publicKey = localStorage.getItem("publicKey");
console.log(publicKey)
this.$store.dispatch('user/login', user).then(() => {
this.$router.push({ path: this.redirect || '/' })
this.loading = false

View File

@ -229,7 +229,7 @@ export default {
}
.filter-widget {
width: 100px;
width: 107px;
height: 36px;
position: relative;
float: left;

View File

@ -161,7 +161,7 @@ export default {
}
.filter-widget {
width: 100px;
width: 107px;
height: 36px;
position: relative;
float: left;

View File

@ -3,15 +3,15 @@
<de-aside-container style="padding: 0 10px;">
<el-tabs v-model="activeName" class="tab-panel" :stretch="true" @tab-click="handleClick">
<el-tab-pane name="PanelList">
<span slot="label"><i class="el-icon-document" />{{ $t('panel.panel_list') }}</span>
<span slot="label"><i class="el-icon-document tablepanel-i" />{{ $t('panel.panel_list') }}</span>
<panel-list v-if="activeName==='PanelList'" />
</el-tab-pane>
<el-tab-pane name="panels_star" :lazy="true">
<span slot="label"><i class="el-icon-star-off" />{{ $t('panel.store') }}</span>
<span slot="label"><i class="el-icon-star-off tablepanel-i" />{{ $t('panel.store') }}</span>
<enshrine v-if="activeName==='panels_star'" />
</el-tab-pane>
<el-tab-pane name="panels_share" :lazy="true">
<span slot="label"><i class="el-icon-share" />{{ $t('panel.share') }}</span>
<span slot="label"><i class="el-icon-share tablepanel-i" />{{ $t('panel.share') }}</span>
<share-tree v-if="showShare" ref="share_tree" :msg-panel-ids="msgPanelIds" />
</el-tab-pane>
</el-tabs>

View File

@ -3,7 +3,7 @@
<de-aside-container>
<el-tabs v-model="currentTemplateType" @tab-click="handleClick">
<el-tab-pane name="system">
<span slot="label"><i class="el-icon-document" /> {{ $t('panel.sys_template') }}</span>
<span slot="label"><i class="el-icon-document tablepanel-i" /> {{ $t('panel.sys_template') }}</span>
<template-list
v-if="currentTemplateType==='system'"
:template-type="currentTemplateType"
@ -16,7 +16,7 @@
/>
</el-tab-pane>
<el-tab-pane name="self">
<span slot="label"><i class="el-icon-star-off" />{{ $t('panel.user_template') }}</span>
<span slot="label"><i class="el-icon-star-off tablepanel-i" />{{ $t('panel.user_template') }}</span>
<!--v-if 重新渲染 强制刷新首行高亮属性-->
<template-list
v-if="currentTemplateType==='self'"

View File

@ -0,0 +1,144 @@
<template>
<div>
<!--基础配置表单-->
<el-form
ref="formInline"
v-loading="loading"
:model="formInline"
:rules="rules"
class="demo-form-inline"
:disabled="show"
size="small"
>
<el-row>
<el-col>
<el-form-item :label="$t('system_parameter_setting.front_time_out')" prop="frontTimeOut">
<el-input
v-model="formInline.frontTimeOut"
:placeholder="$t('system_parameter_setting.empty_front')"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col>
<el-form-item :label="$t('system_parameter_setting.msg_time_out')" prop="msgTimeOut">
<el-input
v-model="formInline.msgTimeOut"
:placeholder="$t('system_parameter_setting.empty_msg')"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button v-if="showEdit" size="small" @click="edit">{{ $t('commons.edit') }}</el-button>
<el-button v-if="showSave" type="success" :disabled="disabledSave" size="small" @click="save('formInline')">
{{ $t('commons.save') }}
</el-button>
<el-button v-if="showCancel" type="info" size="small" @click="cancel">{{ $t('commons.cancel') }}</el-button>
</div>
</div>
</template>
<script>
import { basicInfo, updateInfo } from '@/api/system/basic'
export default {
name: 'EmailSetting',
data() {
return {
formInline: {},
input: '',
visible: true,
showEdit: true,
showSave: false,
showCancel: false,
show: true,
disabledSave: false,
loading: false,
rules: {
frontTimeOut: [
{
pattern: '^([0-9]{1,2}|100)$',
message: this.$t('system_parameter_setting.front_error'),
trigger: 'blur'
}
],
msgTimeOut: [
{
pattern: '^[0-9]*$',
message: this.$t('system_parameter_setting.msg_error'),
trigger: 'blur'
}
]
}
}
},
created() {
this.query()
},
methods: {
query() {
basicInfo().then(response => {
this.formInline = response.data
this.$nextTick(() => {
this.$refs.formInline.clearValidate()
})
})
},
edit() {
this.showEdit = false
this.showSave = true
this.showCancel = true
this.show = false
},
save(formInline) {
this.showEdit = true
this.showCancel = false
this.showSave = false
this.show = true
const param = [
{ paramKey: 'basic.frontTimeOut', paramValue: this.formInline.frontTimeOut, type: 'text', sort: 1 },
{ paramKey: 'basic.msgTimeOut', paramValue: this.formInline.msgTimeOut, type: 'text', sort: 2 }
]
this.$refs[formInline].validate(valid => {
if (valid) {
updateInfo(param).then(response => {
const flag = response.success
if (flag) {
this.$success(this.$t('commons.save_success'))
window.location.reload()
} else {
this.$message.error(this.$t('commons.save_failed'))
}
})
} else {
// this.result = false
}
})
},
cancel() {
this.showEdit = true
this.showCancel = false
this.showSave = false
this.show = true
this.query()
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,5 +1,5 @@
<template>
<div v-loading="result.loading">
<div>
<!--邮件表单-->
<el-form
ref="formInline"
@ -98,7 +98,7 @@
<script>
import { post, get } from '@/api/commonAjax'
import { emailInfo, updateInfo, validate } from '@/api/system/email'
export default {
name: 'EmailSetting',
@ -107,7 +107,6 @@ export default {
formInline: {},
input: '',
visible: true,
result: {},
showEdit: true,
showSave: false,
showCancel: false,
@ -148,11 +147,10 @@ export default {
this.$refs.input = 'password'
},
query() {
this.result = get('/system/mail/info', response => {
emailInfo().then(response => {
this.formInline = response.data
this.formInline.ssl = this.formInline.ssl === 'true'
this.formInline.tls = this.formInline.tls === 'true'
// console.log(this.formInline)
this.$nextTick(() => {
this.$refs.formInline.clearValidate()
})
@ -179,7 +177,7 @@ export default {
}
this.$refs[formInline].validate((valid) => {
if (valid) {
this.result = post('/system/testConnection', param, response => {
validate(param).then(response => {
this.$success(this.$t('commons.connection_successful'))
})
} else {
@ -211,7 +209,7 @@ export default {
this.$refs[formInline].validate(valid => {
if (valid) {
this.result = post('/system/edit/email', param, response => {
updateInfo(param).then(response => {
const flag = response.success
if (flag) {
this.$success(this.$t('commons.save_success'))
@ -220,7 +218,7 @@ export default {
}
})
} else {
return false
// this.result = false
}
})
},

View File

@ -0,0 +1,54 @@
<template>
<layout-content v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane :lazy="true" :label="$t('system_parameter_setting.basic_setting')" name="zero">
<basic-setting />
</el-tab-pane>
<el-tab-pane :lazy="true" :label="$t('system_parameter_setting.mailbox_service_settings')" name="first">
<email-setting />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.display')" name="second">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="DisplaySetting" />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.ldap')" name="third">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="LdapSetting" />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.oidc')" name="fourth">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="SsoSetting" />
</el-tab-pane>
</el-tabs>
</layout-content>
</template>
<script>
import BasicSetting from './BasicSetting'
import EmailSetting from './EmailSetting'
import LayoutContent from '@/components/business/LayoutContent'
import PluginCom from '@/views/system/plugin/PluginCom'
import { pluginLoaded } from '@/api/user'
export default {
components: { BasicSetting, EmailSetting, LayoutContent, PluginCom },
data() {
return {
activeName: 'zero',
isPluginLoaded: false
}
},
beforeCreate() {
pluginLoaded().then(res => {
this.isPluginLoaded = res.success && res.data
})
},
methods: {
handleClick(tab, event) {
console.log(tab, event)
}
}
}
</script>

View File

@ -163,6 +163,8 @@ export default {
return 'MariaDB'
} else if (type === 'ds_doris') {
return 'Doris'
} else if (type === 'mongo') {
return 'MongoDB'
}
},

View File

@ -158,7 +158,8 @@ export default {
{ name: 'es', label: 'Elasticsearch', type: 'es' },
{ name: 'mariadb', label: 'MariaDB', type: 'jdbc', extraParams: 'characterEncoding=UTF-8&connectTimeout=5000&useSSL=false&allowPublicKeyRetrieval=true' },
{ name: 'ds_doris', label: 'Doris', type: 'jdbc', extraParams: 'characterEncoding=UTF-8&connectTimeout=5000&useSSL=false&allowPublicKeyRetrieval=true' },
{ name: 'ck', label: 'ClickHouse', type: 'jdbc', extraParams: '' }
{ name: 'ck', label: 'ClickHouse', type: 'jdbc', extraParams: '' },
{ name: 'mongo', label: 'MongoDB', type: 'jdbc', extraParams: '' }
],
schemas: [],
canEdit: false,

View File

@ -1,21 +0,0 @@
<template>
<router-view />
</template>
<script>
export default ({
data() {
return {
}
},
created() {
this.$store.dispatch('app/toggleSideBarHide', false)
},
method: {
}
})
</script>

View File

@ -1,21 +0,0 @@
<template>
<h2>this is sso page</h2>
</template>
<script>
export default ({
data() {
return {
}
},
created() {
this.$store.dispatch('app/toggleSideBarHide', false)
},
method: {
}
})
</script>

View File

@ -1,10 +0,0 @@
<template>
<h2>
this is display settings page
</h2>
</template>
<script>
export default {
}
</script>

View File

@ -1,322 +0,0 @@
<template>
<div v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
<el-form
ref="systemParams"
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
class="demo-form-inline"
:disabled="show"
size="small"
>
<el-row>
<el-col v-for="(param,index) in systemParams" :key="index">
<!--logo upload-->
<el-form-item
v-if="param.paramKey==='ui.logo'"
:label="$t('display.logo')"
>
<el-upload
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
style="float: right;margin-left: 10px"
class="upload-demo"
action=""
accept=".jpeg,.jpg,.png,.gif"
:on-exceed="handleExceed"
:before-upload="uploadValidate"
:on-error="handleError"
:show-file-list="false"
:file-list="filesTmp"
:http-request="uploadLogo"
>
<el-button style="display: inline-block" size="mini" type="success" plain>
{{ $t('commons.upload') }}
</el-button>
</el-upload>
<el-button
style="float:right;margin-top: 3px"
size="mini"
type="danger"
plain
@click="removeValue('ui.logo')"
>
{{ $t('commons.clear') }}
</el-button>
<el-input
v-model="param.fileName"
:disabled="true"
:placeholder="$t('display.advice_size')+'135px * 30px'"
/>
</el-form-item>
<!--logo upload-->
<el-form-item
v-if="param.paramKey==='ui.loginImage'"
:label="$t('display.loginImage')"
>
<el-upload
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
style="float: right;margin-left: 10px"
class="upload-demo"
action=""
accept=".jpeg,.jpg,.png,.gif"
:on-exceed="handleExceed"
:before-upload="uploadValidate"
:on-error="handleError"
:show-file-list="false"
:file-list="filesTmp"
:http-request="uploadLoginImage"
>
<el-button style="display: inline-block" size="mini" type="success" plain>
{{ $t('commons.upload') }}
</el-button>
</el-upload>
<el-button
style="float:right;margin-top: 3px"
size="mini"
type="danger"
plain
@click="removeValue('ui.loginImage')"
>
{{ $t('commons.clear') }}
</el-button>
<el-input
v-model="param.fileName"
:disabled="true"
:placeholder="$t('display.advice_size')+'500px * 450px'"
/>
</el-form-item>
<!--favicon upload-->
<el-form-item
v-if="param.paramKey==='ui.loginLogo'"
:label="$t('display.loginLogo')"
>
<el-upload
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
style="float: right;margin-left: 10px"
class="upload-demo"
action=""
accept=".jpeg,.jpg,.png,.gif"
:on-exceed="handleExceed"
:before-upload="uploadValidate"
:on-error="handleError"
:show-file-list="false"
:file-list="filesTmp"
:http-request="uploadLoginLogo"
>
<el-button style="display: inline-block" size="mini" type="success" plain>
{{ $t('commons.upload') }}
</el-button>
</el-upload>
<el-button
style="float:right;margin-top: 3px"
size="mini"
type="danger"
plain
@click="removeValue('ui.loginLogo')"
>
{{ $t('commons.clear') }}
</el-button>
<el-input
v-model="param.fileName"
:disabled="true"
:placeholder="$t('display.advice_size')+'135px * 30px'"
/>
</el-form-item>
<!--favicon upload-->
<el-form-item
v-show="showfavicon"
v-if="param.paramKey==='ui.favicon'"
:label="$t('display.favicon')"
>
<el-upload
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
style="float: right;margin-left: 10px"
class="upload-demo"
action=""
accept=".jpeg,.jpg,.png,.gif"
:on-exceed="handleExceed"
:before-upload="uploadValidate"
:on-error="handleError"
:show-file-list="false"
:file-list="filesTmp"
:http-request="uploadFavicon"
>
<el-button style="display: inline-block" size="mini" type="success" plain>
{{ $t('commons.upload') }}
</el-button>
</el-upload>
<el-button
style="float:right;margin-top: 3px"
size="mini"
type="danger"
plain
@click="removeValue('ui.favicon')"
>
{{ $t('commons.clear') }}
</el-button>
<el-input
v-model="param.fileName"
:disabled="true"
:placeholder="$t('display.advice_size')+'16px * 16px'"
/>
</el-form-item>
<!--ui.loginTitle-->
<el-form-item v-if="param.paramKey==='ui.loginTitle'" :label="$t('display.loginTitle')">
<el-input v-model="param.paramValue" placeholder="egDateEase" />
</el-form-item>
<!--ui.title-->
<el-form-item v-if="param.paramKey==='ui.title'" :label="$t('display.title')">
<el-input v-model="param.paramValue" placeholder="egDateEase" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button v-if="showEdit" size="small" @click="edit">{{ $t('commons.edit') }}</el-button>
<el-button v-if="showSave" type="success" :disabled="disabledSave" size="small" @click="save">
{{ $t('commons.save') }}
</el-button>
<el-button v-if="showCancel" type="info" size="small" @click="cancel">{{ $t('commons.cancel') }}</el-button>
</div>
</div>
</template>
<script>
import { get, fileUpload } from '@/api/commonAjax'
export default {
name: 'UiSetting',
components: {
},
data() {
return {
filesTmp: [],
suffixes: new Set(['png', 'jpg', 'gif', 'jpeg']),
files: [],
systemParams: [],
systemParamsOld: [],
input: '',
visible: true,
result: {},
showEdit: true,
showSave: false,
showCancel: false,
show: true,
disabledConnection: false,
disabledSave: false,
loading: false,
rules: {
url: [
{
required: true,
message: 'Not Null',
trigger: ['change', 'blur']
}
]
},
showfavicon: false
}
},
created() {
this.query()
},
methods: {
query() {
get('/system/ui/info').then(res => {
this.systemParams = res.data
})
},
edit() {
this.showEdit = false
this.showSave = true
this.showCancel = true
this.show = false
},
save() {
this.showEdit = true
this.showCancel = false
this.showSave = false
this.show = true
this.systemParams.forEach((systemParam) => {
if (systemParam.file !== null) {
const file = systemParam.file
const name = file.name + ',' + systemParam.paramKey
const newfile = new File([file], name, { type: file.type })
this.files.push(newfile)
systemParam.file = null
}
})
fileUpload('/system/save/ui', null, this.files, { 'systemParams': this.systemParams }).then(response => {
if (response.success) {
this.query()//
this.$success(this.$t('commons.save_success'))
} else {
this.$message.error(this.$t('commons.save_failed'))
}
})
},
cancel() {
this.showEdit = true
this.showCancel = false
this.showSave = false
this.show = true
this.query()
},
handleExceed(files, fileList) {
this.$warning(this.$t('test_track.case.import.upload_limit_count'))
},
handleError() {
this.$warning(this.$t('test_track.case.import.upload_limit_count'))
},
uploadValidate(file) {
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1)
if (!this.suffixes.has(suffix)) {
this.$warning(this.$t('test_track.case.import.upload_limit_format'))
return false
}
if (file.size / 1024 / 1024 > 5) {
this.$warning(this.$t('test_track.case.import.upload_limit_size'))
return false
}
this.errList = []
return true
},
uploadLogo(file) {
this.upload(file, 'ui.logo')
},
uploadFavicon(file) {
this.upload(file, 'ui.favicon')
},
uploadLoginImage(file) {
this.upload(file, 'ui.loginImage')
},
uploadLoginLogo(file) {
this.upload(file, 'ui.loginLogo')
},
upload(file, paramKey) {
this.systemParams.forEach((systemParam) => {
if (systemParam.paramKey === paramKey) {
systemParam.fileName = file.file.name
systemParam.file = file.file
}
})
},
removeValue(paramKey) {
this.systemParams.forEach((systemParam) => {
if (systemParam.paramKey === paramKey) {
systemParam.fileName = null
systemParam.file = null
}
})
}
}
}
</script>
<style scoped>
.el-form {
min-height: 300px;
}
</style>

View File

@ -1,45 +0,0 @@
<template>
<el-card>
<ui-setting v-if="!test" />
<!-- <el-tabs v-model="activeName" class="system-setting">
<el-tab-pane label="显示设置" name="ui">
<ui-setting />
</el-tab-pane>
<el-tab-pane :label="$t('system_parameter_setting.mailbox_service_settings')" name="email">
<email-setting />
</el-tab-pane>
</el-tabs> -->
<async-component v-if="test" url="http://localhost:8081/PluginDemo.js" @execute-axios="executeAxios" />
</el-card>
</template>
<script>
import UiSetting from './UiSetting'
import AsyncComponent from '@/components/AsyncComponent'
export default {
name: 'SystemParameterSetting',
components: {
UiSetting,
AsyncComponent
// 'MsDisplay': display.default,
// 'MsAuth': auth.default
},
data() {
return {
activeName: 'ui',
test: false
}
},
methods: {
// hasLicense
executeAxios(options) {
// console.log(options)
}
}
}
</script>
<style scoped>
</style>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.dataease</groupId>
<artifactId>dataease-server</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
<packaging>pom</packaging>
<parent>