Merge branch 'dev' into pr@dev@feat_switch-dataset

This commit is contained in:
王嘉豪 2022-04-14 15:31:56 +08:00 committed by GitHub
commit 95158632c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 1647 additions and 147 deletions

View File

@ -36,12 +36,12 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</exclusions>-->
</dependency>
<dependency>

View File

@ -30,6 +30,10 @@ public interface AuthApi {
@PostMapping("/useInitPwd")
Boolean useInitPwd();
@ApiOperation("用户初始密码")
@PostMapping("/defaultPwd")
String defaultPwd();
@ApiOperation("登出")
@PostMapping("/logout")
String logout();

View File

@ -154,6 +154,11 @@ public class AuthServer implements AuthApi {
return StringUtils.equals(AuthUtils.getUser().getPassword(), md5);
}
@Override
public String defaultPwd() {
return DEFAULT_PWD;
}
@Override
public String logout() {
String token = ServletUtils.getToken();

View File

@ -42,6 +42,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/index.html", ANON);
filterChainDefinitionMap.put("/link.html", ANON);
filterChainDefinitionMap.put("/board/**", ANON);
filterChainDefinitionMap.put("/websocket/**", "anon");
// 获取主题信息
filterChainDefinitionMap.put("/plugin/theme/themes", ANON);

View File

@ -0,0 +1,12 @@
package io.dataease.commons.constants;
public class RedisConstants {
public static final String GLOBAL_REDIS_TOPIC = "global_redis_topic";
public static final String PLUGIN_INSTALL_MSG = "pluginMsgService";
public static final String WEBSOCKET_MSG = "wsMsgService";
}

View File

@ -0,0 +1,13 @@
package io.dataease.commons.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class RedisMessage<T> implements Serializable {
private String type;
private T data;
}

View File

@ -2,19 +2,24 @@ package io.dataease.config;
import io.dataease.commons.condition.RedisStatusCondition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@Conditional({RedisStatusCondition.class})
@Configuration
public class RedisConfig {
@Conditional({RedisStatusCondition.class})
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
@ -24,4 +29,11 @@ public class RedisConfig {
return redisTemplate;
}
@Bean
public RedisMessageListenerContainer redisContainer() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
return container;
}
}

View File

@ -0,0 +1,59 @@
package io.dataease.listener;
import com.google.gson.Gson;
import io.dataease.commons.condition.RedisStatusCondition;
import io.dataease.commons.constants.RedisConstants;
import io.dataease.commons.model.RedisMessage;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.LogUtil;
import io.dataease.service.redis.RedisMessageBroadcast;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Conditional({RedisStatusCondition.class})
@Service
public class RedisMessageSubscriber implements MessageListener {
@Resource
private RedisMessageListenerContainer redisMessageListenerContainer;
private static final Gson json = new Gson();
@Autowired
private RedisTemplate redisTemplate;
/**
* 启动之后订阅 topic
*/
@EventListener
public void init(ApplicationReadyEvent event) {
String topic = RedisConstants.GLOBAL_REDIS_TOPIC;
LogUtil.info("Subscribe Topic: " + topic);
redisMessageListenerContainer.addMessageListener(new MessageListenerAdapter(this), new ChannelTopic(topic));
}
/**
* @param message 消息内容
* @param pattern 暂时用不到
*/
public void onMessage(final Message message, final byte[] pattern) {
RedisMessage redisMessage = json.fromJson(message.toString(), RedisMessage.class);
RedisMessageBroadcast service = (RedisMessageBroadcast)CommonBeanFactory.getBean(redisMessage.getType());
service.messageCallBack(redisMessage.getData());
}
}

View File

@ -11,8 +11,8 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.DorisConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1026,7 +1026,11 @@ public class DorisQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getDataeaseName(), "*")) {
fieldName = DorisConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(DorisConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(DorisConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(DorisConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(DorisConstants.CAST, originField, y.getDeType() == 2 ? DorisConstants.DEFAULT_INT_FORMAT : DorisConstants.DEFAULT_FLOAT_FORMAT);
@ -1035,7 +1039,11 @@ public class DorisQueryProvider extends QueryProvider {
fieldName = String.format(DorisConstants.ROUND, cast1, "2");
} else {
String cast = String.format(DorisConstants.CAST, originField, y.getDeType() == 2 ? DorisConstants.DEFAULT_INT_FORMAT : DorisConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(DorisConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(DorisConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(DorisConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()
@ -1081,6 +1089,7 @@ public class DorisQueryProvider extends QueryProvider {
private String reflectFieldName(DatasetTableField field) {
return field.getDataeaseName();
}
private String calcFieldRegex(String originField, SQLObj tableObj) {
originField = originField.replaceAll("[\\t\\n\\r]]", "");
// 正则提取[xxx]

View File

@ -10,9 +10,9 @@ import io.dataease.dto.chart.ChartCustomFilterItemDTO;
import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.plugins.common.constants.engine.MysqlConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1030,7 +1030,11 @@ public class MysqlQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getDataeaseName(), "*")) {
fieldName = MysqlConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(MysqlConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MysqlConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(MysqlConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(MysqlConstants.CAST, originField, y.getDeType() == 2 ? MysqlConstants.DEFAULT_INT_FORMAT : MysqlConstants.DEFAULT_FLOAT_FORMAT);
@ -1039,7 +1043,11 @@ public class MysqlQueryProvider extends QueryProvider {
fieldName = String.format(MysqlConstants.ROUND, cast1, "2");
} else {
String cast = String.format(MysqlConstants.CAST, originField, y.getDeType() == 2 ? MysqlConstants.DEFAULT_INT_FORMAT : MysqlConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(MysqlConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MysqlConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(MysqlConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -12,8 +12,8 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.CKConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1039,7 +1039,11 @@ public class CKQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = CKConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(CKConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(CKConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(CKConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = y.getDeType() == 2 ? String.format(CKConstants.toInt64, originField) : String.format(CKConstants.toFloat64, originField);
@ -1047,7 +1051,11 @@ public class CKQueryProvider extends QueryProvider {
fieldName = String.format(CKConstants.toDecimal, agg);
} else {
String cast = y.getDeType() == 2 ? String.format(CKConstants.toInt64, originField) : String.format(CKConstants.toFloat64, originField);
fieldName = String.format(CKConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(CKConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(CKConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -14,6 +14,7 @@ import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.datasource.Db2Configuration;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.Db2Constants;
import io.dataease.plugins.common.constants.MySQLConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import org.apache.commons.collections4.CollectionUtils;
@ -993,7 +994,11 @@ public class Db2QueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = Db2Constants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(Db2Constants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(Db2Constants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(Db2Constants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(Db2Constants.CAST, originField, y.getDeType() == 2 ? Db2Constants.DEFAULT_INT_FORMAT : Db2Constants.DEFAULT_FLOAT_FORMAT);
@ -1001,7 +1006,11 @@ public class Db2QueryProvider extends QueryProvider {
fieldName = String.format(Db2Constants.CAST, agg, Db2Constants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(Db2Constants.CAST, originField, y.getDeType() == 2 ? Db2Constants.DEFAULT_INT_FORMAT : Db2Constants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(Db2Constants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(Db2Constants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(Db2Constants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -12,8 +12,8 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.EsSqlLConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1032,7 +1032,11 @@ public class EsQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = EsSqlLConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(EsSqlLConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(EsSqlLConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(EsSqlLConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(EsSqlLConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? "bigint" : "double");
@ -1040,7 +1044,11 @@ public class EsQueryProvider extends QueryProvider {
fieldName = String.format(EsSqlLConstants.ROUND, agg, "2");
} else {
String cast = String.format(EsSqlLConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? "bigint" : "double");
fieldName = String.format(EsSqlLConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(EsSqlLConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(EsSqlLConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -12,8 +12,8 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.HiveConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1007,7 +1007,11 @@ public class HiveQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = HiveConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(HiveConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(HiveConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(HiveConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(HiveConstants.CAST, originField, y.getDeType() == 2 ? HiveConstants.DEFAULT_INT_FORMAT : HiveConstants.DEFAULT_FLOAT_FORMAT);
@ -1015,7 +1019,11 @@ public class HiveQueryProvider extends QueryProvider {
fieldName = String.format(HiveConstants.CAST, agg, HiveConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(HiveConstants.CAST, originField, y.getDeType() == 2 ? HiveConstants.DEFAULT_INT_FORMAT : HiveConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(HiveConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(HiveConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(HiveConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -974,7 +974,11 @@ public class ImpalaQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = ImpalaConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(ImpalaConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(ImpalaConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(ImpalaConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(ImpalaConstants.CAST, originField, y.getDeType() == 2 ? ImpalaConstants.DEFAULT_INT_FORMAT : ImpalaConstants.DEFAULT_FLOAT_FORMAT);
@ -982,7 +986,11 @@ public class ImpalaQueryProvider extends QueryProvider {
fieldName = String.format(ImpalaConstants.CAST, agg, ImpalaConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(ImpalaConstants.CAST, originField, y.getDeType() == 2 ? ImpalaConstants.DEFAULT_INT_FORMAT : ImpalaConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(ImpalaConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(ImpalaConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(ImpalaConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -12,6 +12,7 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.MongoConstants;
import io.dataease.plugins.common.constants.MySQLConstants;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
@ -915,9 +916,17 @@ public class MongoQueryProvider extends QueryProvider {
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);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MongoConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MongoConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(MongoConstants.AGG_FIELD, y.getSummary(), originField);
}
}
return SQLObj.builder()
.fieldName(fieldName)

View File

@ -1011,7 +1011,11 @@ public class MysqlQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = MySQLConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(MySQLConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MySQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(MySQLConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(MySQLConstants.CAST, originField, y.getDeType() == 2 ? MySQLConstants.DEFAULT_INT_FORMAT : MySQLConstants.DEFAULT_FLOAT_FORMAT);
@ -1019,7 +1023,11 @@ public class MysqlQueryProvider extends QueryProvider {
fieldName = String.format(MySQLConstants.CAST, agg, MySQLConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(MySQLConstants.CAST, originField, y.getDeType() == 2 ? MySQLConstants.DEFAULT_INT_FORMAT : MySQLConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(MySQLConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(MySQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(MySQLConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -14,8 +14,8 @@ import io.dataease.dto.datasource.JdbcConfiguration;
import io.dataease.dto.datasource.OracleConfiguration;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.OracleConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.provider.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1083,7 +1083,11 @@ public class OracleQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = OracleConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(OracleConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(OracleConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(OracleConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(OracleConstants.CAST, originField, y.getDeType() == 2 ? OracleConstants.DEFAULT_INT_FORMAT : OracleConstants.DEFAULT_FLOAT_FORMAT);
@ -1091,7 +1095,11 @@ public class OracleQueryProvider extends QueryProvider {
fieldName = String.format(OracleConstants.CAST, agg, OracleConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(OracleConstants.CAST, originField, y.getDeType() == 2 ? OracleConstants.DEFAULT_INT_FORMAT : OracleConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(OracleConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(OracleConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(OracleConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -14,9 +14,9 @@ import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.datasource.JdbcConfiguration;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.PgConstants;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.plugins.common.constants.SqlServerSQLConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1000,7 +1000,11 @@ public class PgQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = PgConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(PgConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT);
@ -1008,7 +1012,11 @@ public class PgQueryProvider extends QueryProvider {
fieldName = String.format(PgConstants.CAST, agg, PgConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(PgConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -13,11 +13,11 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.datasource.JdbcConfiguration;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.PgConstants;
import io.dataease.plugins.common.constants.RedshiftConstants;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.plugins.common.constants.SqlServerSQLConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.plugins.common.constants.PgConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -927,7 +927,11 @@ public class RedshiftQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = PgConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(PgConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String cast = String.format(PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT);
@ -935,7 +939,11 @@ public class RedshiftQueryProvider extends QueryProvider {
fieldName = String.format(PgConstants.CAST, agg, PgConstants.DEFAULT_FLOAT_FORMAT);
} else {
String cast = String.format(PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT);
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), cast);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(PgConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast);
} else {
fieldName = String.format(PgConstants.AGG_FIELD, y.getSummary(), cast);
}
}
}
return SQLObj.builder()

View File

@ -13,9 +13,9 @@ import io.dataease.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.datasource.JdbcConfiguration;
import io.dataease.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.constants.SQLConstants;
import io.dataease.plugins.common.constants.SqlServerSQLConstants;
import io.dataease.provider.QueryProvider;
import io.dataease.plugins.common.constants.SQLConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -1050,7 +1050,11 @@ public class SqlserverQueryProvider extends QueryProvider {
if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) {
fieldName = SqlServerSQLConstants.AGG_COUNT;
} else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) {
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, y.getSummary(), originField);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField);
} else {
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, y.getSummary(), originField);
}
} else {
if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) {
String convert = String.format(SqlServerSQLConstants.CONVERT, y.getDeType() == DeTypeConstants.DE_INT ? SqlServerSQLConstants.DEFAULT_INT_FORMAT : SqlServerSQLConstants.DEFAULT_FLOAT_FORMAT, originField);
@ -1058,7 +1062,11 @@ public class SqlserverQueryProvider extends QueryProvider {
fieldName = String.format(SqlServerSQLConstants.CONVERT, SqlServerSQLConstants.DEFAULT_FLOAT_FORMAT, agg);
} else {
String convert = String.format(SqlServerSQLConstants.CONVERT, y.getDeType() == 2 ? SqlServerSQLConstants.DEFAULT_INT_FORMAT : SqlServerSQLConstants.DEFAULT_FLOAT_FORMAT, originField);
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, y.getSummary(), convert);
if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) {
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + convert);
} else {
fieldName = String.format(SqlServerSQLConstants.AGG_FIELD, y.getSummary(), convert);
}
}
}
return SQLObj.builder()

View File

@ -35,7 +35,7 @@ public class PanelLinkService {
private static final String USERPARAM = "&user=";
private static final String SHORT_URL_PREFIX = "/link/";
@Value("${server.servlet.context-path}")
@Value("${server.servlet.context-path:#{null}}")
private String contextPath;
@Resource

View File

@ -0,0 +1,6 @@
package io.dataease.service.redis;
public interface RedisMessageBroadcast<T> {
void messageCallBack(T arg);
}

View File

@ -0,0 +1,13 @@
package io.dataease.service.redis.impl;
import io.dataease.service.redis.RedisMessageBroadcast;
import org.springframework.stereotype.Service;
@Service
public class PluginMsgService implements RedisMessageBroadcast {
@Override
public void messageCallBack(Object arg) {
}
}

View File

@ -0,0 +1,29 @@
package io.dataease.service.redis.impl;
import com.google.gson.Gson;
import io.dataease.service.redis.RedisMessageBroadcast;
import io.dataease.websocket.entity.WsMessage;
import io.dataease.websocket.service.impl.StandaloneWsService;
import io.dataease.websocket.util.WsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class WsMsgService implements RedisMessageBroadcast<Map> {
private static Gson json = new Gson();
@Autowired
private StandaloneWsService standaloneWsService;
@Override
public void messageCallBack(Map arg) {
WsMessage message = json.fromJson(json.toJson(arg), WsMessage.class);
Long userId = message.getUserId();
if (WsUtil.isOnLine(userId)) {
standaloneWsService.releaseMessage(message);
}
}
}

View File

@ -1,13 +0,0 @@
package io.dataease.websocket;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class ServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(sec, request, response);
}
}

View File

@ -1,31 +0,0 @@
package io.dataease.websocket;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@ServerEndpoint(value = "/socket", configurator = ServerEndpointConfigurator.class)
@Component
public class WebSocketServer {
@OnOpen
public void onOpen(Session session) throws IOException {
}
@OnMessage
public void onMessage(Session session, String message) throws IOException {
}
@OnClose
public void onClose(Session session) throws IOException {
}
@OnError
public void onError(Session session, Throwable throwable) {
throwable.printStackTrace();
}
}

View File

@ -0,0 +1,33 @@
package io.dataease.websocket.aop;
import io.dataease.websocket.entity.WsMessage;
import io.dataease.websocket.service.WsService;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Aspect
@Component
public class WSTrigger {
@Autowired
private WsService wsService;
@AfterReturning(value = "execution(* io.dataease.service.message.service.strategy.SendStation.sendMsg(..))")
public void after(JoinPoint point) {
Object[] args = point.getArgs();
Optional.ofNullable(args).ifPresent(objs -> {
if (ArrayUtils.isEmpty(objs)) return;
Object arg = args[0];
Long userId = (Long) arg;
WsMessage message = new WsMessage(userId, "/web-msg-topic", "refresh");
wsService.releaseMessage(message);
});
}
}

View File

@ -0,0 +1,39 @@
package io.dataease.websocket.config;
import io.dataease.websocket.factory.DeWsHandlerFactory;
import io.dataease.websocket.handler.PrincipalHandshakeHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
@Configuration
@EnableWebSocketMessageBroker
public class WsConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.setAllowedOriginPatterns("*")
.setHandshakeHandler(new PrincipalHandshakeHandler())
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/user");
registry.setUserDestinationPrefix("/user");
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
registry.addDecoratorFactory(new DeWsHandlerFactory());
registry.setMessageSizeLimit(8192) //设置消息字节数大小
.setSendBufferSizeLimit(8192)//设置消息缓存大小
.setSendTimeLimit(10000); //设置消息发送时间限制毫秒
}
}

View File

@ -0,0 +1,17 @@
package io.dataease.websocket.entity;
import java.security.Principal;
public class DePrincipal implements Principal {
public DePrincipal(String name) {
this.name = name;
}
private String name;
@Override
public String getName() {
return name;
}
}

View File

@ -0,0 +1,21 @@
package io.dataease.websocket.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WsMessage<T> implements Serializable {
private Long userId;
private String topic;
private T data;
}

View File

@ -0,0 +1,33 @@
package io.dataease.websocket.factory;
import io.dataease.websocket.util.WsUtil;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
public class DeWebSocketHandlerDecorator extends WebSocketHandlerDecorator {
public DeWebSocketHandlerDecorator(WebSocketHandler delegate) {
super(delegate);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String name = session.getPrincipal().getName();
Long userId = Long.parseLong(name);
WsUtil.onLine(userId);
super.afterConnectionEstablished(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
String name = session.getPrincipal().getName();
Long userId = Long.parseLong(name);
WsUtil.offLine(userId);
super.afterConnectionClosed(session, closeStatus);
}
}

View File

@ -0,0 +1,15 @@
package io.dataease.websocket.factory;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
public class DeWsHandlerFactory implements WebSocketHandlerDecoratorFactory {
@Override
public WebSocketHandler decorate(WebSocketHandler webSocketHandler) {
return new DeWebSocketHandlerDecorator(webSocketHandler);
}
}

View File

@ -0,0 +1,30 @@
package io.dataease.websocket.handler;
import io.dataease.websocket.entity.DePrincipal;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.Map;
public class PrincipalHandshakeHandler extends DefaultHandshakeHandler {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
HttpServletRequest httpRequest = servletServerHttpRequest.getServletRequest();
final String userId = httpRequest.getParameter("userId");
if (StringUtils.isEmpty(userId)) {
return null;
}
return new DePrincipal(userId);
}
return null;
//return super.determineUser(request, wsHandler, attributes);
}
}

View File

@ -0,0 +1,11 @@
package io.dataease.websocket.service;
import io.dataease.websocket.entity.WsMessage;
public interface WsService {
void releaseMessage(WsMessage wsMessage);
}

View File

@ -0,0 +1,34 @@
package io.dataease.websocket.service.impl;
import io.dataease.commons.condition.RedisStatusCondition;
import io.dataease.commons.constants.RedisConstants;
import io.dataease.commons.model.RedisMessage;
import io.dataease.websocket.entity.WsMessage;
import io.dataease.websocket.service.WsService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
@Conditional({RedisStatusCondition.class})
@Primary
public class DistributedWsService implements WsService {
@Autowired
private RedisTemplate redisTemplate;
public void releaseMessage(WsMessage wsMessage){
if(ObjectUtils.isEmpty(wsMessage) || ObjectUtils.isEmpty(wsMessage.getUserId()) || ObjectUtils.isEmpty(wsMessage.getTopic())) return;
RedisMessage<WsMessage> msg = new RedisMessage();
msg.setType(RedisConstants.WEBSOCKET_MSG);
msg.setData(wsMessage);
redisTemplate.convertAndSend(RedisConstants.GLOBAL_REDIS_TOPIC, msg);
}
}

View File

@ -0,0 +1,21 @@
package io.dataease.websocket.service.impl;
import io.dataease.websocket.entity.WsMessage;
import io.dataease.websocket.service.WsService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class StandaloneWsService implements WsService {
@Resource
private SimpMessagingTemplate messagingTemplate;
public void releaseMessage(WsMessage wsMessage){
if(ObjectUtils.isEmpty(wsMessage) || ObjectUtils.isEmpty(wsMessage.getUserId()) || ObjectUtils.isEmpty(wsMessage.getTopic())) return;
messagingTemplate.convertAndSendToUser(String.valueOf(wsMessage.getUserId()), wsMessage.getTopic(),wsMessage.getData());
}
}

View File

@ -0,0 +1,46 @@
package io.dataease.websocket.util;
import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.commons.utils.AuthUtils;
import org.apache.commons.lang3.ObjectUtils;
import java.util.concurrent.CopyOnWriteArraySet;
public class WsUtil {
private static final CopyOnWriteArraySet<Long> ONLINE_USERS = new CopyOnWriteArraySet();
public static boolean onLine() {
CurrentUserDto user = AuthUtils.getUser();
if (ObjectUtils.isNotEmpty(user) && ObjectUtils.isNotEmpty(user.getUserId()))
return onLine(user.getUserId());
return false;
}
public static boolean onLine(Long userId) {
return ONLINE_USERS.add(userId);
}
public static boolean offLine() {
CurrentUserDto user = AuthUtils.getUser();
if (ObjectUtils.isNotEmpty(user) && ObjectUtils.isNotEmpty(user.getUserId()))
return offLine(user.getUserId());
return false;
}
public static boolean offLine(Long userId) {
return ONLINE_USERS.remove(userId);
}
public static boolean isOnLine(Long userId) {
return ONLINE_USERS.contains(userId);
}
/*public static void releaseMessage(WsMessage wsMessage){
if(ObjectUtils.isEmpty(wsMessage) || ObjectUtils.isEmpty(wsMessage.getUserId()) || ObjectUtils.isEmpty(wsMessage.getTopic())) return;
CommonBeanFactory.getBean()
}*/
}

File diff suppressed because one or more lines are too long

View File

@ -45,6 +45,8 @@
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"screenfull": "4.2.0",
"sockjs-client": "^1.6.0",
"stompjs": "^2.3.3",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"tinymce": "^5.8.2",

View File

@ -29,6 +29,13 @@ export function needModifyPwd() {
})
}
export function defaultPwd() {
return request({
url: '/api/auth/defaultPwd',
method: 'post'
})
}
export function validateUserName(data) {
return request({
url: '/api/auth/validateName',

View File

@ -1,7 +1,6 @@
<template>
<el-popover
v-model="visible"
width="350"
trigger="click"
@ -9,7 +8,7 @@
style="display: flex;align-items: center;"
class="international"
>
<div>
<div v-loading="loading">
<div style="height: 30px;">
<div style="float: left;font-size:16px;font-weight:bold;">
<span>{{ $t('webmsg.web_msg') }}</span>
@ -49,17 +48,10 @@
</div>
</div>
<div slot="reference">
<el-badge :value="count || paginationConfig.total" :hidden="!count && !paginationConfig.total" :max="99" class="item">
<el-badge :value="visible && !loading ? paginationConfig.total : count" :hidden="!count && !paginationConfig.total" :max="99" class="item">
<svg-icon class-name="notification" icon-class="notification" />
</el-badge>
<!-- <div>
<svg-icon
class-name="notification"
icon-class="notification"
/>
<span v-if="count || paginationConfig.total" class="msg-number">{{ count || paginationConfig.total }}</span>
</div>
</div> -->
</div></el-popover>
</template>
@ -81,7 +73,8 @@ export default {
total: 0
},
timer: null,
count: 0
count: 0,
loading: false
}
},
computed: {
@ -101,14 +94,23 @@ export default {
//
loadMsgTypes()
this.queryCount()
// this.search()
// 30s
this.timer = setInterval(() => {
/* this.timer = setInterval(() => {
this.queryCount()
}, 30000)
}, 30000) */
},
mounted() {
bus.$on('refresh-top-notification', () => {
this.search()
if (this.visible) this.search()
else this.queryCount()
})
bus.$on('web-msg-topic-call', msg => {
console.log('收到websocket消息')
this.count = (this.count || this.paginationConfig.total) + 1
// this.queryCount()
// this.search()
})
},
beforeDestroy() {
@ -195,6 +197,7 @@ export default {
})
},
search() {
this.loading = true
const param = {
status: false,
orders: [' create_time desc ']
@ -204,7 +207,9 @@ export default {
this.data = response.data.listObject
this.paginationConfig.total = response.data.itemCount
this.count = this.paginationConfig.total
this.loading = false
}).catch(() => {
this.loading = false
const token = getToken()
if (!token || token === 'null' || token === 'undefined') {
this.timer && clearInterval(this.timer)

View File

@ -0,0 +1,117 @@
<template>
<el-select v-model="selected" multiple v-bind="$attrsAll" v-on="$listenserAll" @change="onChange">
<el-option v-for="item in mdoptionsList" :key="item.key" :label="item.label" :value="item.value" />
<slot name="default" />
</el-select>
</template>
<script>
export default {
name: 'ElSelectAll',
props: {
value: {
type: Array,
default: () => {
return []
}
},
options: {
type: Array,
default: () => {
return []
}
}
},
data() {
const selected = this.value || []
return {
selected,
mdoptionsValue: [],
oldMdoptionsValue: [],
mdoptionsList: []
}
},
computed: {
$attrsAll() {
// const val = this.$vnode.data.model && this.$vnode.data.model.value;
const result = {
// value: val,
...this.$attrs
}
return result
},
$listenserAll() {
const _this = this
return Object.assign({}, this.$listeners, {
change: () => {
this.$emit('change', (_this.selected || []).filter(v => {
return v !== 'all'
}))
},
input: () => {
this.$emit('input', (_this.selected || []).filter(v => {
return v !== 'all'
}))
}
})
}
},
watch: {
selected: {
immediate: true,
deep: true,
handler(val) {
this.$emit('input', (val || []).filter(v => {
return v !== 'all'
}))
}
},
options: {
immediate: true,
deep: true,
handler(val) {
if ((!val || val.length === 0) && !this.$slots) {
this.mdoptionsList = []
} else {
this.mdoptionsList = [{
key: 'all',
value: 'all',
label: '全部'
}, ...val]
}
}
}
},
mounted() {
},
methods: {
onChange(val) {
// eslint-disable-next-line no-debugger
const allValues = []
//
for (const item of this.mdoptionsList) {
allValues.push(item.value)
}
//
const oldVal = this.oldMdoptionsValue.length === 1 ? [] : this.oldMdoptionsValue[1] || []
//
if (val.includes('all')) this.selected = allValues
//
if (oldVal.includes('all') && !val.includes('all')) this.selected = []
//
//
if (oldVal.includes('all') && val.includes('all')) {
const index = val.indexOf('all')
val.splice(index, 1) //
this.selected = val
}
//
if (!oldVal.includes('all') && !val.includes('all')) {
if (val.length === allValues.length - 1) this.selected = ['all'].concat(val)
}
//
this.oldMdoptionsValue[1] = this.selected
}
}
}
</script>

View File

@ -10,6 +10,7 @@
:placeholder="$t(element.options.attrs.placeholder)"
:popper-append-to-body="inScreen"
:size="size"
:filterable="true"
@change="changeValue"
@focus="setOptionWidth"
@blur="onBlur"

View File

@ -131,6 +131,7 @@ export default {
default_login: 'Normal'
},
commons: {
default_pwd: 'Default Pwd',
stop: 'Stop',
first_login_tips: 'Please change the initial password',
roger_that: 'Roger That',
@ -1064,7 +1065,28 @@ export default {
total_pos_left: 'Left',
total_pos_right: 'Right',
chart_label: 'Label',
drag_block_label: 'Label'
drag_block_label: 'Label',
count_distinct: 'Distinct Count',
table_page_mode: 'Page Mode',
page_mode_page: 'Page',
page_mode_pull: 'Pull',
exp_can_not_empty: 'Condition can not be empty',
value_formatter: 'Value Formatter',
value_formatter_type: 'Formatter Type',
value_formatter_auto: 'Auto',
value_formatter_value: 'Value',
value_formatter_percent: 'Percent',
value_formatter_unit: 'Unit',
value_formatter_decimal_count: 'Decimal Count',
value_formatter_suffix: 'Unit Suffix',
value_formatter_thousand_separator: 'Thousand Separator',
value_formatter_example: 'Example',
unit_none: 'None',
unit_thousand: 'Thousand',
unit_ten_thousand: 'Ten Thousand',
unit_million: 'Million',
unit_hundred_million: 'Hundred Million',
formatter_decimal_count_error: 'Range 0-10'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',
@ -1662,7 +1684,10 @@ export default {
themeDark: 'Dark',
themeCustom: 'Custom',
openHomePage: 'Show Home Page',
mobileBG: 'Mobile Login page BG'
mobileBG: 'Mobile Login page BG',
helpLink: 'Help Document Link',
homeLink: 'Home Link',
defaultHomeLink: 'Default is the system built-in home page'
},
auth: {

View File

@ -131,6 +131,7 @@ export default {
default_login: '普通登錄'
},
commons: {
default_pwd: '初始密碼',
stop: '停止',
first_login_tips: '您使用的是初始密碼,記得修改密碼哦',
roger_that: '知道了',
@ -1064,7 +1065,28 @@ export default {
total_pos_left: '左側',
total_pos_right: '右側',
chart_label: '文本卡',
drag_block_label: '標簽'
drag_block_label: '標簽',
count_distinct: '去重計數',
table_page_mode: '分頁模式',
page_mode_page: '翻頁',
page_mode_pull: '下拉',
exp_can_not_empty: '條件不能為空',
value_formatter: '數值格式',
value_formatter_type: '格式類型',
value_formatter_auto: '自動',
value_formatter_value: '數值',
value_formatter_percent: '百分比',
value_formatter_unit: '數量單位',
value_formatter_decimal_count: '小數位數',
value_formatter_suffix: '單位後綴',
value_formatter_thousand_separator: '千分符',
value_formatter_example: '示例',
unit_none: '無',
unit_thousand: '千',
unit_ten_thousand: '萬',
unit_million: '百萬',
unit_hundred_million: '億',
formatter_decimal_count_error: '請輸入0-10的整數'
},
dataset: {
sheet_warn: '有多個 Sheet 頁,默認抽取第一個',
@ -1672,7 +1694,10 @@ export default {
themeCustom: '自定義',
openHomePage: '顯示首頁',
mobileBG: '移動端登錄頁背景'
mobileBG: '移動端登錄頁背景',
helpLink: '幫助文檔鏈接',
homeLink: '首頁鏈接',
defaultHomeLink: '默認為系統內置首頁'
},
auth: {

View File

@ -131,6 +131,7 @@ export default {
default_login: '普通登录'
},
commons: {
default_pwd: '初始密码',
stop: '停止',
first_login_tips: '您使用的是初始密码,记得修改密码哦',
roger_that: '知道了',
@ -1067,7 +1068,28 @@ export default {
total_pos_left: '左侧',
total_pos_right: '右侧',
chart_label: '文本卡',
drag_block_label: '标签'
drag_block_label: '标签',
count_distinct: '去重计数',
table_page_mode: '分页模式',
page_mode_page: '翻页',
page_mode_pull: '下拉',
exp_can_not_empty: '条件不能为空',
value_formatter: '数值格式',
value_formatter_type: '格式类型',
value_formatter_auto: '自动',
value_formatter_value: '数值',
value_formatter_percent: '百分比',
value_formatter_unit: '数量单位',
value_formatter_decimal_count: '小数位数',
value_formatter_suffix: '单位后缀',
value_formatter_thousand_separator: '千分符',
value_formatter_example: '示例',
unit_none: '无',
unit_thousand: '千',
unit_ten_thousand: '万',
unit_million: '百万',
unit_hundred_million: '亿',
formatter_decimal_count_error: '请输入0-10的整数'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
@ -1680,7 +1702,10 @@ export default {
themeDark: '深色',
themeCustom: '自定义',
openHomePage: '显示首页',
mobileBG: '移动端登录页背景'
mobileBG: '移动端登录页背景',
helpLink: '帮助文档链接',
homeLink: '首页链接',
defaultHomeLink: '默认为系统内置首页'
},
auth: {

View File

@ -27,7 +27,7 @@
<lang-select class="right-menu-item hover-effect" />
<div style="height: 100%;padding: 0 8px;" class="right-menu-item hover-effect">
<a
href="https://dataease.io/docs/"
:href="helpLink"
target="_blank"
style="display: flex;height: 100%;width: 100%;justify-content: center;align-items: center;"
>
@ -151,6 +151,12 @@ export default {
}
return this.variables.topBarMenuTextActive
},
helpLink() {
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.helpLink'] && this.$store.getters.uiInfo['ui.helpLink'].paramValue) {
return this.$store.getters.uiInfo['ui.helpLink'].paramValue
}
return 'https://dataease.io/docs/'
},
/* topMenuColor() {
return this.$store.getters.uiInfo.topMenuColor
}, */

View File

@ -25,6 +25,7 @@ import '@/components/canvas/custom-component' // 注册自定义组件
import '@/utils/DateUtil'
import draggable from 'vuedraggable'
import deWebsocket from '@/websocket'
Vue.config.productionTip = false
Vue.use(VueClipboard)
Vue.use(widgets)
@ -113,6 +114,7 @@ Vue.prototype.checkPermission = function(pers) {
})
return hasPermission
}
Vue.use(deWebsocket)
new Vue({
router,

View File

@ -19,6 +19,8 @@ import {
import Layout from '@/layout/index'
// import bus from './utils/bus'
import { getSocket } from '@/websocket'
NProgress.configure({
showSpinner: false
}) // NProgress Configuration
@ -57,6 +59,8 @@ router.beforeEach(async(to, from, next) => {
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
// get user info
store.dispatch('user/getInfo').then(() => {
const deWebsocket = getSocket()
deWebsocket && deWebsocket.reconnect && deWebsocket.reconnect()
store.dispatch('lic/getLicInfo').then(() => {
loadMenus(next, to)
}).catch(() => {

View File

@ -811,3 +811,9 @@ div:focus {
padding-top: 0px;
}
}
.pwd-tips > span {
font-weight: 800;
color: #F56C6C;
}

View File

@ -277,7 +277,8 @@ export const DEFAULT_FUNCTION_CFG = {
sliderRange: [0, 10]
}
export const DEFAULT_THRESHOLD = {
gaugeThreshold: ''
gaugeThreshold: '',
labelThreshold: []
}
// chart config
export const BASE_BAR = {

View File

@ -0,0 +1,71 @@
export const formatterItem = {
type: 'auto', // auto,value,percent
unit: 1, // 换算单位
suffix: '', // 单位后缀
decimalCount: 2, // 小数位数
thousandSeparator: true// 千分符
}
// 单位list
export const unitList = [
{ name: 'unit_none', value: 1 },
{ name: 'unit_thousand', value: 1000 },
{ name: 'unit_ten_thousand', value: 10000 },
{ name: 'unit_million', value: 1000000 },
{ name: 'unit_hundred_million', value: 100000000 }
]
// 格式化方式
export const formatterType = [
{ name: 'value_formatter_auto', value: 'auto' },
{ name: 'value_formatter_value', value: 'value' },
{ name: 'value_formatter_percent', value: 'percent' }
]
export function valueFormatter(value, formatter) {
// 1.unit 2.decimal 3.thousand separator and suffix
let result
if (formatter.type === 'auto') {
result = transSeparatorAndSuffix(transUnit(value, formatter), formatter)
} else if (formatter.type === 'value') {
result = transSeparatorAndSuffix(transDecimal(transUnit(value, formatter), formatter), formatter)
} else if (formatter.type === 'percent') {
value = value * 100
result = transSeparatorAndSuffix(transDecimal(value, formatter), formatter)
} else {
result = value
}
return result
}
function transUnit(value, formatter) {
return value / formatter.unit
}
function transDecimal(value, formatter) {
return value.toFixed(formatter.decimalCount)
}
function transSeparatorAndSuffix(value, formatter) {
let str = value + ''
if (formatter.thousandSeparator) {
const thousandsReg = /(\d)(?=(\d{3})+$)/g
const numArr = str.split('.')
numArr[0] = numArr[0].replace(thousandsReg, '$1,')
str = numArr.join('.')
}
if (formatter.type === 'percent') {
str += '%'
} else {
if (formatter.unit === 1000) {
str += '千'
} else if (formatter.unit === 10000) {
str += '万'
} else if (formatter.unit === 1000000) {
str += '百万'
} else if (formatter.unit === 100000000) {
str += '亿'
}
}
return str + formatter.suffix.replace(/(^\s*)|(\s*$)/g, '')
}

View File

@ -77,6 +77,9 @@
</el-dropdown>
</el-dropdown-item>
<el-dropdown-item v-if="chart.render === 'antv' && chart.type.includes('table')" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<span>{{ $t('chart.value_formatter') }}...</span>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">
<span>{{ $t('chart.show_name_set') }}</span>
</el-dropdown-item>
@ -93,6 +96,7 @@
import { getItemType } from '@/views/chart/components/drag-item/utils'
import FieldErrorTips from '@/views/chart/components/drag-item/components/FieldErrorTips'
import bus from '@/utils/bus'
import { formatterItem } from '@/views/chart/chart/formatter'
export default {
name: 'DimensionItem',
@ -110,6 +114,10 @@ export default {
type: Number,
required: true
},
chart: {
type: Object,
required: true
},
dimensionData: {
type: Array,
required: true
@ -121,7 +129,8 @@ export default {
},
data() {
return {
tagType: 'success'
tagType: 'success',
formatterItem: formatterItem
}
},
watch: {
@ -134,8 +143,14 @@ export default {
},
mounted() {
bus.$on('reset-change-table', () => this.getItemTagType())
this.init()
},
methods: {
init() {
if (!this.item.formatterCfg) {
this.item.formatterCfg = JSON.parse(JSON.stringify(this.formatterItem))
}
},
clickItem(param) {
if (!param) {
return
@ -150,6 +165,9 @@ export default {
case 'filter':
this.editFilter()
break
case 'formatter':
this.valueFormatter()
break
default:
break
}
@ -205,6 +223,12 @@ export default {
},
getItemTagType() {
this.tagType = getItemType(this.dimensionData, this.quotaData, this.item)
},
valueFormatter() {
this.item.index = this.index
this.item.formatterType = 'quota'
this.$emit('valueFormatter', this.item)
}
}
}

View File

@ -49,13 +49,14 @@
<i class="el-icon-arrow-right el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="item.id === 'count' || item.deType === 0 || item.deType === 1" :command="beforeSummary('count')">{{ $t('chart.count') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('sum')">{{ $t('chart.sum') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('avg')">{{ $t('chart.avg') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('max')">{{ $t('chart.max') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('min')">{{ $t('chart.min') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('stddev_pop')">{{ $t('chart.stddev_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('var_pop')">{{ $t('chart.var_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('sum')">{{ $t('chart.sum') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('avg')">{{ $t('chart.avg') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('max')">{{ $t('chart.max') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('min')">{{ $t('chart.min') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('stddev_pop')">{{ $t('chart.stddev_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('var_pop')">{{ $t('chart.var_pop') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('count')">{{ $t('chart.count') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('count_distinct')">{{ $t('chart.count_distinct') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown-item>
@ -98,6 +99,9 @@
<el-dropdown-item icon="el-icon-files" :command="beforeClickItem('filter')">
<span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item>
<el-dropdown-item v-if="chart.render === 'antv' && chart.type.includes('table')" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<span>{{ $t('chart.value_formatter') }}...</span>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">
<span>{{ $t('chart.show_name_set') }}</span>
</el-dropdown-item>
@ -115,6 +119,7 @@ import { compareItem } from '@/views/chart/chart/compare'
import { getItemType } from '@/views/chart/components/drag-item/utils'
import FieldErrorTips from '@/views/chart/components/drag-item/components/FieldErrorTips'
import bus from '@/utils/bus'
import { formatterItem } from '@/views/chart/chart/formatter'
export default {
name: 'QuotaExtItem',
@ -149,7 +154,8 @@ export default {
return {
compareItem: compareItem,
disableEditCompare: false,
tagType: 'success'
tagType: 'success',
formatterItem: formatterItem
}
},
watch: {
@ -177,6 +183,9 @@ export default {
if (!this.item.compareCalc) {
this.item.compareCalc = JSON.parse(JSON.stringify(this.compareItem))
}
if (!this.item.formatterCfg) {
this.item.formatterCfg = JSON.parse(JSON.stringify(this.formatterItem))
}
},
isEnableCompare() {
let xAxis = null
@ -209,6 +218,9 @@ export default {
case 'filter':
this.editFilter()
break
case 'formatter':
this.valueFormatter()
break
default:
break
}
@ -293,6 +305,12 @@ export default {
},
getItemTagType() {
this.tagType = getItemType(this.dimensionData, this.quotaData, this.item)
},
valueFormatter() {
this.item.index = this.index
this.item.formatterType = 'quota'
this.$emit('valueFormatter', this.item)
}
}
}

View File

@ -49,13 +49,14 @@
<i class="el-icon-arrow-right el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="item.id === 'count' || item.deType === 0 || item.deType === 1" :command="beforeSummary('count')">{{ $t('chart.count') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('sum')">{{ $t('chart.sum') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('avg')">{{ $t('chart.avg') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('max')">{{ $t('chart.max') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('min')">{{ $t('chart.min') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('stddev_pop')">{{ $t('chart.stddev_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1" :command="beforeSummary('var_pop')">{{ $t('chart.var_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('sum')">{{ $t('chart.sum') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('avg')">{{ $t('chart.avg') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('max')">{{ $t('chart.max') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('min')">{{ $t('chart.min') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('stddev_pop')">{{ $t('chart.stddev_pop') }}</el-dropdown-item>
<el-dropdown-item v-if="item.id !== 'count' && item.deType !== 0 && item.deType !== 1 && item.deType !== 5" :command="beforeSummary('var_pop')">{{ $t('chart.var_pop') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('count')">{{ $t('chart.count') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('count_distinct')">{{ $t('chart.count_distinct') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown-item>
@ -98,6 +99,9 @@
<el-dropdown-item icon="el-icon-files" :command="beforeClickItem('filter')">
<span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item>
<el-dropdown-item v-if="chart.render === 'antv' && chart.type.includes('table')" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<span>{{ $t('chart.value_formatter') }}...</span>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">
<span>{{ $t('chart.show_name_set') }}</span>
</el-dropdown-item>
@ -115,6 +119,7 @@ import { compareItem } from '@/views/chart/chart/compare'
import { getItemType } from '@/views/chart/components/drag-item/utils'
import FieldErrorTips from '@/views/chart/components/drag-item/components/FieldErrorTips'
import bus from '@/utils/bus'
import { formatterItem } from '@/views/chart/chart/formatter'
export default {
name: 'QuotaItem',
@ -149,7 +154,8 @@ export default {
return {
compareItem: compareItem,
disableEditCompare: false,
tagType: 'success'
tagType: 'success',
formatterItem: formatterItem
}
},
watch: {
@ -173,6 +179,9 @@ export default {
if (!this.item.compareCalc) {
this.item.compareCalc = JSON.parse(JSON.stringify(this.compareItem))
}
if (!this.item.formatterCfg) {
this.item.formatterCfg = JSON.parse(JSON.stringify(this.formatterItem))
}
},
isEnableCompare() {
let xAxis = null
@ -205,6 +214,9 @@ export default {
case 'filter':
this.editFilter()
break
case 'formatter':
this.valueFormatter()
break
default:
break
}
@ -289,6 +301,12 @@ export default {
},
getItemTagType() {
this.tagType = getItemType(this.dimensionData, this.quotaData, this.item)
},
valueFormatter() {
this.item.index = this.index
this.item.formatterType = 'quota'
this.$emit('valueFormatter', this.item)
}
}
}

View File

@ -136,7 +136,8 @@ export default {
const customAttr = JSON.parse(this.chart.customAttr)
if (customAttr.color) {
this.label_class.color = customAttr.color.dimensionColor
this.label_content_class.color = customAttr.color.quotaColor
// color threshold
this.colorThreshold(customAttr.color.quotaColor)
}
if (customAttr.size) {
this.dimensionShow = customAttr.size.dimensionShow
@ -168,6 +169,57 @@ export default {
chartResize() {
//
this.calcHeight()
},
colorThreshold(valueColor) {
if (this.chart.senior) {
const senior = JSON.parse(this.chart.senior)
if (senior.threshold && senior.threshold.labelThreshold && senior.threshold.labelThreshold.length > 0) {
const value = this.chart.data.series[0].data[0]
for (let i = 0; i < senior.threshold.labelThreshold.length; i++) {
let flag = false
const t = senior.threshold.labelThreshold[i]
if (t.term === 'eq') {
if (value === t.value) {
this.label_content_class.color = t.color
flag = true
}
} else if (t.term === 'not_eq') {
if (value !== t.value) {
this.label_content_class.color = t.color
flag = true
}
} else if (t.term === 'lt') {
if (value < t.value) {
this.label_content_class.color = t.color
flag = true
}
} else if (t.term === 'gt') {
if (value > t.value) {
this.label_content_class.color = t.color
flag = true
}
} else if (t.term === 'le') {
if (value <= t.value) {
this.label_content_class.color = t.color
flag = true
}
} else if (t.term === 'ge') {
if (value >= t.value) {
this.label_content_class.color = t.color
flag = true
}
}
if (flag) {
break
} else if (i === senior.threshold.labelThreshold.length - 1) {
this.label_content_class.color = valueColor
}
}
} else {
this.label_content_class.color = valueColor
}
}
}
}
}

View File

@ -1,10 +1,11 @@
<template>
<div style="width: 100%">
<!--仪表盘-->
<el-col v-if="chart.type && chart.type === 'gauge'">
<el-form ref="thresholdForm" :model="thresholdForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.threshold_range')+'(%)'" class="form-item">
<span>0,</span>
<el-input v-model="thresholdForm.gaugeThreshold" style="width: 100px;margin: 0 10px;" :placeholder="$t('chart.threshold_range')" size="mini" clearable @change="changeThreshold" />
<el-input v-model="thresholdForm.gaugeThreshold" style="width: 100px;margin: 0 10px;" :placeholder="$t('chart.threshold_range')" size="mini" clearable @change="gaugeThresholdChange" />
<span>,100</span>
<el-tooltip class="item" effect="dark" placement="bottom">
<div slot="content">
@ -17,14 +18,65 @@
</el-form-item>
</el-form>
</el-col>
<!--指标卡-->
<el-col v-if="chart.type && chart.type === 'text'">
<el-col>
<el-button
:title="$t('chart.edit')"
icon="el-icon-edit"
type="text"
size="small"
style="width: 24px;margin-left: 4px;"
@click="editLabelThreshold"
/>
<el-col style="padding: 0 18px;">
<el-row v-for="(item,index) in thresholdForm.labelThreshold" :key="index" class="line-style">
<el-col :span="8">
<span v-if="item.term === 'eq'" :title="$t('chart.filter_eq')">{{ $t('chart.filter_eq') }}</span>
<span v-else-if="item.term === 'not_eq'" :title="$t('chart.filter_not_eq')">{{ $t('chart.filter_not_eq') }}</span>
<span v-else-if="item.term === 'lt'" :title="$t('chart.filter_lt')">{{ $t('chart.filter_lt') }}</span>
<span v-else-if="item.term === 'gt'" :title="$t('chart.filter_gt')">{{ $t('chart.filter_gt') }}</span>
<span v-else-if="item.term === 'le'" :title="$t('chart.filter_le')">{{ $t('chart.filter_le') }}</span>
<span v-else-if="item.term === 'ge'" :title="$t('chart.filter_ge')">{{ $t('chart.filter_ge') }}</span>
</el-col>
<el-col :span="8">
<span :title="item.value">{{ item.value }}</span>
</el-col>
<el-col :span="8">
<span :style="{width:'14px', height:'14px', backgroundColor: item.color}" />
</el-col>
</el-row>
</el-col>
</el-col>
</el-col>
<!--编辑阈值-->
<el-dialog
v-if="editLabelThresholdDialog"
v-dialogDrag
:title="$t('chart.threshold')"
:visible="editLabelThresholdDialog"
:show-close="false"
width="50%"
class="dialog-css"
>
<text-threshold-edit :threshold="thresholdForm.labelThreshold" @onLabelThresholdChange="thresholdChange" />
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeLabelThreshold">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="changeLabelThreshold">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { DEFAULT_THRESHOLD } from '@/views/chart/chart/chart'
import TextThresholdEdit from '@/views/chart/components/senior/dialog/TextThresholdEdit'
export default {
name: 'Threshold',
components: { TextThresholdEdit },
props: {
chart: {
type: Object,
@ -33,7 +85,9 @@ export default {
},
data() {
return {
thresholdForm: JSON.parse(JSON.stringify(DEFAULT_THRESHOLD))
thresholdForm: JSON.parse(JSON.stringify(DEFAULT_THRESHOLD)),
editLabelThresholdDialog: false,
thresholdArr: []
}
},
watch: {
@ -58,12 +112,18 @@ export default {
}
if (senior.threshold) {
this.thresholdForm = senior.threshold
if (!this.thresholdForm.labelThreshold) {
this.thresholdForm.labelThreshold = []
}
} else {
this.thresholdForm = JSON.parse(JSON.stringify(DEFAULT_THRESHOLD))
}
}
},
changeThreshold() {
this.$emit('onThresholdChange', this.thresholdForm)
},
gaugeThresholdChange() {
// check input
if (this.thresholdForm.gaugeThreshold) {
const arr = this.thresholdForm.gaugeThreshold.split(',')
@ -79,7 +139,49 @@ export default {
}
}
}
this.$emit('onThresholdChange', this.thresholdForm)
this.changeThreshold()
},
editLabelThreshold() {
this.editLabelThresholdDialog = true
},
closeLabelThreshold() {
this.editLabelThresholdDialog = false
},
changeLabelThreshold() {
// check line config
for (let i = 0; i < this.thresholdArr.length; i++) {
const ele = this.thresholdArr[i]
if (!ele.term || ele.term === '') {
this.$message({
message: this.$t('chart.exp_can_not_empty'),
type: 'error',
showClose: true
})
return
}
if (!ele.value) {
this.$message({
message: this.$t('chart.value_can_not_empty'),
type: 'error',
showClose: true
})
return
}
if (parseFloat(ele.value).toString() === 'NaN') {
this.$message({
message: this.$t('chart.value_error'),
type: 'error',
showClose: true
})
return
}
}
this.thresholdForm.labelThreshold = JSON.parse(JSON.stringify(this.thresholdArr))
this.changeThreshold()
this.closeLabelThreshold()
},
thresholdChange(val) {
this.thresholdArr = val
}
}
}
@ -120,4 +222,25 @@ span{
cursor: pointer;
z-index: 1003;
}
.line-style >>> span{
display: inline-block;
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin: 0 10px;
}
.dialog-css >>> .el-dialog__title {
font-size: 14px;
}
.dialog-css >>> .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css >>> .el-dialog__body {
padding: 10px 20px 20px;
}
</style>

View File

@ -0,0 +1,162 @@
<template>
<el-col>
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addThreshold" />
<div style="max-height: 50vh;overflow-y: auto;">
<el-row v-for="(item,index) in thresholdArr" :key="index" class="line-item">
<el-col :span="6">
<el-select v-model="item.term" size="mini" @change="changeThreshold">
<el-option-group
v-for="(group,idx) in valueOptions"
:key="idx"
:label="group.label"
>
<el-option
v-for="opt in group.options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-option-group>
</el-select>
</el-col>
<el-col :span="10" style="text-align: center;">
<el-input v-model="item.value" class="value-item" :placeholder="$t('chart.drag_block_label_value')" size="mini" clearable @change="changeThreshold" />
</el-col>
<el-col :span="4" style="text-align: center;">
<el-color-picker v-model="item.color" show-alpha class="color-picker-style" :predefine="predefineColors" @change="changeThreshold" />
</el-col>
<el-col :span="4">
<el-button type="text" icon="el-icon-delete" circle style="float: right" @click="removeThreshold(index)" />
</el-col>
</el-row>
</div>
</el-col>
</template>
<script>
import { COLOR_PANEL } from '@/views/chart/chart/chart'
export default {
name: 'TextThresholdEdit',
props: {
threshold: {
type: Array,
required: true
}
},
data() {
return {
thresholdArr: [],
thresholdObj: {
term: 'eq',
value: '0',
color: '#ff0000ff'
},
valueOptions: [
{
label: '',
options: [{
value: 'eq',
label: this.$t('chart.filter_eq')
}, {
value: 'not_eq',
label: this.$t('chart.filter_not_eq')
}]
},
{
label: '',
options: [{
value: 'lt',
label: this.$t('chart.filter_lt')
}, {
value: 'gt',
label: this.$t('chart.filter_gt')
}]
},
{
label: '',
options: [{
value: 'le',
label: this.$t('chart.filter_le')
}, {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
}
],
predefineColors: COLOR_PANEL
}
},
mounted() {
this.init()
},
methods: {
init() {
this.thresholdArr = JSON.parse(JSON.stringify(this.threshold))
},
addThreshold() {
this.thresholdArr.push(JSON.parse(JSON.stringify(this.thresholdObj)))
this.changeThreshold()
},
removeThreshold(index) {
this.thresholdArr.splice(index, 1)
this.changeThreshold()
},
changeThreshold() {
this.$emit('onLabelThresholdChange', this.thresholdArr)
}
}
}
</script>
<style scoped>
.line-item {
width: 100%;
border-radius: 4px;
border: 1px solid #DCDFE6;
padding: 4px 14px;
margin-bottom: 10px;
display: flex;
justify-content: left;
align-items: center;
}
.form-item >>> .el-form-item__label {
font-size: 12px;
}
span {
font-size: 12px;
}
.value-item {
position: relative;
display: inline-block;
width: 200px !important;
}
.select-item {
position: relative;
display: inline-block;
width: 100px !important;
}
.el-select-dropdown__item {
padding: 0 20px;
font-size: 12px;
}
.color-picker-style{
cursor: pointer;
z-index: 1003;
width: 28px;
height: 28px;
margin-top: 6px;
}
.color-picker-style >>> .el-color-picker__trigger{
width: 28px;
height: 28px;
}
</style>

View File

@ -0,0 +1,87 @@
<template>
<div>
<el-form ref="form" :model="formatterItem.formatterCfg" label-width="80px" size="mini" class="formatter-form">
<el-form-item :label="$t('chart.value_formatter_type')">
<el-radio-group v-model="formatterItem.formatterCfg.type" @change="getExampleValue">
<el-radio v-for="radio in typeList" :key="radio.value" :label="radio.value">{{ $t('chart.' + radio.name) }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-show="formatterItem.formatterCfg.type !== 'auto'" :label="$t('chart.value_formatter_decimal_count')">
<el-input-number v-model="formatterItem.formatterCfg.decimalCount" :min="0" :max="10" size="mini" @change="getExampleValue" />
</el-form-item>
<el-form-item v-show="formatterItem.formatterCfg.type !== 'percent'" :label="$t('chart.value_formatter_unit')">
<el-select v-model="formatterItem.formatterCfg.unit" :placeholder="$t('chart.pls_select_field')" size="mini" @change="getExampleValue">
<el-option v-for="item in unitList" :key="item.value" :label="$t('chart.' + item.name)" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('chart.value_formatter_suffix')">
<el-input v-model="formatterItem.formatterCfg.suffix" size="mini" clearable :placeholder="$t('commons.input_content')" @change="getExampleValue" />
</el-form-item>
<el-form-item :label="$t('chart.value_formatter_thousand_separator')">
<el-checkbox v-model="formatterItem.formatterCfg.thousandSeparator" @change="getExampleValue" />
</el-form-item>
<el-form-item :label="$t('chart.value_formatter_example')">
<span>{{ exampleResult }}</span>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { formatterType, unitList, valueFormatter } from '@/views/chart/chart/formatter'
export default {
name: 'ValueFormatterEdit',
props: {
formatterItem: {
type: Object,
required: true
},
chart: {
type: Object,
required: true
}
},
data() {
return {
typeList: formatterType,
unitList: unitList,
exampleResult: '20000000'
}
},
mounted() {
this.getExampleValue()
},
methods: {
getExampleValue() {
this.exampleResult = valueFormatter(20000000, this.formatterItem.formatterCfg)
}
}
}
</script>
<style scoped>
.el-form-item{
margin-bottom: 10px!important;
}
.formatter-form >>> .el-form-item__label{
font-size: 12px!important;
font-weight: 400!important;
}
.formatter-form >>> .el-radio__label{
font-size: 12px!important;
font-weight: 400!important;
}
.el-select-dropdown__item >>> span{
font-size: 12px!important;
}
.exp-style{
color: #C0C4CC;
font-size: 12px;
}
</style>

View File

@ -366,10 +366,12 @@
:item="item"
:dimension-data="dimension"
:quota-data="quota"
:chart="chart"
@onDimensionItemChange="dimensionItemChange"
@onDimensionItemRemove="dimensionItemRemove"
@editItemFilter="showDimensionEditFilter"
@onNameEdit="showRename"
@valueFormatter="valueFormatter"
/>
</transition-group>
</draggable>
@ -445,6 +447,7 @@
@editItemFilter="showQuotaEditFilter"
@onNameEdit="showRename"
@editItemCompare="showQuotaEditCompare"
@valueFormatter="valueFormatter"
/>
</transition-group>
</draggable>
@ -893,7 +896,7 @@
<el-tab-pane :label="$t('chart.senior')" class="padding-tab" style="width: 300px;">
<el-row class="view-panel">
<div
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge'))"
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge')) || view.type === 'text'"
style="overflow:auto;border-right: 1px solid #e6e6e6;height: 100%;width: 100%;"
class="attr-style theme-border-class"
>
@ -913,7 +916,7 @@
</el-collapse>
</el-row>
<el-row
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge'))"
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge') || view.type === 'text')"
>
<span class="padding-lr">{{ $t('chart.analyse_cfg') }}</span>
<el-collapse v-model="styleActiveNames" class="style-collapse">
@ -930,7 +933,7 @@
/>
</el-collapse-item>
<el-collapse-item
v-if="view.type && (view.type.includes('gauge'))"
v-if="view.type && (view.type.includes('gauge') || view.type === 'text')"
name="threshold"
:title="$t('chart.threshold')"
>
@ -1116,6 +1119,7 @@
</div>
</el-dialog>
<!--同环比设置-->
<el-dialog
v-if="showEditQuotaCompare"
v-dialogDrag
@ -1131,6 +1135,23 @@
<el-button type="primary" size="mini" @click="saveQuotaEditCompare">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
<!--数值格式-->
<el-dialog
v-if="showValueFormatter"
v-dialogDrag
:title="$t('chart.value_formatter') + ' - ' + valueFormatterItem.name"
:visible="showValueFormatter"
:show-close="false"
width="600px"
class="dialog-css"
>
<value-formatter-edit :formatter-item="valueFormatterItem" :chart="chart" />
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeValueFormatter">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveValueFormatter">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</el-row>
</template>
@ -1213,9 +1234,11 @@ import Threshold from '@/views/chart/components/senior/Threshold'
import TotalCfg from '@/views/chart/components/shape-attr/TotalCfg'
import LabelNormalText from '@/views/chart/components/normal/LabelNormalText'
import { pluginTypes } from '@/api/chart/chart'
import ValueFormatterEdit from '@/views/chart/components/value-formatter/ValueFormatterEdit'
export default {
name: 'ChartEdit',
components: {
ValueFormatterEdit,
LabelNormalText,
TotalCfg,
Threshold,
@ -1367,7 +1390,8 @@ export default {
showEditQuotaCompare: false,
preChartId: '',
pluginRenderOptions: [],
showChartSet: true
showValueFormatter: false,
valueFormatterItem: {}
}
},
@ -2302,11 +2326,11 @@ export default {
},
addXaxisExt(e) {
if (this.view.type !== 'table-info') {
this.dragCheckType(this.view.xaxis, 'd')
this.dragCheckType(this.view.xaxisExt, 'd')
}
this.dragMoveDuplicate(this.view.xaxis, e)
if ((this.view.type === 'map' || this.view.type === 'word-cloud') && this.view.xaxis.length > 1) {
this.view.xaxis = [this.view.xaxis[0]]
this.dragMoveDuplicate(this.view.xaxisExt, e)
if ((this.view.type === 'map' || this.view.type === 'word-cloud') && this.view.xaxisExt.length > 1) {
this.view.xaxisExt = [this.view.xaxisExt[0]]
}
this.calcData(true)
},
@ -2573,6 +2597,33 @@ export default {
this.view.customAttr.label.position = 'middle'
}
}
},
valueFormatter(item) {
this.valueFormatterItem = JSON.parse(JSON.stringify(item))
this.showValueFormatter = true
},
closeValueFormatter() {
this.showValueFormatter = false
},
saveValueFormatter() {
const ele = this.valueFormatterItem.formatterCfg.decimalCount
if (ele === undefined || ele.toString().indexOf('.') > -1 || parseInt(ele).toString() === 'NaN' || parseInt(ele) < 0 || parseInt(ele) > 10) {
this.$message({
message: this.$t('chart.formatter_decimal_count_error'),
type: 'error',
showClose: true
})
return
}
//
if (this.valueFormatterItem.formatterType === 'quota') {
this.view.yaxis[this.valueFormatterItem.index].formatterCfg = this.valueFormatterItem.formatterCfg
} else if (this.valueFormatterItem.formatterType === 'quotaExt') {
this.view.yaxisExt[this.valueFormatterItem.index].formatterCfg = this.valueFormatterItem.formatterCfg
}
this.calcData(true)
this.closeValueFormatter()
}
}
}

View File

@ -23,7 +23,7 @@
</el-link> -->
</el-col>
</el-row>
<el-row style="display: flex;">
<el-row style="display: flex;border-bottom: 1px solid;border-bottom-color:#E6E6E6;">
<el-col style="text-overflow:ellipsis;overflow: hidden;white-space: nowrap;font-size: 14px; width: 90px;">
<span>{{ $t('panel.share_to') }}</span>
</el-col>

View File

@ -45,7 +45,7 @@
controls-position="right"
size="mini"
:min="1"
:max="12"
:max="100"
@change="dynamicPrefixChange"
/>
</el-form-item>

View File

@ -38,7 +38,7 @@
controls-position="right"
size="mini"
:min="0"
:max="10"
:max="100"
@change="sDynamicPrefixChange"
/>
</el-form-item>
@ -91,7 +91,7 @@
controls-position="right"
size="mini"
:min="0"
:max="10"
:max="100"
@change="eDynamicPrefixChange"
/>
</el-form-item>

View File

@ -69,6 +69,19 @@
<el-button type="primary" @click="save">{{ $t('commons.confirm') }}</el-button>
<el-button @click="reset">{{ $t('commons.reset') }}</el-button>
</el-form-item>
<el-form-item>
<!-- <el-link class="pwd-tips" type="danger" :underline="false">{{ $t('commons.default_pwd') + '' + defaultPWD }}</el-link> -->
<el-button class="pwd-tips" type="text">{{ $t('commons.default_pwd') + '' + defaultPWD }}</el-button>
<el-button
v-clipboard:copy="defaultPWD"
v-clipboard:success="onCopy"
v-clipboard:error="onError"
type="text"
>
{{ $t('commons.copy') }}
</el-button>
</el-form-item>
</el-form>
</layout-content>
@ -79,7 +92,7 @@ import LayoutContent from '@/components/business/LayoutContent'
import { PHONE_REGEX } from '@/utils/validate'
import { getDeptTree, treeByDeptId } from '@/api/system/dept'
import { addUser, editUser, allRoles } from '@/api/system/user'
import { pluginLoaded } from '@/api/user'
import { pluginLoaded, defaultPwd } from '@/api/user'
export default {
components: { LayoutContent },
@ -160,7 +173,8 @@ export default {
roleDatas: [],
userRoles: [],
formType: 'add',
isPluginLoaded: false
isPluginLoaded: false,
defaultPWD: 'DataEase123..'
}
},
@ -183,6 +197,11 @@ export default {
pluginLoaded().then(res => {
this.isPluginLoaded = res.success && res.data
})
defaultPwd().then(res => {
if (res && res.data) {
this.defaultPWD = res.data
}
})
},
methods: {
entryKey(event) {
@ -320,7 +339,15 @@ export default {
return node
})
this.depts = results
}
},
onCopy(e) {
this.$success(this.$t('commons.copy_success'))
},
onError(e) {}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,5 +1,13 @@
<template>
<el-row class="main_container">
<div
v-if="loading"
v-loading="loading"
style="position:absolute;top:55px;width: 100%;height: calc(100% - 55px);"
/>
<div v-else-if="homeLink">
<iframe id="mobsf" :src="homeLink" frameborder="0" style="position:absolute;top:55px;width: 100%;height: calc(100% - 55px);" />
</div>
<el-row v-else class="main_container">
<el-row class="head">
<span class="hint_head">{{ $t('wizard.welcome_title') }}</span> <br>
<span class="hint_content">{{ $t('wizard.welcome_hint') }}</span>
@ -73,9 +81,25 @@ export default {
href: 'https://www.dataease.io',
component: 'CardDetail'
}
]
],
loading: true
}
},
computed: {
homeLink() {
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.homeLink'] && this.$store.getters.uiInfo['ui.homeLink'].paramValue) {
return this.$store.getters.uiInfo['ui.homeLink'].paramValue
}
return null
}
},
mounted() {
setTimeout(() => {
this.loading = false
}, 1000)
},
created() {
this.init()
},

View File

@ -0,0 +1,95 @@
import bus from '@/utils/bus'
import SockJS from 'sockjs-client'
import Stomp from 'stompjs'
import store from '@/store'
class DeWebsocket {
constructor() {
this.ws_url = '/websocket'
this.client = null
this.channels = [
{
topic: '/web-msg-topic',
event: 'web-msg-topic-call'
}
]
this.timer = null
this.initialize()
}
initialize() {
this.connection()
const _this = this
this.timer = this.isLoginStatu() && setInterval(() => {
this.isLoginStatu() || this.destroy()
try {
_this.client && _this.client.send('heart detection')
} catch (error) {
console.log('Disconnection reconnection...')
_this.connection()
}
}, 5000)
}
destroy() {
this.timer && clearInterval(this.timer)
this.disconnect()
return true
}
reconnect() {
this.initialize()
}
isLoginStatu() {
return store.state && store.state.user && store.state.user.user && store.state.user.user.userId
}
connection() {
if (!this.isLoginStatu()) {
return
}
const socket = new SockJS(this.ws_url + '?userId=' + store.state.user.user.userId)
/* const socket = new SockJS('http://localhost:8081' + this.ws_url) */
this.client = Stomp.over(socket)
const heads = {
/* Authorization: '', */
userId: store.state.user.user.userId
}
this.client.connect(
heads,
res => {
// 连接成功 订阅所有主题
this.subscribe()
},
err => {
// 连接失败 打印错误信息
console.error(err)
}
).bind(this)
}
subscribe() {
this.channels.forEach(channel => {
this.client.subscribe('/user/' + store.state.user.user.userId + channel.topic, res => {
res && res.body && bus.$emit(channel.event, res.body)
})
})
}
disconnect() {
this.client && this.client.disconnect()
}
}
const result = new DeWebsocket()
export const getSocket = () => {
return result
}
export default {
install(Vue) {
// 使用$$前缀避免与Element UI的冲突
Vue.prototype.$deWebsocket = result
}
}

View File

@ -20,7 +20,7 @@ module.exports = {
proxy: {
'^(?!/login)': {
target: 'http://localhost:8081/',
ws: false
ws: true
}
},
open: true,