diff --git a/Dockerfile b/Dockerfile index 5f284057f1..a6ca401801 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,9 @@ FROM registry.cn-qingdao.aliyuncs.com/dataease/fabric8-java-alpine-openjdk8-jre:edge -RUN echo -e 'http://mirrors.aliyun.com/alpine/edge/main/\nhttp://mirrors.aliyun.com/alpine/edge/community/' > /etc/apk/repositories +RUN echo -e 'https://dl-cdn.alpinelinux.org/alpine/edge/main/\nhttps://dl-cdn.alpinelinux.org/alpine/edge/community/' > /etc/apk/repositories RUN apk add chromium chromium-chromedriver fontconfig --no-cache --allow-untrusted -RUN mkdir -p /usr/local/sbin/ \ - && cp /usr/bin/chromedriver /usr/local/sbin/ \ - && chmod a+x /usr/local/sbin/chromedriver - ADD simsun.ttc /usr/share/fonts/ RUN cd /usr/share/fonts/ \ diff --git a/backend/pom.xml b/backend/pom.xml index a5f0f7fcd5..b03cea2f01 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -5,7 +5,7 @@ dataease-server io.dataease - 1.7.0 + 1.8.0 4.0.0 @@ -214,7 +214,12 @@ io.dataease dataease-plugin-interface - 1.7 + 1.8.0 + + + io.dataease + dataease-plugin-view + 1.8.0 cn.hutool @@ -408,48 +413,74 @@ - - org.apache.maven.plugins - maven-antrun-plugin - - - - main-class-placement - generate-resources - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - + + + + whole + + whole + + + true + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + + main-class-placement + generate-resources + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + + + + stage + + stage + + + + + pentaho-public diff --git a/backend/src/main/java/io/dataease/auth/annotation/DeCleaner.java b/backend/src/main/java/io/dataease/auth/annotation/DeCleaner.java new file mode 100644 index 0000000000..40f9c57c26 --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/annotation/DeCleaner.java @@ -0,0 +1,14 @@ +package io.dataease.auth.annotation; + +import io.dataease.commons.constants.DePermissionType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DeCleaner { + DePermissionType value(); +} diff --git a/backend/src/main/java/io/dataease/auth/aop/DeCleanerAnnotationHandler.java b/backend/src/main/java/io/dataease/auth/aop/DeCleanerAnnotationHandler.java new file mode 100644 index 0000000000..276d43b1ca --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/aop/DeCleanerAnnotationHandler.java @@ -0,0 +1,74 @@ +package io.dataease.auth.aop; + + +import io.dataease.auth.annotation.DeCleaner; +import io.dataease.auth.api.dto.CurrentUserDto; +import io.dataease.commons.constants.AuthConstants; +import io.dataease.commons.constants.DePermissionType; +import io.dataease.commons.utils.AuthUtils; +import io.dataease.commons.utils.LogUtil; +import io.dataease.listener.util.CacheUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +@Aspect +@Component +public class DeCleanerAnnotationHandler { + + @Around(value = "@annotation(io.dataease.auth.annotation.DeCleaner)") + public Object CleanerAround(ProceedingJoinPoint point) { + try { + CurrentUserDto user = AuthUtils.getUser(); + MethodSignature ms = (MethodSignature) point.getSignature(); + Method method = ms.getMethod(); + DeCleaner deCleaner = method.getAnnotation(DeCleaner.class); + DePermissionType type = deCleaner.value(); + switch (type.name()) { + case "DATASOURCE": + cleanDataSource(); + break; + case "DATASET": + cleanDataSet(); + break; + default: + cleanPanel(); + break; + } + return point.proceed(point.getArgs()); + + }catch (Throwable e) { + LogUtil.error(e.getMessage(), e); + throw new RuntimeException(e); + } + } + + public void cleanPanel() { + CurrentUserDto user = AuthUtils.getUser(); + CacheUtils.remove(AuthConstants.USER_PANEL_NAME, "user" + user.getUserId()); + CacheUtils.remove(AuthConstants.DEPT_PANEL_NAME, "dept" + user.getDeptId()); + user.getRoles().forEach(role -> { + CacheUtils.remove(AuthConstants.ROLE_PANEL_NAME, "role" + role.getId()); + }); + } + public void cleanDataSet() { + CurrentUserDto user = AuthUtils.getUser(); + CacheUtils.remove(AuthConstants.USER_DATASET_NAME, "user" + user.getUserId()); + CacheUtils.remove(AuthConstants.DEPT_DATASET_NAME, "dept" + user.getDeptId()); + user.getRoles().forEach(role -> { + CacheUtils.remove(AuthConstants.ROLE_DATASET_NAME, "role" + role.getId()); + }); + } + public void cleanDataSource() { + CurrentUserDto user = AuthUtils.getUser(); + CacheUtils.remove(AuthConstants.USER_LINK_NAME, "user" + user.getUserId()); + CacheUtils.remove(AuthConstants.DEPT_LINK_NAME, "dept" + user.getDeptId()); + user.getRoles().forEach(role -> { + CacheUtils.remove(AuthConstants.ROLE_LINK_NAME, "role" + role.getId()); + }); + } +} diff --git a/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java b/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java index 5bc267b60d..5654a987b6 100644 --- a/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java +++ b/backend/src/main/java/io/dataease/auth/aop/DePermissionAnnotationHandler.java @@ -27,7 +27,11 @@ public class DePermissionAnnotationHandler { @Around(value = "@annotation(io.dataease.auth.annotation.DePermissions)") public Object PermissionsAround(ProceedingJoinPoint point) { + try { + if (AuthUtils.getUser().getIsAdmin()) { + return point.proceed(point.getArgs()); + } MethodSignature ms = (MethodSignature) point.getSignature(); Method method = ms.getMethod(); DePermissions annotation = method.getAnnotation(DePermissions.class); @@ -47,13 +51,13 @@ public class DePermissionAnnotationHandler { Boolean someAccess = false; for (int i = 0; i < dePermissions.length; i++) { DePermission permission = dePermissions[i]; - try{ + try { boolean currentAccess = access(args[permission.paramIndex()], permission, 0); if (currentAccess) { someAccess = true; break; } - }catch (Exception e) { + } catch (Exception e) { exceptions.add(e); } } @@ -71,6 +75,9 @@ public class DePermissionAnnotationHandler { @Around(value = "@annotation(io.dataease.auth.annotation.DePermission)") public Object PermissionAround(ProceedingJoinPoint point) { try { + if (AuthUtils.getUser().getIsAdmin()) { + return point.proceed(point.getArgs()); + } MethodSignature ms = (MethodSignature) point.getSignature(); Method method = ms.getMethod(); @@ -88,20 +95,22 @@ public class DePermissionAnnotationHandler { } private Boolean access(Object arg, DePermission annotation, int layer) throws Exception { - if (ObjectUtils.isEmpty(arg)) return true; + if (ObjectUtils.isEmpty(arg)) + return true; String type = annotation.type().name().toLowerCase(); String value = annotation.value(); Integer requireLevel = annotation.level().getLevel(); Set resourceIds = AuthUtils.permissionByType(type).stream().filter( - item -> item.getLevel() >= requireLevel - ).map(AuthItem::getAuthSource).collect(Collectors.toSet()); + item -> item.getLevel() >= requireLevel).map(AuthItem::getAuthSource).collect(Collectors.toSet()); Class parameterType = arg.getClass(); if (parameterType.isPrimitive() || isWrapClass(parameterType) || isString(parameterType)) { boolean permissionValid = resourceIds.contains(arg); - if (permissionValid) return true; - throw new UnauthorizedException("Subject does not have permission[" + annotation.level().name() +":"+ annotation.type() + ":" + arg + "]"); + if (permissionValid) + return true; + throw new UnauthorizedException("Subject does not have permission[" + annotation.level().name() + ":" + + annotation.type() + ":" + arg + "]"); } else if (isArray(parameterType)) { for (int i = 0; i < Array.getLength(arg); i++) { Object o = Array.get(arg, i); @@ -124,7 +133,7 @@ public class DePermissionAnnotationHandler { Object o = argMap.get(values[layer]); return access(o, annotation, ++layer); } else { - //当作自定义类处理 + // 当作自定义类处理 String[] values = value.split("u002E"); String fieldName = values[layer]; @@ -135,7 +144,7 @@ public class DePermissionAnnotationHandler { return true; } - private Object getFieldValue(Object o, String fieldName) throws Exception{ + private Object getFieldValue(Object o, String fieldName) throws Exception { Class aClass = o.getClass(); while (null != aClass.getSuperclass()) { Field[] declaredFields = aClass.getDeclaredFields(); @@ -183,5 +192,4 @@ public class DePermissionAnnotationHandler { return Arrays.stream(wrapClasies).anyMatch(item -> StringUtils.equals(item, clz.getName())); } - } diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java index f900cd4bc1..3828fbe35a 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java @@ -1,12 +1,15 @@ package io.dataease.auth.service.impl; +import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.auth.entity.AuthItem; import io.dataease.auth.service.ExtAuthService; import io.dataease.base.domain.SysAuth; import io.dataease.base.mapper.ext.ExtAuthMapper; import io.dataease.commons.constants.AuthConstants; import io.dataease.commons.model.AuthURD; +import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.LogUtil; +import io.dataease.listener.util.CacheUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -146,4 +149,7 @@ public class ExtAuthServiceImpl implements ExtAuthService { public void clearRoleResource(Long roleId) { LogUtil.info("all permission resource of role {} is cleanning...", roleId); } + + + } diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java index 8afa6e7281..01a9dd903b 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java @@ -45,6 +45,7 @@ public class ShiroServiceImpl implements ShiroService { // 获取主题信息 filterChainDefinitionMap.put("/plugin/theme/themes", ANON); filterChainDefinitionMap.put("/plugin/theme/items/**", ANON); + filterChainDefinitionMap.put("/plugin/view/types", ANON); // 验证链接 filterChainDefinitionMap.put("/api/link/validate**", ANON); diff --git a/backend/src/main/java/io/dataease/base/domain/ChartView.java b/backend/src/main/java/io/dataease/base/domain/ChartView.java index 69777d3f87..569746859c 100644 --- a/backend/src/main/java/io/dataease/base/domain/ChartView.java +++ b/backend/src/main/java/io/dataease/base/domain/ChartView.java @@ -1,38 +1,39 @@ package io.dataease.base.domain; import java.io.Serializable; - -import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class ChartView implements Serializable { - @ApiModelProperty("ID") private String id; - @ApiModelProperty("名称") + private String name; - @ApiModelProperty("分组ID") - private String sceneId; - @ApiModelProperty("数据集ID") - private String tableId; - @ApiModelProperty("图表类型") - private String type; - @ApiModelProperty("chart渲染方式") - private String render; - @ApiModelProperty("展示结果") - private Integer resultCount; - @ApiModelProperty("展示模式") - private String resultMode; - @ApiModelProperty("标题") + private String title; - @ApiModelProperty("创建人") + + private String sceneId; + + private String tableId; + + private String type; + + private String render; + + private Integer resultCount; + + private String resultMode; + private String createBy; - @ApiModelProperty("创建时间") + private Long createTime; - @ApiModelProperty("更新时间") + private Long updateTime; - @ApiModelProperty("样式优先级") + private String stylePriority; + private String chartType; + + private Boolean isPlugin; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/base/domain/ChartViewExample.java b/backend/src/main/java/io/dataease/base/domain/ChartViewExample.java index 9def62d21e..51a45711b1 100644 --- a/backend/src/main/java/io/dataease/base/domain/ChartViewExample.java +++ b/backend/src/main/java/io/dataease/base/domain/ChartViewExample.java @@ -244,6 +244,76 @@ public class ChartViewExample { return (Criteria) this; } + public Criteria andTitleIsNull() { + addCriterion("title is null"); + return (Criteria) this; + } + + public Criteria andTitleIsNotNull() { + addCriterion("title is not null"); + return (Criteria) this; + } + + public Criteria andTitleEqualTo(String value) { + addCriterion("title =", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleNotEqualTo(String value) { + addCriterion("title <>", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleGreaterThan(String value) { + addCriterion("title >", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleGreaterThanOrEqualTo(String value) { + addCriterion("title >=", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleLessThan(String value) { + addCriterion("title <", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleLessThanOrEqualTo(String value) { + addCriterion("title <=", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleLike(String value) { + addCriterion("title like", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleNotLike(String value) { + addCriterion("title not like", value, "title"); + return (Criteria) this; + } + + public Criteria andTitleIn(List values) { + addCriterion("title in", values, "title"); + return (Criteria) this; + } + + public Criteria andTitleNotIn(List values) { + addCriterion("title not in", values, "title"); + return (Criteria) this; + } + + public Criteria andTitleBetween(String value1, String value2) { + addCriterion("title between", value1, value2, "title"); + return (Criteria) this; + } + + public Criteria andTitleNotBetween(String value1, String value2) { + addCriterion("title not between", value1, value2, "title"); + return (Criteria) this; + } + public Criteria andSceneIdIsNull() { addCriterion("scene_id is null"); return (Criteria) this; @@ -654,76 +724,6 @@ public class ChartViewExample { return (Criteria) this; } - public Criteria andTitleIsNull() { - addCriterion("title is null"); - return (Criteria) this; - } - - public Criteria andTitleIsNotNull() { - addCriterion("title is not null"); - return (Criteria) this; - } - - public Criteria andTitleEqualTo(String value) { - addCriterion("title =", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleNotEqualTo(String value) { - addCriterion("title <>", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleGreaterThan(String value) { - addCriterion("title >", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleGreaterThanOrEqualTo(String value) { - addCriterion("title >=", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleLessThan(String value) { - addCriterion("title <", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleLessThanOrEqualTo(String value) { - addCriterion("title <=", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleLike(String value) { - addCriterion("title like", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleNotLike(String value) { - addCriterion("title not like", value, "title"); - return (Criteria) this; - } - - public Criteria andTitleIn(List values) { - addCriterion("title in", values, "title"); - return (Criteria) this; - } - - public Criteria andTitleNotIn(List values) { - addCriterion("title not in", values, "title"); - return (Criteria) this; - } - - public Criteria andTitleBetween(String value1, String value2) { - addCriterion("title between", value1, value2, "title"); - return (Criteria) this; - } - - public Criteria andTitleNotBetween(String value1, String value2) { - addCriterion("title not between", value1, value2, "title"); - return (Criteria) this; - } - public Criteria andCreateByIsNull() { addCriterion("create_by is null"); return (Criteria) this; @@ -983,6 +983,136 @@ public class ChartViewExample { addCriterion("style_priority not between", value1, value2, "stylePriority"); return (Criteria) this; } + + public Criteria andChartTypeIsNull() { + addCriterion("chart_type is null"); + return (Criteria) this; + } + + public Criteria andChartTypeIsNotNull() { + addCriterion("chart_type is not null"); + return (Criteria) this; + } + + public Criteria andChartTypeEqualTo(String value) { + addCriterion("chart_type =", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeNotEqualTo(String value) { + addCriterion("chart_type <>", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeGreaterThan(String value) { + addCriterion("chart_type >", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeGreaterThanOrEqualTo(String value) { + addCriterion("chart_type >=", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeLessThan(String value) { + addCriterion("chart_type <", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeLessThanOrEqualTo(String value) { + addCriterion("chart_type <=", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeLike(String value) { + addCriterion("chart_type like", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeNotLike(String value) { + addCriterion("chart_type not like", value, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeIn(List values) { + addCriterion("chart_type in", values, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeNotIn(List values) { + addCriterion("chart_type not in", values, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeBetween(String value1, String value2) { + addCriterion("chart_type between", value1, value2, "chartType"); + return (Criteria) this; + } + + public Criteria andChartTypeNotBetween(String value1, String value2) { + addCriterion("chart_type not between", value1, value2, "chartType"); + return (Criteria) this; + } + + public Criteria andIsPluginIsNull() { + addCriterion("is_plugin is null"); + return (Criteria) this; + } + + public Criteria andIsPluginIsNotNull() { + addCriterion("is_plugin is not null"); + return (Criteria) this; + } + + public Criteria andIsPluginEqualTo(Boolean value) { + addCriterion("is_plugin =", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginNotEqualTo(Boolean value) { + addCriterion("is_plugin <>", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginGreaterThan(Boolean value) { + addCriterion("is_plugin >", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginGreaterThanOrEqualTo(Boolean value) { + addCriterion("is_plugin >=", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginLessThan(Boolean value) { + addCriterion("is_plugin <", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginLessThanOrEqualTo(Boolean value) { + addCriterion("is_plugin <=", value, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginIn(List values) { + addCriterion("is_plugin in", values, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginNotIn(List values) { + addCriterion("is_plugin not in", values, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginBetween(Boolean value1, Boolean value2) { + addCriterion("is_plugin between", value1, value2, "isPlugin"); + return (Criteria) this; + } + + public Criteria andIsPluginNotBetween(Boolean value1, Boolean value2) { + addCriterion("is_plugin not between", value1, value2, "isPlugin"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/dataease/base/domain/ChartViewWithBLOBs.java b/backend/src/main/java/io/dataease/base/domain/ChartViewWithBLOBs.java index 61779e0cdd..d928332ac5 100644 --- a/backend/src/main/java/io/dataease/base/domain/ChartViewWithBLOBs.java +++ b/backend/src/main/java/io/dataease/base/domain/ChartViewWithBLOBs.java @@ -1,8 +1,6 @@ package io.dataease.base.domain; import java.io.Serializable; - -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -11,25 +9,26 @@ import lombok.ToString; @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ChartViewWithBLOBs extends ChartView implements Serializable { - @ApiModelProperty("x轴") private String xAxis; - @ApiModelProperty("y轴") + + private String xAxisExt; + private String yAxis; - @ApiModelProperty("副y轴") + private String yAxisExt; - @ApiModelProperty("堆叠") + private String extStack; - @ApiModelProperty("气泡") + private String extBubble; - @ApiModelProperty("图形属性") + private String customAttr; - @ApiModelProperty("组件样式") + private String customStyle; - @ApiModelProperty("过滤条件") + private String customFilter; - @ApiModelProperty("下钻字段") + private String drillFields; - @ApiModelProperty("快照") + private String snapshot; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/dataease/base/domain/PanelLinkMapping.java b/backend/src/main/java/io/dataease/base/domain/PanelLinkMapping.java index 7321d46342..0bb0bebfd3 100644 --- a/backend/src/main/java/io/dataease/base/domain/PanelLinkMapping.java +++ b/backend/src/main/java/io/dataease/base/domain/PanelLinkMapping.java @@ -11,5 +11,7 @@ public class PanelLinkMapping implements Serializable { private Long userId; + private String uuid; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/base/domain/PanelLinkMappingExample.java b/backend/src/main/java/io/dataease/base/domain/PanelLinkMappingExample.java index a4e98885dc..baa9094e73 100644 --- a/backend/src/main/java/io/dataease/base/domain/PanelLinkMappingExample.java +++ b/backend/src/main/java/io/dataease/base/domain/PanelLinkMappingExample.java @@ -293,6 +293,76 @@ public class PanelLinkMappingExample { addCriterion("user_id not between", value1, value2, "userId"); return (Criteria) this; } + + public Criteria andUuidIsNull() { + addCriterion("uuid is null"); + return (Criteria) this; + } + + public Criteria andUuidIsNotNull() { + addCriterion("uuid is not null"); + return (Criteria) this; + } + + public Criteria andUuidEqualTo(String value) { + addCriterion("uuid =", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidNotEqualTo(String value) { + addCriterion("uuid <>", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidGreaterThan(String value) { + addCriterion("uuid >", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidGreaterThanOrEqualTo(String value) { + addCriterion("uuid >=", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidLessThan(String value) { + addCriterion("uuid <", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidLessThanOrEqualTo(String value) { + addCriterion("uuid <=", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidLike(String value) { + addCriterion("uuid like", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidNotLike(String value) { + addCriterion("uuid not like", value, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidIn(List values) { + addCriterion("uuid in", values, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidNotIn(List values) { + addCriterion("uuid not in", values, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidBetween(String value1, String value2) { + addCriterion("uuid between", value1, value2, "uuid"); + return (Criteria) this; + } + + public Criteria andUuidNotBetween(String value1, String value2) { + addCriterion("uuid not between", value1, value2, "uuid"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/dataease/base/mapper/ChartViewMapper.xml b/backend/src/main/java/io/dataease/base/mapper/ChartViewMapper.xml index 1bdedbf438..d7e9404ad0 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ChartViewMapper.xml +++ b/backend/src/main/java/io/dataease/base/mapper/ChartViewMapper.xml @@ -4,20 +4,23 @@ + - + + + @@ -87,12 +90,12 @@ - id, `name`, scene_id, table_id, `type`, render, result_count, result_mode, title, - create_by, create_time, update_time, style_priority + id, `name`, title, scene_id, table_id, `type`, render, result_count, result_mode, + create_by, create_time, update_time, style_priority, chart_type, is_plugin - x_axis, y_axis, y_axis_ext, ext_stack, ext_bubble, custom_attr, custom_style, custom_filter, - drill_fields, snapshot + x_axis, x_axis_ext, y_axis, y_axis_ext, ext_stack, ext_bubble, custom_attr, custom_style, + custom_filter, drill_fields, snapshot select @@ -98,10 +99,10 @@ - insert into panel_link_mapping (id, resource_id, user_id - ) - values (#{id,jdbcType=BIGINT}, #{resourceId,jdbcType=VARCHAR}, #{userId,jdbcType=BIGINT} - ) + insert into panel_link_mapping (id, resource_id, user_id, + uuid) + values (#{id,jdbcType=BIGINT}, #{resourceId,jdbcType=VARCHAR}, #{userId,jdbcType=BIGINT}, + #{uuid,jdbcType=VARCHAR}) insert into panel_link_mapping @@ -115,6 +116,9 @@ user_id, + + uuid, + @@ -126,6 +130,9 @@ #{userId,jdbcType=BIGINT}, + + #{uuid,jdbcType=VARCHAR}, + - select distinct s.panel_group_id as id, IFNULL(s.granter,g.create_by) as creator, g.name + select distinct s.panel_group_id as id, u.nick_name as creator, g.name from panel_share s left join panel_group g on g.id = s.panel_group_id + left join sys_user u on u.username = IFNULL(s.granter,g.create_by) where ( s.target_id = #{userId} and s.type = 0 ) or ( s.target_id = #{deptId} and s.type = 2 ) or diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.java b/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.java index d74b1044e4..cb0fd05188 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.java +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.java @@ -8,6 +8,9 @@ import java.util.List; public interface ExtVAuthModelMapper { - List queryAuthModel (@Param("record") VAuthModelRequest record); + List queryAuthModel(@Param("record") VAuthModelRequest record); + List queryAuthModelViews (@Param("record") VAuthModelRequest record); + + List queryAuthViewsOriginal (@Param("record") VAuthModelRequest record); } diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.xml b/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.xml index 912b404ae0..133ca26079 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.xml +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtVAuthModelMapper.xml @@ -4,106 +4,176 @@ + + SELECT + v_auth_model.id, + v_auth_model.name, + v_auth_model.label, + v_auth_model.pid, + v_auth_model.node_type, + v_auth_model.model_type, + v_auth_model.model_inner_type, + v_auth_model.auth_type, + v_auth_model.create_by, + v_auth_model.level, + v_auth_model.mode, + v_auth_model.data_source_id, + authInfo.PRIVILEGES AS `privileges` + FROM + ( SELECT GET_V_AUTH_MODEL_ID_P_USE ( #{record.userId}, #{record.modelType} ) cids ) t, + v_auth_model + LEFT JOIN ( + SELECT + auth_source, + group_concat( DISTINCT sys_auth_detail.privilege_extend ) AS `privileges` + FROM + ( + `sys_auth` + LEFT JOIN `sys_auth_detail` ON (( + `sys_auth`.`id` = `sys_auth_detail`.`auth_id` + ))) + WHERE + sys_auth_detail.privilege_value = 1 + AND sys_auth.auth_source_type = #{record.modelType} + AND ( + ( + sys_auth.auth_target_type = 'dept' + AND sys_auth.auth_target IN ( SELECT dept_id FROM sys_user WHERE user_id = #{record.userId} ) + ) + OR ( + sys_auth.auth_target_type = 'user' + AND sys_auth.auth_target = #{record.userId} + ) + OR ( + sys_auth.auth_target_type = 'role' + AND sys_auth.auth_target IN ( SELECT role_id FROM sys_users_roles WHERE user_id = #{record.userId} ) + ) + ) + GROUP BY + `sys_auth`.`auth_source` + ) authInfo ON v_auth_model.id = authInfo.auth_source + WHERE + FIND_IN_SET( v_auth_model.id, cids ) + + and v_auth_model.id = #{record.id,jdbcType=VARCHAR} + + + and v_auth_model.pid = #{record.pid,jdbcType=VARCHAR} + + + and v_auth_model.node_type = #{record.nodeType,jdbcType=VARCHAR} + + + and v_auth_model.model_type = #{record.modelType,jdbcType=VARCHAR} + + + and v_auth_model.model_inner_type = #{record.modelInnerType,jdbcType=VARCHAR} + + + and v_auth_model.auth_type = #{record.authType,jdbcType=VARCHAR} + + + and v_auth_model.create_by = #{record.createBy,jdbcType=VARCHAR} + + + and v_auth_model.`level` = #{record.level,jdbcType=BIGINT} + + + + and v_auth_model.`mode` = 0 + + + and (v_auth_model.`mode` = 1 or (v_auth_model.`model_inner_type` = 'group' and v_auth_model.model_type = + 'dataset')) + + + + and v_auth_model.data_source_id = #{record.dataSourceId,jdbcType=VARCHAR} + + + and v_auth_model.`name` = #{record.name,jdbcType=LONGVARCHAR} + + + and v_auth_model.`label` = #{record.label,jdbcType=LONGVARCHAR} + + + and v_auth_model.model_inner_type in + + #{item} + + + ORDER BY v_auth_model.node_type desc, CONVERT(v_auth_model.label using gbk) asc + + + + + + diff --git a/backend/src/main/java/io/dataease/commons/utils/AuthUtils.java b/backend/src/main/java/io/dataease/commons/utils/AuthUtils.java index 5fc77ab5cf..30a7f3a2df 100644 --- a/backend/src/main/java/io/dataease/commons/utils/AuthUtils.java +++ b/backend/src/main/java/io/dataease/commons/utils/AuthUtils.java @@ -4,6 +4,7 @@ import io.dataease.auth.api.dto.CurrentRoleDto; import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.auth.entity.AuthItem; import io.dataease.auth.service.ExtAuthService; +import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.commons.model.AuthURD; import org.apache.commons.lang3.StringUtils; @@ -56,7 +57,7 @@ public class AuthUtils { Long deptId = user.getDeptId(); List roles = user.getRoles(); Set result = new HashSet<>(); - if (StringUtils.equals("link", type)) { + if (StringUtils.equals(DePermissionType.DATASOURCE.name().toLowerCase(), type)) { Set userSet = extAuthService.dataSourceIdByUser(userId).stream().collect(Collectors.toSet()); Set roleSet = roles.stream().map(role -> extAuthService.dataSourceIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet()); Set deptSet = extAuthService.dataSourceIdByDept(deptId).stream().collect(Collectors.toSet()); @@ -69,7 +70,7 @@ public class AuthUtils { return result; } - else if (StringUtils.equals("dataset", type)) { + else if (StringUtils.equals(DePermissionType.DATASET.name().toLowerCase(), type)) { Set userSet = extAuthService.dataSetIdByUser(userId).stream().collect(Collectors.toSet()); Set roleSet = roles.stream().map(role -> extAuthService.dataSetIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet()); Set deptSet = extAuthService.dataSetIdByDept(deptId).stream().collect(Collectors.toSet()); @@ -81,7 +82,7 @@ public class AuthUtils { }); return result; } - else if (StringUtils.equals("panel", type)) { + else if (StringUtils.equals(DePermissionType.PANEL.name().toLowerCase(), type)) { Set userSet = extAuthService.panelIdByUser(userId).stream().collect(Collectors.toSet()); Set roleSet = roles.stream().map(role -> extAuthService.panelIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet()); Set deptSet = extAuthService.panelIdByDept(deptId).stream().collect(Collectors.toSet()); diff --git a/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java b/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java index ca256b47b7..ec283b549b 100644 --- a/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java +++ b/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java @@ -7,6 +7,7 @@ import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.MessageDigest; +import java.util.UUID; /** * 加密解密工具 @@ -19,6 +20,13 @@ public class CodingUtil { private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", + "W", "X", "Y", "Z" }; /** * MD5加密 * @@ -165,4 +173,26 @@ public class CodingUtil { } } + + public static boolean isNumeric(String str){ + for (int i = str.length();--i>=0;){ + if (!Character.isDigit(str.charAt(i))){ + return false; + } + } + return true; + } + + + + public static String shortUuid() { + StringBuffer shortBuffer = new StringBuffer(); + String uuid = UUID.randomUUID().toString().replace("-", ""); + for (int i = 0; i < 8; i++) { + String str = uuid.substring(i * 4, i * 4 + 4); + int x = Integer.parseInt(str, 16); + shortBuffer.append(chars[x % 0x3E]); + } + return shortBuffer.toString(); + } } diff --git a/backend/src/main/java/io/dataease/commons/utils/TreeUtils.java b/backend/src/main/java/io/dataease/commons/utils/TreeUtils.java index 13796111b9..d5cf0d96b3 100644 --- a/backend/src/main/java/io/dataease/commons/utils/TreeUtils.java +++ b/backend/src/main/java/io/dataease/commons/utils/TreeUtils.java @@ -2,6 +2,7 @@ package io.dataease.commons.utils; import io.dataease.commons.model.ITreeBase; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import java.util.*; import java.util.stream.Collectors; @@ -18,6 +19,9 @@ public class TreeUtils{ */ public static List mergeTree(List tree,String ... rootPid) { Assert.notNull(rootPid, "Root Pid cannot be null"); + if(CollectionUtils.isEmpty(tree)){ + return null; + } List result = new ArrayList<>(); // 构建id-节点map映射 Map treePidMap = tree.stream().collect(Collectors.toMap(T::getId, t -> t)); diff --git a/backend/src/main/java/io/dataease/controller/IndexController.java b/backend/src/main/java/io/dataease/controller/IndexController.java index e9d77d1056..bf8ad7eca0 100644 --- a/backend/src/main/java/io/dataease/controller/IndexController.java +++ b/backend/src/main/java/io/dataease/controller/IndexController.java @@ -3,6 +3,7 @@ package io.dataease.controller; import io.dataease.commons.exception.DEException; import io.dataease.commons.license.DefaultLicenseService; import io.dataease.commons.license.F2CLicenseResponse; +import io.dataease.commons.utils.CodingUtil; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; import io.dataease.service.panel.PanelLinkService; @@ -48,8 +49,13 @@ public class IndexController { } @GetMapping("/link/{index}") - public void link(@PathVariable(value = "index", required = true) Long index) { - String url = panelLinkService.getUrlByIndex(index); + public void link(@PathVariable(value = "index", required = true) String index) { + String url; + if (CodingUtil.isNumeric(index)) { + url = panelLinkService.getUrlByIndex(Long.parseLong(index)); + } else { + url = panelLinkService.getUrlByUuid(index); + } HttpServletResponse response = ServletUtils.response(); try { response.sendRedirect(url); diff --git a/backend/src/main/java/io/dataease/controller/chart/ChartViewController.java b/backend/src/main/java/io/dataease/controller/chart/ChartViewController.java index 714edd2007..d55cf8be57 100644 --- a/backend/src/main/java/io/dataease/controller/chart/ChartViewController.java +++ b/backend/src/main/java/io/dataease/controller/chart/ChartViewController.java @@ -72,9 +72,9 @@ public class ChartViewController { } @ApiOperation("复制") - @PostMapping("chartCopy/{id}") - public String chartCopy(@PathVariable String id) { - return chartViewService.chartCopy(id); + @PostMapping("chartCopy/{id}/{panelId}") + public String chartCopy(@PathVariable String id, @PathVariable String panelId) { + return chartViewService.chartCopy(id,panelId); } @ApiIgnore diff --git a/backend/src/main/java/io/dataease/controller/dataset/DataSetGroupController.java b/backend/src/main/java/io/dataease/controller/dataset/DataSetGroupController.java index 0a52e11796..f4cdcff78b 100644 --- a/backend/src/main/java/io/dataease/controller/dataset/DataSetGroupController.java +++ b/backend/src/main/java/io/dataease/controller/dataset/DataSetGroupController.java @@ -1,13 +1,19 @@ package io.dataease.controller.dataset; import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.auth.annotation.DePermission; +import io.dataease.auth.annotation.DePermissions; import io.dataease.base.domain.DatasetGroup; +import io.dataease.commons.constants.DePermissionType; +import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.controller.request.dataset.DataSetGroupRequest; import io.dataease.dto.dataset.DataSetGroupDTO; import io.dataease.service.dataset.DataSetGroupService; import io.dataease.service.dataset.ExtractDataService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; @@ -28,12 +34,18 @@ public class DataSetGroupController { @Resource private ExtractDataService extractDataService; + @RequiresPermissions("data:read") + @DePermissions(value = { + @DePermission(type = DePermissionType.DATASET, value = "id"), + @DePermission(type = DePermissionType.DATASET, value = "pid", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE) + }, logical = Logical.AND) @ApiOperation("保存") @PostMapping("/save") public DataSetGroupDTO save(@RequestBody DatasetGroup datasetGroup) { return dataSetGroupService.save(datasetGroup); } + @RequiresPermissions("data:read") @ApiOperation("查询树") @PostMapping("/tree") public List tree(@RequestBody DataSetGroupRequest datasetGroup) { @@ -46,6 +58,8 @@ public class DataSetGroupController { return dataSetGroupService.treeNode(datasetGroup); } + @RequiresPermissions("data:read") + @DePermission(type = DePermissionType.DATASET, level = ResourceAuthLevel.DATASET_LEVEL_MANAGE) @ApiOperation("删除") @PostMapping("/delete/{id}") public void tree(@PathVariable String id) throws Exception { diff --git a/backend/src/main/java/io/dataease/controller/dataset/DataSetTableController.java b/backend/src/main/java/io/dataease/controller/dataset/DataSetTableController.java index 1fd35a4c09..fc1b99c337 100644 --- a/backend/src/main/java/io/dataease/controller/dataset/DataSetTableController.java +++ b/backend/src/main/java/io/dataease/controller/dataset/DataSetTableController.java @@ -1,9 +1,13 @@ package io.dataease.controller.dataset; import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.auth.annotation.DePermission; +import io.dataease.auth.annotation.DePermissions; import io.dataease.base.domain.DatasetTable; import io.dataease.base.domain.DatasetTableField; import io.dataease.base.domain.DatasetTableIncrementalConfig; +import io.dataease.commons.constants.DePermissionType; +import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.controller.request.dataset.DataSetTableRequest; import io.dataease.controller.response.DataSetDetail; import io.dataease.dto.datasource.TableField; @@ -11,6 +15,8 @@ import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.dto.dataset.ExcelFileData; import io.dataease.service.dataset.DataSetTableService; import io.swagger.annotations.*; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -30,12 +36,24 @@ public class DataSetTableController { @Resource private DataSetTableService dataSetTableService; + @RequiresPermissions("data:read") + @DePermissions(value = { + @DePermission(type = DePermissionType.DATASET, value = "id"), + @DePermission(type = DePermissionType.DATASET, value = "sceneId", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE), + @DePermission(type = DePermissionType.DATASOURCE, value = "dataSourceId", level = ResourceAuthLevel.DATASET_LEVEL_USE) + }, logical = Logical.AND) @ApiOperation("批量保存") @PostMapping("batchAdd") public void batchAdd(@RequestBody List datasetTable) throws Exception { dataSetTableService.batchInsert(datasetTable); } + @RequiresPermissions("data:read") + @DePermissions(value = { + @DePermission(type = DePermissionType.DATASET, value = "id", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE), + @DePermission(type = DePermissionType.DATASET, value = "sceneId", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE), + @DePermission(type = DePermissionType.DATASOURCE, value = "dataSourceId", level = ResourceAuthLevel.DATASET_LEVEL_USE) + }, logical = Logical.AND) @ApiOperation("更新") @PostMapping("update") public void save(@RequestBody DataSetTableRequest datasetTable) throws Exception { @@ -46,12 +64,19 @@ public class DataSetTableController { } } + @RequiresPermissions("data:read") + @DePermissions(value = { + @DePermission(type = DePermissionType.DATASET, value = "id", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE), + @DePermission(type = DePermissionType.DATASET, value = "sceneId", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE), + @DePermission(type = DePermissionType.DATASOURCE, value = "dataSourceId", level = ResourceAuthLevel.DATASET_LEVEL_USE) + }, logical = Logical.AND) @ApiOperation("修改") @PostMapping("alter") public void alter(@RequestBody DataSetTableRequest request) throws Exception { dataSetTableService.alter(request); } + @DePermission(type = DePermissionType.DATASET, level = ResourceAuthLevel.DATASET_LEVEL_MANAGE) @ApiOperation("删除") @PostMapping("delete/{id}") public void delete(@ApiParam(name = "id", value = "数据集ID", required = true) @PathVariable String id) throws Exception { @@ -70,6 +95,7 @@ public class DataSetTableController { return dataSetTableService.listAndGroup(dataSetTableRequest); } + @DePermission(type = DePermissionType.DATASET, level = ResourceAuthLevel.DATASET_LEVEL_USE) @ApiOperation("详息") @PostMapping("get/{id}") public DatasetTable get(@ApiParam(name = "id", value = "数据集ID", required = true) @PathVariable String id) { diff --git a/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java b/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java index 4d3601e7f3..b6b1218c01 100644 --- a/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java +++ b/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java @@ -3,7 +3,11 @@ package io.dataease.controller.datasource; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.auth.annotation.DePermission; +import io.dataease.auth.annotation.DePermissions; import io.dataease.base.domain.Datasource; +import io.dataease.commons.constants.DePermissionType; +import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.PageUtils; import io.dataease.commons.utils.Pager; @@ -16,6 +20,8 @@ import io.dataease.service.datasource.DatasourceService; import io.dataease.dto.DatasourceDTO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; @@ -32,18 +38,24 @@ public class DatasourceController { @Resource private DatasourceService datasourceService; + @RequiresPermissions("datasource:add") + @DePermission(type = DePermissionType.DATASOURCE, value = "id") @ApiOperation("新增数据源") @PostMapping("/add") public Datasource addDatasource(@RequestBody Datasource datasource) throws Exception{ return datasourceService.addDatasource(datasource); } + @RequiresPermissions("datasource:read") + @DePermission(type = DePermissionType.DATASOURCE, value = "id") @ApiOperation("验证数据源") @PostMapping("/validate") public ResultHolder validate(@RequestBody Datasource datasource) throws Exception { return datasourceService.validate(datasource); } + @RequiresPermissions("datasource:read") + @DePermission(type = DePermissionType.DATASOURCE) @ApiOperation("验证数据源") @GetMapping("/validate/{datasourceId}") public ResultHolder validate(@PathVariable String datasourceId) { @@ -65,6 +77,7 @@ public class DatasourceController { return getDatasourceList().stream().filter(datasourceDTO -> datasourceDTO.getType().equalsIgnoreCase(type)).collect(Collectors.toList()); } + @RequiresPermissions("datasource:read") @ApiIgnore @PostMapping("/list/{goPage}/{pageSize}") public Pager> getDatasourceList(@RequestBody BaseGridRequest request, @PathVariable int goPage, @PathVariable int pageSize) throws Exception { @@ -72,12 +85,15 @@ public class DatasourceController { return PageUtils.setPageInfo(page, datasourceService.gridQuery(request)); } + @DePermission(type = DePermissionType.DATASOURCE, level = ResourceAuthLevel.LINK_LEVEL_MANAGE) @ApiOperation("删除数据源") @PostMapping("/delete/{datasourceID}") public void deleteDatasource(@PathVariable(value = "datasourceID") String datasourceID) throws Exception { datasourceService.deleteDatasource(datasourceID); } + @RequiresPermissions("datasource:add") + @DePermission(type = DePermissionType.DATASOURCE, value = "id", level = ResourceAuthLevel.LINK_LEVEL_MANAGE) @ApiOperation("更新数据源") @PostMapping("/update") public void updateDatasource(@RequestBody Datasource Datasource) { diff --git a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java index 62383c6c02..e059975190 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java @@ -9,6 +9,7 @@ import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.controller.handler.annotation.I18n; import io.dataease.controller.request.panel.PanelGroupRequest; +import io.dataease.dto.authModel.VAuthModelDTO; import io.dataease.dto.panel.PanelGroupDTO; import io.dataease.service.panel.PanelGroupService; import io.swagger.annotations.Api; @@ -70,5 +71,11 @@ public class PanelGroupController { return panelGroupService.findOne(id); } + @ApiOperation("仪表板视图信息") + @PostMapping("/queryPanelViewTree") + @I18n + public List queryPanelViewTree(){ + return panelGroupService.queryPanelViewTree(); + } } diff --git a/backend/src/main/java/io/dataease/controller/request/authModel/VAuthModelRequest.java b/backend/src/main/java/io/dataease/controller/request/authModel/VAuthModelRequest.java index 223859b936..5ec7201638 100644 --- a/backend/src/main/java/io/dataease/controller/request/authModel/VAuthModelRequest.java +++ b/backend/src/main/java/io/dataease/controller/request/authModel/VAuthModelRequest.java @@ -14,9 +14,15 @@ import java.util.List; public class VAuthModelRequest extends VAuthModelDTO { private String userId; + private String privileges; + private Integer datasetMode; + private boolean clearEmptyDir; + private List modelInnerTypeArray; + private List pids; + } diff --git a/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java b/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java index 00adf25aa8..e3751a563c 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SystemParameterController.java @@ -11,6 +11,7 @@ import io.dataease.service.FileService; import io.dataease.service.system.EmailService; import io.dataease.service.system.SystemParameterService; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -39,11 +40,13 @@ public class SystemParameterController { private EmailService emailService; + @RequiresPermissions("sysparam:read") @GetMapping("/mail/info") public MailInfo mailInfo() { return emailService.mailInfo(); } + @RequiresPermissions("sysparam:read") @GetMapping("/basic/info") public BasicInfo basicInfo() { return systemParameterService.basicInfo(); @@ -55,11 +58,13 @@ public class SystemParameterController { return StringUtils.isNotBlank(basicInfo.getFrontTimeOut()) ? Integer.parseInt(basicInfo.getFrontTimeOut()) : 10; } + @RequiresPermissions("sysparam:read") @PostMapping("/edit/email") public void editMail(@RequestBody List systemParameter) { emailService.editMail(systemParameter); } + @RequiresPermissions("sysparam:read") @PostMapping("/edit/basic") public void editBasic(@RequestBody List systemParameter) { systemParameterService.editBasic(systemParameter); @@ -76,6 +81,7 @@ public class SystemParameterController { } + @RequiresPermissions("sysparam:read") @GetMapping("/base/info") public List getBaseInfo() { return systemParameterService.getSystemParameterInfo(ParamConstants.Classify.BASE.getValue()); diff --git a/backend/src/main/java/io/dataease/dto/authModel/VAuthModelDTO.java b/backend/src/main/java/io/dataease/dto/authModel/VAuthModelDTO.java index a3ce5a3978..fd1ddc516c 100644 --- a/backend/src/main/java/io/dataease/dto/authModel/VAuthModelDTO.java +++ b/backend/src/main/java/io/dataease/dto/authModel/VAuthModelDTO.java @@ -17,5 +17,13 @@ public class VAuthModelDTO extends VAuthModelWithBLOBs implements ITreeBase children; + private long allLeafs = 0l; + + private String innerId; + + public String toString(){ + return this.getName(); + } + } diff --git a/backend/src/main/java/io/dataease/plugins/server/ThemeServer.java b/backend/src/main/java/io/dataease/plugins/server/ThemeServer.java index 5e1ee1769d..df49eba490 100644 --- a/backend/src/main/java/io/dataease/plugins/server/ThemeServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/ThemeServer.java @@ -3,6 +3,7 @@ package io.dataease.plugins.server; import java.util.List; import org.apache.commons.lang3.ObjectUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -36,6 +37,7 @@ public class ThemeServer { return themeXpackService.queryItems(themeId); } + @RequiresPermissions("sysparam:read") @PostMapping("/save") public void save(@RequestPart("request") ThemeRequest request, @RequestPart(value = "file", required = false) MultipartFile bodyFile) { @@ -55,6 +57,7 @@ public class ThemeServer { } + @RequiresPermissions("sysparam:read") @PostMapping("/delete/{themeId}") public void delete(@PathVariable("themeId") int themeId) { ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XAuthServer.java b/backend/src/main/java/io/dataease/plugins/server/XAuthServer.java index 012939cda2..2aec82d079 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XAuthServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XAuthServer.java @@ -14,6 +14,7 @@ import io.dataease.plugins.xpack.auth.dto.response.XpackSysAuthDetailDTO; import io.dataease.plugins.xpack.auth.dto.response.XpackVAuthModelDTO; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import io.dataease.plugins.xpack.auth.service.AuthXpackService; @@ -25,37 +26,41 @@ public class XAuthServer { private static final Set cacheTypes = new HashSet<>(); + @RequiresPermissions("auth:read") @PostMapping("/authModels") @I18n - public List authModels(@RequestBody XpackBaseTreeRequest request){ + public List authModels(@RequestBody XpackBaseTreeRequest request) { AuthXpackService sysAuthService = SpringContextUtil.getBean(AuthXpackService.class); CurrentUserDto user = AuthUtils.getUser(); return sysAuthService.searchAuthModelTree(request, user.getUserId(), user.getIsAdmin()); } + @RequiresPermissions("auth:read") @PostMapping("/authDetails") - public Map> authDetails(@RequestBody XpackSysAuthRequest request){ + public Map> authDetails(@RequestBody XpackSysAuthRequest request) { AuthXpackService sysAuthService = SpringContextUtil.getBean(AuthXpackService.class); return sysAuthService.searchAuthDetails(request); } - @GetMapping("/authDetailsModel/{authType}") + @RequiresPermissions("auth:read") + @GetMapping("/authDetailsModel/{authType}/{direction}") @I18n - public ListauthDetailsModel(@PathVariable String authType){ + public List authDetailsModel(@PathVariable String authType, @PathVariable String direction) { AuthXpackService sysAuthService = SpringContextUtil.getBean(AuthXpackService.class); - List authDetails = sysAuthService.searchAuthDetailsModel(authType); - if(authType.equalsIgnoreCase("dataset")){ + List authDetails = sysAuthService.searchAuthDetailsModel(authType); + if (authType.equalsIgnoreCase("dataset")) { XpackSysAuthDetail xpackSysAuthDetail = new XpackSysAuthDetail(); xpackSysAuthDetail.setPrivilegeName("i18n_auth_row_permission"); xpackSysAuthDetail.setPrivilegeType(20); xpackSysAuthDetail.setPrivilegeValue(1); - authDetails.add(0,xpackSysAuthDetail); + authDetails.add(0, xpackSysAuthDetail); } return authDetails; } + @RequiresPermissions("auth:read") @PostMapping("/authChange") - public void authChange(@RequestBody XpackSysAuthRequest request){ + public void authChange(@RequestBody XpackSysAuthRequest request) { AuthXpackService sysAuthService = SpringContextUtil.getBean(AuthXpackService.class); CurrentUserDto user = AuthUtils.getUser(); sysAuthService.authChange(request, user.getUserId(), user.getUsername(), user.getIsAdmin()); diff --git a/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java b/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java index 76dc14c8eb..0c3b911405 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java @@ -14,6 +14,7 @@ import io.dataease.plugins.xpack.dept.dto.response.XpackSysDept; import io.dataease.plugins.xpack.dept.service.DeptXpackService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; @@ -66,6 +67,7 @@ public class XDeptServer { return nodes; } + @RequiresPermissions("dept:add") @ApiOperation("创建") @PostMapping("/create") public int create(@RequestBody XpackCreateDept dept){ @@ -73,6 +75,7 @@ public class XDeptServer { return deptService.add(dept); } + @RequiresPermissions("dept:del") @ApiOperation("删除") @PostMapping("/delete") public void delete(@RequestBody List requests){ @@ -83,6 +86,7 @@ public class XDeptServer { deptService.batchDelete(requests); } + @RequiresPermissions("dept:edit") @ApiOperation("更新") @PostMapping("/update") public int update(@RequestBody XpackCreateDept dept){ @@ -91,6 +95,7 @@ public class XDeptServer { } + @RequiresPermissions("dept:del") @ApiIgnore @ApiOperation("删除") @PostMapping("/nodesByDeptId/{deptId}") diff --git a/backend/src/main/java/io/dataease/plugins/server/XDisplayServer.java b/backend/src/main/java/io/dataease/plugins/server/XDisplayServer.java index 36e26fc1bb..b689183768 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XDisplayServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XDisplayServer.java @@ -4,6 +4,7 @@ package io.dataease.plugins.server; import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.display.dto.response.SysSettingDto; import io.dataease.plugins.xpack.display.service.DisplayXpackService; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -22,6 +23,7 @@ public class XDisplayServer { return disPlayXpackService.systemSettings(); } + @RequiresPermissions("sysparam:read") @PostMapping(value="/save", consumes = {"multipart/form-data"}) public void saveUIInfo(@RequestPart("request") Map> systemParameterMap, @RequestPart(value = "files", required = false) List bodyFiles) throws Exception { DisplayXpackService disPlayXpackService = SpringContextUtil.getBean(DisplayXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java index 31595ae413..317fe48079 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java @@ -20,6 +20,7 @@ import io.dataease.service.ScheduleService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -39,6 +40,7 @@ public class XEmailTaskServer { @Resource private PriorityThreadPoolExecutor priorityExecutor; + @RequiresPermissions("task-email:read") @PostMapping("/queryTasks/{goPage}/{pageSize}") public Pager> queryTask(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) { @@ -71,6 +73,7 @@ public class XEmailTaskServer { return listPager; } + @RequiresPermissions("task-email:add") @PostMapping("/save") public void save(@RequestBody XpackEmailCreate param) throws Exception { XpackEmailTaskRequest request = param.fillContent(); @@ -81,6 +84,7 @@ public class XEmailTaskServer { scheduleService.addSchedule(globalTask); } + @RequiresPermissions("task-email:read") @PostMapping("/queryForm/{taskId}") public XpackEmailCreate queryForm(@PathVariable Long taskId) { EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); @@ -141,6 +145,7 @@ public class XEmailTaskServer { } + @RequiresPermissions("task-email:del") @PostMapping("/delete/{taskId}") public void delete(@PathVariable Long taskId) { EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XLdapServer.java b/backend/src/main/java/io/dataease/plugins/server/XLdapServer.java index 2a6c2c7d6a..44f77c9833 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XLdapServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XLdapServer.java @@ -6,6 +6,7 @@ import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.display.dto.response.SysSettingDto; import io.dataease.plugins.xpack.ldap.dto.response.LdapInfo; import io.dataease.plugins.xpack.ldap.service.LdapXpackService; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -21,6 +22,7 @@ public class XLdapServer { return ldapXpackService.info(); } + @RequiresPermissions("sysparam:read") @PostMapping("/save") public void save(@RequestBody List settings) { LdapXpackService ldapXpackService = SpringContextUtil.getBean(LdapXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XOidcServer.java b/backend/src/main/java/io/dataease/plugins/server/XOidcServer.java index becea9e55a..bf600f0aae 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XOidcServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XOidcServer.java @@ -5,6 +5,7 @@ import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.display.dto.response.SysSettingDto; import io.dataease.plugins.xpack.oidc.service.OidcXpackService; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; @@ -21,6 +22,7 @@ public class XOidcServer { return oidcXpackService.oidcSettings(); } + @RequiresPermissions("sysparam:read") @PostMapping("/save") public void save(@RequestBody List settings) { OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java b/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java index e3ba4da452..200a00155f 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java @@ -13,6 +13,7 @@ import io.dataease.plugins.xpack.role.dto.response.XpackRoleItemDto; import io.dataease.plugins.xpack.role.service.RoleXpackService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; @@ -26,6 +27,7 @@ public class XRoleServer { @Autowired private ExtAuthService extAuthService; + @RequiresPermissions("role:add") @ApiOperation("新增角色") @PostMapping("/create") public void create(@RequestBody XpackRoleDto role){ @@ -34,6 +36,7 @@ public class XRoleServer { } + @RequiresPermissions("role:del") @ApiOperation("删除角色") @PostMapping("/delete/{roleId}") public void delete(@PathVariable("roleId") Long roleId){ @@ -43,6 +46,7 @@ public class XRoleServer { } + @RequiresPermissions("role:edit") @ApiOperation("更新角色") @PostMapping("/update") public void update(@RequestBody XpackRoleDto role){ @@ -50,6 +54,7 @@ public class XRoleServer { roleXpackService.update(role); } + @RequiresPermissions("role:read") @ApiOperation("分页查询") @PostMapping("/roleGrid/{goPage}/{pageSize}") public Pager> roleGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) { diff --git a/backend/src/main/java/io/dataease/plugins/server/view/PluginViewServer.java b/backend/src/main/java/io/dataease/plugins/server/view/PluginViewServer.java new file mode 100644 index 0000000000..d57b1088ab --- /dev/null +++ b/backend/src/main/java/io/dataease/plugins/server/view/PluginViewServer.java @@ -0,0 +1,33 @@ +package io.dataease.plugins.server.view; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.view.entity.PluginViewType; +import io.dataease.plugins.view.service.ViewPluginService; + +@RequestMapping("/plugin/view") +@RestController +public class PluginViewServer { + + @PostMapping("/types") + public List types() { + List result = new ArrayList<>(); + Map beanMap = SpringContextUtil.getApplicationContext() + .getBeansOfType(ViewPluginService.class); + if (beanMap.keySet().size() == 0) { + return result; + } + for (Entry entry : beanMap.entrySet()) { + result.add(entry.getValue().viewType()); + } + return result; + } +} diff --git a/backend/src/main/java/io/dataease/provider/query/doris/DorisQueryProvider.java b/backend/src/main/java/io/dataease/provider/query/doris/DorisQueryProvider.java index 9ba233dc06..4e2a59f65d 100644 --- a/backend/src/main/java/io/dataease/provider/query/doris/DorisQueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/query/doris/DorisQueryProvider.java @@ -76,7 +76,7 @@ public class DorisQueryProvider extends QueryProvider { @Override public String createSQLPreview(String sql, String orderBy) { - return "SELECT * FROM (" + sql + ") AS tmp ORDER BY " + orderBy + " LIMIT 0,1000"; + return "SELECT * FROM (" + sqlFix(sql) + ") AS tmp LIMIT 0,1000"; } @Override @@ -147,14 +147,6 @@ public class DorisQueryProvider extends QueryProvider { if (customWheres != null) wheres.add(customWheres); if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); - if ((fields.size() > 0)) { - xOrders.add(SQLObj.builder() - .orderDirection("asc") - .orderField(fields.get(0).getDataeaseName()) - .orderAlias(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, "0")) - .build()); - st_sql.add("orders", xOrders); - } return st_sql.render(); } diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index c250176e74..2eb4a6a591 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -219,6 +219,11 @@ public class ChartViewService { } List xAxis = new Gson().fromJson(view.getXAxis(), new TypeToken>() { }.getType()); + if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot")) { + List xAxisExt = new Gson().fromJson(view.getXAxisExt(), new TypeToken>() { + }.getType()); + xAxis.addAll(xAxisExt); + } List yAxis = new Gson().fromJson(view.getYAxis(), new TypeToken>() { }.getType()); if (StringUtils.equalsIgnoreCase(view.getType(), "chart-mix")) { @@ -1679,9 +1684,9 @@ public class ChartViewService { return chartViewMapper.selectByPrimaryKey(id); } - public String chartCopy(String id) { + public String chartCopy(String id,String panelId) { String newChartId = UUID.randomUUID().toString(); - extChartViewMapper.chartCopy(newChartId, id); + extChartViewMapper.chartCopy(newChartId, id,panelId); return newChartId; } diff --git a/backend/src/main/java/io/dataease/service/dataset/DataSetGroupService.java b/backend/src/main/java/io/dataease/service/dataset/DataSetGroupService.java index 2a5f04ec2f..a6b42f3038 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetGroupService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetGroupService.java @@ -1,9 +1,11 @@ package io.dataease.service.dataset; +import io.dataease.auth.annotation.DeCleaner; import io.dataease.base.domain.DatasetGroup; import io.dataease.base.domain.DatasetGroupExample; import io.dataease.base.mapper.DatasetGroupMapper; import io.dataease.base.mapper.ext.ExtDataSetGroupMapper; +import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.TreeUtils; @@ -39,6 +41,7 @@ public class DataSetGroupService { @Resource private SysAuthService sysAuthService; + @DeCleaner(DePermissionType.DATASET) public DataSetGroupDTO save(DatasetGroup datasetGroup) { checkName(datasetGroup); if (StringUtils.isEmpty(datasetGroup.getId())) { diff --git a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java index ef659854cf..ed92c08d74 100644 --- a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java +++ b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java @@ -1,18 +1,18 @@ package io.dataease.service.datasource; -import cn.hutool.json.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.jayway.jsonpath.JsonPath; +import io.dataease.auth.annotation.DeCleaner; import io.dataease.base.domain.*; import io.dataease.base.mapper.*; import io.dataease.base.mapper.ext.ExtDataSourceMapper; import io.dataease.base.mapper.ext.query.GridExample; +import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.exception.DEException; import io.dataease.commons.model.AuthURD; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.CommonThreadPool; -import io.dataease.commons.utils.HttpClientUtil; import io.dataease.commons.utils.LogUtil; import io.dataease.controller.ResultHolder; import io.dataease.controller.request.DatasourceUnionRequest; @@ -20,7 +20,6 @@ import io.dataease.controller.request.datasource.ApiDefinition; import io.dataease.controller.sys.base.BaseGridRequest; import io.dataease.controller.sys.base.ConditionEntity; import io.dataease.commons.constants.DatasourceTypes; -import io.dataease.exception.ExcelException; import io.dataease.provider.datasource.ApiProvider; import io.dataease.provider.datasource.DatasourceProvider; import io.dataease.provider.ProviderFactory; @@ -57,6 +56,7 @@ public class DatasourceService { @Resource private CommonThreadPool commonThreadPool; + @DeCleaner(DePermissionType.DATASOURCE) public Datasource addDatasource(Datasource datasource) throws Exception{ checkName(datasource); long currentTimeMillis = System.currentTimeMillis(); diff --git a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java index b063082e99..bba789b07a 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java @@ -1,14 +1,20 @@ package io.dataease.service.panel; +import io.dataease.auth.annotation.DeCleaner; import io.dataease.base.domain.*; import io.dataease.base.mapper.ChartViewMapper; import io.dataease.base.mapper.PanelGroupMapper; +import io.dataease.base.mapper.VAuthModelMapper; import io.dataease.base.mapper.ext.ExtPanelGroupMapper; import io.dataease.base.mapper.ext.ExtPanelLinkJumpMapper; +import io.dataease.base.mapper.ext.ExtVAuthModelMapper; +import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.constants.PanelConstants; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.TreeUtils; +import io.dataease.controller.request.authModel.VAuthModelRequest; import io.dataease.controller.request.panel.PanelGroupRequest; +import io.dataease.dto.authModel.VAuthModelDTO; import io.dataease.dto.chart.ChartViewDTO; import io.dataease.dto.panel.PanelGroupDTO; import io.dataease.exception.DataEaseException; @@ -28,6 +34,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; /** * Author: wangjiahao @@ -59,7 +66,10 @@ public class PanelGroupService { private PanelViewService panelViewService; @Resource private ExtPanelLinkJumpMapper extPanelLinkJumpMapper; - + @Resource + private ExtVAuthModelMapper extVAuthModelMapper; + @Resource + private VAuthModelMapper vAuthModelMapper; public List tree(PanelGroupRequest panelGroupRequest) { String userId = String.valueOf(AuthUtils.getUser().getUserId()); @@ -75,6 +85,7 @@ public class PanelGroupService { return TreeUtils.mergeTree(panelGroupDTOList, "default_panel"); } + @DeCleaner(DePermissionType.PANEL) @Transactional public PanelGroup saveOrUpdate(PanelGroupRequest request) { try { @@ -157,6 +168,9 @@ public class PanelGroupService { if (!CollectionUtils.isNotEmpty(panelGroupDTOList)) { DataEaseException.throwException("未查询到用户对应的资源权限,请尝试刷新重新保存"); } + + //移除没有用到的仪表板私有视图 + extPanelGroupMapper.removeUselessViews(panelId); return panelGroupDTOList.get(0); } @@ -214,4 +228,31 @@ public class PanelGroupService { return chartViewDTOList; } + public List queryPanelViewTree(){ + List result = new ArrayList<>(); + VAuthModelRequest panelRequest = new VAuthModelRequest(); + panelRequest.setUserId(String.valueOf(AuthUtils.getUser().getUserId())); + panelRequest.setModelType("panel"); + List panelResult = extVAuthModelMapper.queryAuthModel(panelRequest); + // 获取仪表板下面的视图 + if(CollectionUtils.isNotEmpty(panelResult)){ + result.addAll(panelResult); + List panelIds = panelResult.stream().map(VAuthModelDTO::getId).collect(Collectors.toList()); + VAuthModelRequest viewRequest = new VAuthModelRequest(); + viewRequest.setPids(panelIds); + List viewResult = extVAuthModelMapper.queryAuthModelViews(viewRequest); + if(CollectionUtils.isNotEmpty(viewResult)){ + result.addAll(viewResult); + } + result = TreeUtils.mergeTree(result,"panel_list"); + // 原有视图的目录结构 + List viewOriginal = extVAuthModelMapper.queryAuthViewsOriginal(viewRequest); + if(CollectionUtils.isNotEmpty(viewOriginal) && viewOriginal.size()>1){ + result.addAll(TreeUtils.mergeTree(viewOriginal,"public_chart")); + } + } + + return result; + } + } diff --git a/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java b/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java index 2ec72e2990..65ee577faa 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java @@ -9,6 +9,7 @@ import io.dataease.base.mapper.PanelLinkMapper; import io.dataease.base.mapper.PanelLinkMappingMapper; import io.dataease.base.mapper.ext.ExtPanelLinkMapper; import io.dataease.commons.utils.AuthUtils; +import io.dataease.commons.utils.CodingUtil; import io.dataease.commons.utils.ServletUtils; import io.dataease.controller.request.panel.link.EnablePwdRequest; import io.dataease.controller.request.panel.link.LinkRequest; @@ -18,6 +19,7 @@ import io.dataease.dto.panel.link.GenerateDto; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,7 +27,6 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; -import java.util.Optional; @Service public class PanelLinkService { @@ -34,6 +35,9 @@ public class PanelLinkService { private static final String USERPARAM = "&user="; private static final String SHORT_URL_PREFIX = "/link/"; + @Value("${server.servlet.context-path}") + private String contextPath; + @Resource private PanelLinkMapper mapper; @Resource @@ -43,14 +47,22 @@ public class PanelLinkService { @Resource private PanelLinkMappingMapper panelLinkMappingMapper; + @Transactional public void changeValid(LinkRequest request) { PanelLink po = new PanelLink(); po.setResourceId(request.getResourceId()); po.setValid(request.isValid()); - mapper.updateByExampleSelective(po, example(request.getResourceId(), AuthUtils.getUser().getUserId())); + Long userId = AuthUtils.getUser().getUserId(); + mapper.updateByExampleSelective(po, example(request.getResourceId(), userId)); + + PanelLinkMappingExample example = new PanelLinkMappingExample(); + example.createCriteria().andResourceIdEqualTo(request.getResourceId()).andUserIdEqualTo(userId); + PanelLinkMapping mapping = new PanelLinkMapping(); + mapping.setUuid(CodingUtil.shortUuid()); + panelLinkMappingMapper.updateByExampleSelective(mapping, example); } - private PanelLinkExample example(String panelLinkId, Long userId){ + private PanelLinkExample example(String panelLinkId, Long userId) { PanelLinkExample example = new PanelLinkExample(); example.createCriteria().andResourceIdEqualTo(panelLinkId).andUserIdEqualTo(userId); return example; @@ -78,18 +90,18 @@ public class PanelLinkService { private PanelLink findOne(String resourceId) { PanelLinkExample example = new PanelLinkExample(); example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdIsNull(); - List list = mapper.selectByExample(example); + List list = mapper.selectByExample(example); return CollectionUtils.isNotEmpty(list) ? list.get(0) : null; } public PanelLink findOne(String resourceId, Long userId) { - if(userId == null){ + if (userId == null) { return findOne(resourceId); } List panelLinks = mapper.selectByExample(example(resourceId, userId)); - if(CollectionUtils.isNotEmpty(panelLinks)){ + if (CollectionUtils.isNotEmpty(panelLinks)) { return panelLinks.get(0); - }else { + } else { return null; } } @@ -114,6 +126,7 @@ public class PanelLinkService { PanelLinkMapping mapping = new PanelLinkMapping(); mapping.setResourceId(resourceId); mapping.setUserId(AuthUtils.getUser().getUserId()); + mapping.setUuid(CodingUtil.shortUuid()); panelLinkMappingMapper.insert(mapping); } return convertDto(one); @@ -141,8 +154,8 @@ public class PanelLinkService { private String buildLinkParam(PanelLink link) { String linkParam = encrypt(link.getResourceId()); - if(link.getUserId() != null){ - linkParam = linkParam+ USERPARAM + link.getUserId().toString(); + if (link.getUserId() != null) { + linkParam = linkParam + USERPARAM + link.getUserId().toString(); } return linkParam; } @@ -161,7 +174,8 @@ public class PanelLinkService { public Boolean validateHeads(PanelLink panelLink) throws Exception { HttpServletRequest request = ServletUtils.request(); String token = request.getHeader("LINK-PWD-TOKEN"); - if (!panelLink.getEnablePwd() || StringUtils.isEmpty(token) || StringUtils.equals("undefined", token) || StringUtils.equals("null", token)) { + if (!panelLink.getEnablePwd() || StringUtils.isEmpty(token) || StringUtils.equals("undefined", token) + || StringUtils.equals("null", token)) { String resourceId = panelLink.getResourceId(); String pwd = "dataease"; String tk = JWTUtils.signLink(resourceId, panelLink.getUserId(), pwd); @@ -170,7 +184,8 @@ public class PanelLinkService { httpServletResponse.setHeader("LINK-PWD-TOKEN", tk); return false; } - if (StringUtils.isEmpty(panelLink.getPwd())) return false; + if (StringUtils.isEmpty(panelLink.getPwd())) + return false; return JWTUtils.verifyLink(token, panelLink.getResourceId(), panelLink.getUserId(), panelLink.getPwd()); } @@ -206,11 +221,32 @@ public class PanelLinkService { example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(AuthUtils.getUser().getUserId()); List mappings = panelLinkMappingMapper.selectByExample(example); PanelLinkMapping mapping = mappings.get(0); - return SHORT_URL_PREFIX + mapping.getId(); + String uuid = mapping.getUuid(); + return contextPath + SHORT_URL_PREFIX + (StringUtils.isBlank(uuid) ? mapping.getId() : uuid); } public String getUrlByIndex(Long index) { PanelLinkMapping mapping = panelLinkMappingMapper.selectByPrimaryKey(index); + + String resourceId = mapping.getResourceId(); + Long userId = mapping.getUserId(); + PanelLink one = findOne(resourceId, userId); + if (StringUtils.isNotBlank(mapping.getUuid())) { + one.setResourceId("error-resource-id"); + } + return convertDto(one).getUri(); + } + + public String getUrlByUuid(String uuid) { + PanelLinkMappingExample example = new PanelLinkMappingExample(); + example.createCriteria().andUuidEqualTo(uuid); + List mappings = panelLinkMappingMapper.selectByExample(example); + if (CollectionUtils.isEmpty(mappings)) { + PanelLink panelLink = new PanelLink(); + panelLink.setResourceId("error-resource-id"); + return BASEURL + buildLinkParam(panelLink); + } + PanelLinkMapping mapping = mappings.get(0); String resourceId = mapping.getResourceId(); Long userId = mapping.getUserId(); PanelLink one = findOne(resourceId, userId); diff --git a/backend/src/main/resources/application-stage.properties b/backend/src/main/resources/application-stage.properties new file mode 100644 index 0000000000..4e1c3c1d54 --- /dev/null +++ b/backend/src/main/resources/application-stage.properties @@ -0,0 +1 @@ +server.servlet.context-path=/de-api \ No newline at end of file diff --git a/backend/src/main/resources/application-whole.properties b/backend/src/main/resources/application-whole.properties new file mode 100644 index 0000000000..99b93b71c8 --- /dev/null +++ b/backend/src/main/resources/application-whole.properties @@ -0,0 +1 @@ +server.servlet.context-path= \ No newline at end of file diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 4b4a49e919..fdb33ea352 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.profiles.active=@profiles.active@ spring.application.name=dataease server.port=8081 diff --git a/backend/src/main/resources/db/migration/V32__1.8.sql b/backend/src/main/resources/db/migration/V32__1.8.sql new file mode 100644 index 0000000000..7657d638ed --- /dev/null +++ b/backend/src/main/resources/db/migration/V32__1.8.sql @@ -0,0 +1,315 @@ +ALTER TABLE `chart_view` ADD COLUMN `x_axis_ext` LONGTEXT COMMENT 'table-row' AFTER `x_axis`; +UPDATE `chart_view` SET `x_axis_ext` = '[]'; + + +INSERT INTO `chart_group` (`id`, `name`, `pid`, `level`, `type`, `create_by`, `create_time`) VALUES ('0', 'i18n_public_chart', 'public_chart', -1, 'history', 'admin', NULL); + +ALTER TABLE `chart_view` +MODIFY COLUMN `scene_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '场景ID chart_type为private的时候 是仪表板id' AFTER `title`, +ADD COLUMN `chart_type` varchar(255) NULL DEFAULT 'public' COMMENT '视图类型 public 公共 历史可复用的视图,private 私有 专属某个仪表板' AFTER `style_priority`; + +delete from sys_auth_detail where auth_id in(select id from sys_auth where auth_source_type = 'chart'); +delete from sys_auth where auth_source_type = 'chart'; + +DROP TRIGGER `new_auth_chart_view`; +DROP TRIGGER `delete_auth_chart_view`; + +delete from sys_menu where menu_id ='10'; + +DROP VIEW IF EXISTS `v_auth_model`; +CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_auth_model` AS SELECT +`sys_user`.`user_id` AS `id`, +`sys_user`.`username` AS `name`, +`sys_user`.`username` AS `label`, +'0' AS `pid`, +'leaf' AS `node_type`, +'user' AS `model_type`, +'user' AS `model_inner_type`, +'target' AS `auth_type`, +`sys_user`.`create_by` AS `create_by`, +0 AS `level`, +0 AS `mode`, +'0' AS `data_source_id` +FROM + `sys_user` +WHERE + ( `sys_user`.`is_admin` <> 1 ) UNION ALL +SELECT + `sys_role`.`role_id` AS `id`, + `sys_role`.`name` AS `name`, + `sys_role`.`name` AS `label`, + '0' AS `pid`, + 'leaf' AS `node_type`, + 'role' AS `model_type`, + 'role' AS `model_inner_type`, + 'target' AS `auth_type`, + `sys_role`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` +FROM + `sys_role` UNION ALL +SELECT + `sys_dept`.`dept_id` AS `id`, + `sys_dept`.`name` AS `name`, + `sys_dept`.`name` AS `lable`,( + cast( `sys_dept`.`pid` AS CHAR charset utf8mb4 ) COLLATE utf8mb4_general_ci + ) AS `pid`, +IF + (( `sys_dept`.`sub_count` = 0 ), 'leaf', 'spine' ) AS `node_type`, + 'dept' AS `model_type`, + 'dept' AS `model_inner_type`, + 'target' AS `auth_type`, + `sys_dept`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` +FROM + `sys_dept` UNION ALL +SELECT + `datasource`.`id` AS `id`, + `datasource`.`name` AS `NAME`, + `datasource`.`name` AS `label`, + '0' AS `pid`, + 'leaf' AS `node_type`, + 'link' AS `model_type`, + `datasource`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `datasource`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` +FROM + `datasource` UNION ALL +SELECT + `dataset_group`.`id` AS `id`, + `dataset_group`.`name` AS `NAME`, + `dataset_group`.`name` AS `lable`, +IF + ( isnull( `dataset_group`.`pid` ), '0', `dataset_group`.`pid` ) AS `pid`, + 'spine' AS `node_type`, + 'dataset' AS `model_type`, + `dataset_group`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `dataset_group`.`create_by` AS `create_by`, + `dataset_group`.`level` AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` +FROM + `dataset_group` UNION ALL +SELECT + `dataset_table`.`id` AS `id`, + `dataset_table`.`name` AS `NAME`, + `dataset_table`.`name` AS `lable`, + `dataset_table`.`scene_id` AS `pid`, + 'leaf' AS `node_type`, + 'dataset' AS `model_type`, + `dataset_table`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `dataset_table`.`create_by` AS `create_by`, + 0 AS `level`, + `dataset_table`.`mode` AS `mode`, + `dataset_table`.`data_source_id` AS `data_source_id` +FROM + `dataset_table` UNION ALL +SELECT + `panel_group`.`id` AS `id`, + `panel_group`.`name` AS `NAME`, + `panel_group`.`name` AS `label`,( + CASE + `panel_group`.`id` + WHEN 'panel_list' THEN + '0' + WHEN 'default_panel' THEN + '0' ELSE `panel_group`.`pid` + END + ) AS `pid`, + IF + (( `panel_group`.`node_type` = 'folder' ), 'spine', 'leaf' ) AS `node_type`, + 'panel' AS `model_type`, + `panel_group`.`panel_type` AS `model_inner_type`, + 'source' AS `auth_type`, + `panel_group`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `panel_group` UNION ALL + SELECT + `sys_menu`.`menu_id` AS `menu_id`, + `sys_menu`.`title` AS `name`, + `sys_menu`.`title` AS `label`, + `sys_menu`.`pid` AS `pid`, + IF + (( `sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`, + 'menu' AS `model_type`,( + CASE + `sys_menu`.`type` + WHEN 0 THEN + 'folder' + WHEN 1 THEN + 'menu' + WHEN 2 THEN + 'button' + END + ) AS `model_inner_type`, + 'source' AS `auth_type`, + `sys_menu`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `sys_menu` + WHERE + (( + `sys_menu`.`i_frame` <> 1 + ) + OR isnull( `sys_menu`.`i_frame` )) UNION ALL + SELECT + `plugin_sys_menu`.`menu_id` AS `menu_id`, + `plugin_sys_menu`.`title` AS `name`, + `plugin_sys_menu`.`title` AS `label`, + `plugin_sys_menu`.`pid` AS `pid`, + IF + (( `plugin_sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`, + 'menu' AS `model_type`,( + CASE + `plugin_sys_menu`.`type` + WHEN 0 THEN + 'folder' + WHEN 1 THEN + 'menu' + WHEN 2 THEN + 'button' + END + ) AS `model_inner_type`, + 'source' AS `auth_type`, + `plugin_sys_menu`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `plugin_sys_menu` + WHERE + (( + `plugin_sys_menu`.`i_frame` <> 1 + ) + OR isnull( `plugin_sys_menu`.`i_frame` )); + + + +delete from panel_view where id in ( +'5dafcf9b-8e0a-11ec-8e4b-0242ac130002', +'5dafd1d1-8e0a-11ec-8e4b-0242ac130002', +'5dafd224-8e0a-11ec-8e4b-0242ac130002', +'5dafd26e-8e0a-11ec-8e4b-0242ac130002', +'5dafd2ac-8e0a-11ec-8e4b-0242ac130002', +'5dafd2f1-8e0a-11ec-8e4b-0242ac130002', +'5dafd32e-8e0a-11ec-8e4b-0242ac130002', +'5dafd363-8e0a-11ec-8e4b-0242ac130002', +'6c200051-8e0a-11ec-8e4b-0242ac130002', +'6c2002c2-8e0a-11ec-8e4b-0242ac130002', +'6c20030f-8e0a-11ec-8e4b-0242ac130002', +'6c2003ca-8e0a-11ec-8e4b-0242ac130002', +'6c20040d-8e0a-11ec-8e4b-0242ac130002', +'6c200442-8e0a-11ec-8e4b-0242ac130002', +'6c200478-8e0a-11ec-8e4b-0242ac130002', +'6c2004a9-8e0a-11ec-8e4b-0242ac130002', +'6c2004e4-8e0a-11ec-8e4b-0242ac130002', +'6c200530-8e0a-11ec-8e4b-0242ac130002', +'6c200568-8e0a-11ec-8e4b-0242ac130002', +'6c200598-8e0a-11ec-8e4b-0242ac130002', +'7611e439-8e0a-11ec-8e4b-0242ac130002', +'7611e678-8e0a-11ec-8e4b-0242ac130002', +'7611e6c4-8e0a-11ec-8e4b-0242ac130002', +'7611e700-8e0a-11ec-8e4b-0242ac130002', +'7611e7d0-8e0a-11ec-8e4b-0242ac130002', +'7611e80a-8e0a-11ec-8e4b-0242ac130002', +'7611e844-8e0a-11ec-8e4b-0242ac130002', +'7611e87d-8e0a-11ec-8e4b-0242ac130002', +'7611e8b5-8e0a-11ec-8e4b-0242ac130002', +'7611e8ed-8e0a-11ec-8e4b-0242ac130002', +'7611e923-8e0a-11ec-8e4b-0242ac130002', +'7611e957-8e0a-11ec-8e4b-0242ac130002', +'7611e98f-8e0a-11ec-8e4b-0242ac130002', +'7611e9c9-8e0a-11ec-8e4b-0242ac130002', +'7611ea05-8e0a-11ec-8e4b-0242ac130002', +'7611ea46-8e0a-11ec-8e4b-0242ac130002', +'805b082d-8e0a-11ec-8e4b-0242ac130002', +'805b0a85-8e0a-11ec-8e4b-0242ac130002', +'805b0abb-8e0a-11ec-8e4b-0242ac130002', +'805b0ae0-8e0a-11ec-8e4b-0242ac130002', +'805b0b0f-8e0a-11ec-8e4b-0242ac130002', +'805b0b2d-8e0a-11ec-8e4b-0242ac130002', +'805b0bdb-8e0a-11ec-8e4b-0242ac130002', +'805b0cc1-8e0a-11ec-8e4b-0242ac130002', +'805b0cf8-8e0a-11ec-8e4b-0242ac130002', +'805b0d31-8e0a-11ec-8e4b-0242ac130002' +); + +INSERT INTO `panel_view` VALUES ('5dafcf9b-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', '84b444e1-0088-44f9-acdc-cc39018413bc', NULL, NULL, NULL, NULL, NULL), ('5dafd1d1-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'c68db172-2df2-4aa2-aad6-077cf1684e14', NULL, NULL, NULL, NULL, NULL), ('5dafd224-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'f8d62b2b-b99a-4b6c-8378-d7c2ec4ea766', NULL, NULL, NULL, NULL, NULL), ('5dafd26e-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'c4943403-4960-4ad8-a9c5-12c46c538c34', NULL, NULL, NULL, NULL, NULL), ('5dafd2ac-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'f257452d-6fc1-4499-bdce-bd10b3e1c520', NULL, NULL, NULL, NULL, NULL), ('5dafd2f1-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', '8271c4e4-43ab-48c6-b7b4-67ccaba3f80b', NULL, NULL, NULL, NULL, NULL), ('5dafd32e-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'a0058881-b29f-4b5c-911f-7f1480b07eb0', NULL, NULL, NULL, NULL, NULL), ('5dafd363-8e0a-11ec-8e4b-0242ac130002', '117f679e-8355-4645-a692-47e2009cbc0d', 'c36cd358-0501-4f83-a323-f754485d00b1', NULL, NULL, NULL, NULL, NULL), ('6c200051-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '95f8e3a2-62a5-48a7-a719-fcf53746da8d', NULL, NULL, NULL, NULL, NULL), ('6c2002c2-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '8a26a936-89bf-45a8-b1ce-d5ef1719465d', NULL, NULL, NULL, NULL, NULL), ('6c20030f-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '8d1c3f30-0639-452e-9883-164f37353324', NULL, NULL, NULL, NULL, NULL), ('6c2003ca-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '175b25df-1939-4582-a9c5-d9e8ed3ea2b1', NULL, NULL, NULL, NULL, NULL), ('6c20040d-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', 'c3da496f-073c-413a-bebd-e7f1a4a00ba7', NULL, NULL, NULL, NULL, NULL), ('6c200442-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', 'da18eecd-feff-4140-a291-cce4abf1afaa', NULL, NULL, NULL, NULL, NULL), ('6c200478-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '3f201733-bbb3-485e-a1d6-0fe4f00b5304', NULL, NULL, NULL, NULL, NULL), ('6c2004a9-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '692d5bdc-aa70-4fce-b830-b8d6620539c6', NULL, NULL, NULL, NULL, NULL), ('6c2004e4-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', 'aff5be0c-f195-4fce-bd2b-b8d0e63764de', NULL, NULL, NULL, NULL, NULL), ('6c200530-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', 'cb66836d-a34c-40c6-87e7-0db0375ec19e', NULL, NULL, NULL, NULL, NULL), ('6c200568-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '1d06e2a0-d936-4192-b523-2eb1e8cebd51', NULL, NULL, NULL, NULL, NULL), ('6c200598-8e0a-11ec-8e4b-0242ac130002', 'c8d4c4b4-2293-417f-b76d-3632cc217bb1', '0de1d446-8300-4ab3-a4ef-4e8f8579cb2e', NULL, NULL, NULL, NULL, NULL), ('7611e439-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', 'ebac2821-d1a0-4f26-b5d9-cd5c60ac75ab', NULL, NULL, NULL, NULL, NULL), ('7611e678-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '5ad64afc-132c-40ea-8f69-2f8bfe6b31d4', NULL, NULL, NULL, NULL, NULL), ('7611e6c4-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '4242cbb0-fca4-4b27-b2a7-ca576a18815e', NULL, NULL, NULL, NULL, NULL), ('7611e700-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', 'c52b6d95-b404-4130-8635-5903cb8d0e84', NULL, NULL, NULL, NULL, NULL), ('7611e7d0-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '2e6f8b45-116d-46c4-a287-f3054e798556', NULL, NULL, NULL, NULL, NULL), ('7611e80a-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '504c0abd-7d31-4771-8ef9-a3494c7bb33c', NULL, NULL, NULL, NULL, NULL), ('7611e844-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '02136575-effb-4a0c-b5be-9886d20259b3', NULL, NULL, NULL, NULL, NULL), ('7611e87d-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '8412d80d-1830-4128-bc6a-019cf32afc7f', NULL, NULL, NULL, NULL, NULL), ('7611e8b5-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '0f9cd623-f319-4bb5-9751-7478abee3bd2', NULL, NULL, NULL, NULL, NULL), ('7611e8ed-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', 'a1d7bfef-f20c-4739-bfe4-cc55ed0b3fc8', NULL, NULL, NULL, NULL, NULL), ('7611e923-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '68fc74f2-1790-427a-ac22-49fb20edbe9a', NULL, NULL, NULL, NULL, NULL), ('7611e957-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '97400660-27a5-4502-a7cd-274190953a6c', NULL, NULL, NULL, NULL, NULL), ('7611e98f-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '07ece816-f983-493e-b25d-7bfb467d787d', NULL, NULL, NULL, NULL, NULL), ('7611e9c9-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', 'c124c0f3-3f1f-4635-bac7-f3e1f5503099', NULL, NULL, NULL, NULL, NULL), ('7611ea05-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '984059ca-3f9d-4ee4-9616-e409dd11991e', NULL, NULL, NULL, NULL, NULL), ('7611ea46-8e0a-11ec-8e4b-0242ac130002', 'd2bda4c3-3c25-40c6-bed3-994ffe2949df', '2de7c3d3-e642-4509-aff1-b2520ebfe85e', NULL, NULL, NULL, NULL, NULL), ('805b082d-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '3a5e4081-4cd5-427f-bd3a-ff7815efaf25', NULL, NULL, NULL, NULL, NULL), ('805b0a85-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '57760693-15db-4de9-9170-55ee7d1eb0eb', NULL, NULL, NULL, NULL, NULL), ('805b0abb-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '0d8bc9d7-b76b-4ec5-96e7-0df1c3426205', NULL, NULL, NULL, NULL, NULL), ('805b0ae0-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '03410ec1-1bd0-4afd-ac37-9306e00e328c', NULL, NULL, NULL, NULL, NULL), ('805b0b0f-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', 'eaa8947b-d9e7-4ca4-ba65-08965dfa620c', NULL, NULL, NULL, NULL, NULL), ('805b0b2d-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '93a58625-3730-4a07-99bd-75f174ff428d', NULL, NULL, NULL, NULL, NULL), ('805b0bdb-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '2f9bf4d5-b1d3-4cac-9df2-2c8827d65bbf', NULL, NULL, NULL, NULL, NULL), ('805b0cc1-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '1aad98e5-3f99-4c0a-aa75-ca9236de0f09', NULL, NULL, NULL, NULL, NULL), ('805b0cf8-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '5f694f25-b0fd-45f6-acbd-9dd338e196ce', NULL, NULL, NULL, NULL, NULL), ('805b0d31-8e0a-11ec-8e4b-0242ac130002', 'ceb6cd6c-531e-4a23-a467-caa5ef7218cc', '9ecb6827-f47f-4b19-b788-81a6b55940af', NULL, NULL, NULL, NULL, NULL); + +update chart_view set chart_type ='private' +where id in ( +'84b444e1-0088-44f9-acdc-cc39018413bc', +'c68db172-2df2-4aa2-aad6-077cf1684e14', +'f8d62b2b-b99a-4b6c-8378-d7c2ec4ea766', +'c4943403-4960-4ad8-a9c5-12c46c538c34', +'f257452d-6fc1-4499-bdce-bd10b3e1c520', +'8271c4e4-43ab-48c6-b7b4-67ccaba3f80b', +'a0058881-b29f-4b5c-911f-7f1480b07eb0', +'c36cd358-0501-4f83-a323-f754485d00b1', +'95f8e3a2-62a5-48a7-a719-fcf53746da8d', +'8a26a936-89bf-45a8-b1ce-d5ef1719465d', +'8d1c3f30-0639-452e-9883-164f37353324', +'175b25df-1939-4582-a9c5-d9e8ed3ea2b1', +'c3da496f-073c-413a-bebd-e7f1a4a00ba7', +'da18eecd-feff-4140-a291-cce4abf1afaa', +'3f201733-bbb3-485e-a1d6-0fe4f00b5304', +'692d5bdc-aa70-4fce-b830-b8d6620539c6', +'aff5be0c-f195-4fce-bd2b-b8d0e63764de', +'cb66836d-a34c-40c6-87e7-0db0375ec19e', +'1d06e2a0-d936-4192-b523-2eb1e8cebd51', +'0de1d446-8300-4ab3-a4ef-4e8f8579cb2e', +'ebac2821-d1a0-4f26-b5d9-cd5c60ac75ab', +'5ad64afc-132c-40ea-8f69-2f8bfe6b31d4', +'4242cbb0-fca4-4b27-b2a7-ca576a18815e', +'c52b6d95-b404-4130-8635-5903cb8d0e84', +'2e6f8b45-116d-46c4-a287-f3054e798556', +'504c0abd-7d31-4771-8ef9-a3494c7bb33c', +'02136575-effb-4a0c-b5be-9886d20259b3', +'8412d80d-1830-4128-bc6a-019cf32afc7f', +'0f9cd623-f319-4bb5-9751-7478abee3bd2', +'a1d7bfef-f20c-4739-bfe4-cc55ed0b3fc8', +'68fc74f2-1790-427a-ac22-49fb20edbe9a', +'97400660-27a5-4502-a7cd-274190953a6c', +'07ece816-f983-493e-b25d-7bfb467d787d', +'c124c0f3-3f1f-4635-bac7-f3e1f5503099', +'984059ca-3f9d-4ee4-9616-e409dd11991e', +'2de7c3d3-e642-4509-aff1-b2520ebfe85e', +'3a5e4081-4cd5-427f-bd3a-ff7815efaf25', +'57760693-15db-4de9-9170-55ee7d1eb0eb', +'0d8bc9d7-b76b-4ec5-96e7-0df1c3426205', +'03410ec1-1bd0-4afd-ac37-9306e00e328c', +'eaa8947b-d9e7-4ca4-ba65-08965dfa620c', +'93a58625-3730-4a07-99bd-75f174ff428d', +'2f9bf4d5-b1d3-4cac-9df2-2c8827d65bbf', +'1aad98e5-3f99-4c0a-aa75-ca9236de0f09', +'5f694f25-b0fd-45f6-acbd-9dd338e196ce', +'9ecb6827-f47f-4b19-b788-81a6b55940af' +); + +delete from chart_group where id in ( +'2c200620-f2f3-4224-a41d-381fa061591b', +'3f551269-d985-4633-884d-d118704da2db', +'4de97755-5d5a-4fe0-9af0-27601f967787', +'5a8e8b0a-2f64-4d1b-aac1-d284b2b8436f', +'bc7542d8-2b7e-4909-81ff-3627b0227501', +'bfa7d87f-c76f-4406-9f19-0adccb7c568d' +); + +ALTER TABLE `panel_link_mapping` +ADD COLUMN `uuid` varchar(8) NULL COMMENT 'uuid' AFTER `user_id`; + +ALTER TABLE `chart_view` +ADD COLUMN `is_plugin` bit(1) NULL COMMENT '是否插件' AFTER `chart_type`; diff --git a/backend/src/main/resources/generatorConfig.xml b/backend/src/main/resources/generatorConfig.xml index e90877a423..ec4f820fc4 100644 --- a/backend/src/main/resources/generatorConfig.xml +++ b/backend/src/main/resources/generatorConfig.xml @@ -60,6 +60,6 @@ - +
diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index 8b8f3705cf..db35d7a38e 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -118,4 +118,5 @@ i18n_calc_field_error=Field expression error i18n_cp_exist=Column permission of the same type already exists connection_failed=Connection Failed theme_name_repeat=name of theme has been existed -theme_name_empty=name can not be empty \ No newline at end of file +theme_name_empty=name can not be empty +i18n_public_chart=【Public Chart】 diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index e52791f02a..a44472bba1 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -118,3 +118,4 @@ i18n_cp_exist=已有同类型的列权限存在 connection_failed=连接失败 theme_name_repeat=名称已存在 theme_name_empty=名称不能为空 +i18n_public_chart=【存量视图】 diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index c3f6464aaa..11914ecbda 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -119,3 +119,4 @@ i18n_cp_exist=已有同類型的列權限存在 connection_failed=連接失敗 theme_name_repeat=名稱已存在 theme_name_empty=名稱不能為空 +i18n_public_chart=【存量视图】 diff --git a/frontend/.env.staging b/frontend/.env.staging index a8793a0989..44c8f6dec2 100644 --- a/frontend/.env.staging +++ b/frontend/.env.staging @@ -4,5 +4,5 @@ NODE_ENV = production ENV = 'staging' # base api -VUE_APP_BASE_API = '/stage-api' +VUE_APP_BASE_API = '/de-api/' diff --git a/frontend/pom.xml b/frontend/pom.xml index f051750be0..1ca3d3227d 100644 --- a/frontend/pom.xml +++ b/frontend/pom.xml @@ -6,7 +6,7 @@ dataease-server io.dataease - 1.7.0 + 1.8.0 4.0.0 diff --git a/frontend/src/api/chart/chart.js b/frontend/src/api/chart/chart.js index 87abbcd662..b7657defbc 100644 --- a/frontend/src/api/chart/chart.js +++ b/frontend/src/api/chart/chart.js @@ -28,11 +28,11 @@ export function getChartTree(data) { }) } -export function chartCopy(id) { +export function chartCopy(id, panelId) { return request({ - url: '/chart/view/chartCopy/' + id, + url: '/chart/view/chartCopy/' + id + '/' + panelId, method: 'post', - loading: true + loading: false }) } export function chartGroupTree(data) { @@ -69,3 +69,10 @@ export function ajaxGetDataOnly(id, data) { data }) } + +export function pluginTypes() { + return request({ + url: '/plugin/view/types', + method: 'post' + }) +} diff --git a/frontend/src/api/panel/panel.js b/frontend/src/api/panel/panel.js index 675355f064..0a399b81af 100644 --- a/frontend/src/api/panel/panel.js +++ b/frontend/src/api/panel/panel.js @@ -154,3 +154,11 @@ export function initPanelData(panelId, callback) { callback(response) }) } + +export function queryPanelViewTree() { + return request({ + url: '/panel/group/queryPanelViewTree', + method: 'post' + }) +} + diff --git a/frontend/src/components/AsyncComponent/index.vue b/frontend/src/components/AsyncComponent/index.vue index 09dd19ef4c..7c0b613372 100644 --- a/frontend/src/components/AsyncComponent/index.vue +++ b/frontend/src/components/AsyncComponent/index.vue @@ -1,14 +1,15 @@ diff --git a/frontend/src/components/canvas/components/Editor/PreviewEject.vue b/frontend/src/components/canvas/components/Editor/PreviewEject.vue index d9c76d0453..6c23856e7f 100644 --- a/frontend/src/components/canvas/components/Editor/PreviewEject.vue +++ b/frontend/src/components/canvas/components/Editor/PreviewEject.vue @@ -53,7 +53,7 @@ export default { } // 加载视图数据 initPanelData(this.panelId, function() { - this.dataLoading = false + _this.dataLoading = false // 如果含有跳转参数 进行触发 const tempParam = localStorage.getItem('jumpInfoParam') if (tempParam) { diff --git a/frontend/src/components/canvas/custom-component/UserView.vue b/frontend/src/components/canvas/custom-component/UserView.vue index 74903dd566..a17634a791 100644 --- a/frontend/src/components/canvas/custom-component/UserView.vue +++ b/frontend/src/components/canvas/custom-component/UserView.vue @@ -16,8 +16,15 @@ {{ $t('chart.chart_error_tips') }} + - +
@@ -69,7 +76,7 @@ import ChartComponent from '@/views/chart/components/ChartComponent.vue' import TableNormal from '@/views/chart/components/table/TableNormal' import LabelNormal from '../../../views/chart/components/normal/LabelNormal' import { uuid } from 'vue-uuid' - +import bus from '@/utils/bus' import { mapState } from 'vuex' import { isChange } from '@/utils/conditionUtil' import { BASE_CHART_STRING } from '@/views/chart/chart/chart' @@ -82,10 +89,10 @@ import ChartComponentG2 from '@/views/chart/components/ChartComponentG2' import EditBarView from '@/components/canvas/components/Editor/EditBarView' import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/components/canvas/utils/style' import ChartComponentS2 from '@/views/chart/components/ChartComponentS2' - +import PluginCom from '@/views/system/plugin/PluginCom' export default { name: 'UserView', - components: { ChartComponentS2, EditBarView, ChartComponent, TableNormal, LabelNormal, DrillPath, ChartComponentG2 }, + components: { PluginCom, ChartComponentS2, EditBarView, ChartComponent, TableNormal, LabelNormal, DrillPath, ChartComponentG2 }, props: { element: { type: Object, @@ -108,6 +115,7 @@ export default { required: false, default: false }, + // eslint-disable-next-line vue/require-default-prop componentIndex: { type: Number, required: false @@ -156,6 +164,9 @@ export default { sourceCustomStyleStr: null } }, + mounted() { + this.bindPluginEvent() + }, computed: { scaleCoefficient() { if (this.terminal === 'pc' && !this.mobileLayoutStatus) { @@ -260,6 +271,7 @@ export default { }, watch: { + 'cfilters': { handler: function(val1, val2) { if (isChange(val1, val2) && !this.isFirstLoad) { @@ -286,7 +298,9 @@ export default { } // 如果gap有变化刷新 if (this.preCanvasPanel && this.preCanvasPanel.gap !== newVal.panel.gap) { - this.$refs[this.element.propValue.id].chartResize() + this.chart.isPlugin + ? this.$refs[this.element.propValue.id].callPluginInner({ methodName: 'chartResize' }) + : this.$refs[this.element.propValue.id].chartResize() } this.preCanvasPanel = deepCopy(newVal.panel) }, @@ -301,7 +315,9 @@ export default { this.changeIndex++ this.chartResize(this.changeIndex) } else { - this.$refs[this.element.propValue.id].chartResize() + this.chart.isPlugin + ? this.$refs[this.element.propValue.id].callPluginInner({ methodName: 'chartResize' }) + : this.$refs[this.element.propValue.id].chartResize() } } }, @@ -320,7 +336,8 @@ export default { } }, 'chartType': function(newVal, oldVal) { - if (newVal === 'map' && newVal !== oldVal) { + // this.isPlugin = this.plugins.some(plugin => plugin.value === this.chart.type) + if ((newVal === 'map' || newVal === 'buddle-map') && newVal !== oldVal) { this.initAreas() } }, @@ -334,6 +351,7 @@ export default { deep: true } }, + created() { this.refId = uuid.v1 if (this.element && this.element.propValue && this.element.propValue.viewId) { @@ -343,6 +361,14 @@ export default { } }, methods: { + bindPluginEvent() { + bus.$on('plugin-chart-click', this.chartClick) + bus.$on('plugin-jump-click', this.jumpClick) + bus.$on('plugin-add-view-track-filter', this.addViewTrackFilter) + }, + addViewTrackFilter(linkageParam) { + this.$store.commit('addViewTrackFilter', linkageParam) + }, // 根据仪表板的缩放比例,修改视图内部参数 mergeScale() { const scale = Math.min(this.previewCanvasScale.scalePointWidth, this.previewCanvasScale.scalePointHeight) * this.scaleCoefficient @@ -459,7 +485,7 @@ export default { chartClick(param) { if (this.drillClickDimensionList.length < this.chart.drillFields.length - 1) { - this.chart.type === 'map' && this.sendToChildren(param) + (this.chart.type === 'map' || this.chart.type === 'buddle-map') && this.sendToChildren(param) this.drillClickDimensionList.push({ dimensionList: param.data.dimensionList }) this.getData(this.element.propValue.viewId) } else if (this.chart.drillFields.length > 0) { @@ -529,17 +555,22 @@ export default { resetDrill() { const length = this.drillClickDimensionList.length this.drillClickDimensionList = [] - if (this.chart.type === 'map') { + if (this.chart.type === 'map' || this.chart.type === 'buddle-map') { this.backToParent(0, length) const current = this.$refs[this.element.propValue.id] - current && current.registerDynamicMap && current.registerDynamicMap(null) + + if (this.chart.isPlugin) { + current && current.callPluginInner({ methodName: 'registerDynamicMap', methodParam: null }) + } else { + current && current.registerDynamicMap && current.registerDynamicMap(null) + } } }, drillJump(index) { const length = this.drillClickDimensionList.length this.drillClickDimensionList = this.drillClickDimensionList.slice(0, index) - if (this.chart.type === 'map') { + if (this.chart.type === 'map' || this.chart.type === 'buddle-map') { this.backToParent(index, length) } this.getData(this.element.propValue.viewId) @@ -558,7 +589,11 @@ export default { this.currentAcreaNode = tempNode const current = this.$refs[this.element.propValue.id] - current && current.registerDynamicMap && current.registerDynamicMap(this.currentAcreaNode.code) + if (this.chart.isPlugin) { + current && current.callPluginInner({ methodName: 'registerDynamicMap', methodParam: this.currentAcreaNode.code }) + } else { + current && current.registerDynamicMap && current.registerDynamicMap(this.currentAcreaNode.code) + } }, // 切换下一级地图 @@ -575,7 +610,11 @@ export default { const nextNode = currentNode.children.find(item => item.name === name) this.currentAcreaNode = nextNode const current = this.$refs[this.element.propValue.id] - nextNode && current && current.registerDynamicMap && current.registerDynamicMap(nextNode.code) + if (this.chart.isPlugin) { + nextNode && current && current.callPluginInner({ methodName: 'registerDynamicMap', methodParam: nextNode.code }) + } else { + nextNode && current && current.registerDynamicMap && current.registerDynamicMap(nextNode.code) + } } }, @@ -604,7 +643,12 @@ export default { const areaNode = this.findEntityByname(name, []) if (!areaNode) return const current = this.$refs[this.element.propValue.id] - current && current.registerDynamicMap && current.registerDynamicMap(areaNode.code) + + if (this.chart.isPlugin) { + current && current.callPluginInner({ methodName: 'registerDynamicMap', methodParam: areaNode.code }) + } else { + current && current.registerDynamicMap && current.registerDynamicMap(areaNode.code) + } }, // 根据地名获取areaCode findEntityByname(name, array) { @@ -632,7 +676,9 @@ export default { if (this.$refs[this.element.propValue.id]) { this.timeMachine = setTimeout(() => { if (index === this.changeIndex) { - this.$refs[this.element.propValue.id].chartResize() + this.chart.isPlugin + ? this.$refs[this.element.propValue.id].callPluginInner({ methodName: 'chartResize' }) + : this.$refs[this.element.propValue.id].chartResize() } this.destroyTimeMachine() }, 50) diff --git a/frontend/src/components/canvas/store/copy.js b/frontend/src/components/canvas/store/copy.js index 3b6f34f511..f8bcfa22c7 100644 --- a/frontend/src/components/canvas/store/copy.js +++ b/frontend/src/components/canvas/store/copy.js @@ -47,7 +47,7 @@ export default { // 如果是用户视图 测先进行底层复制 if (data.type === 'view') { - chartCopy(data.propValue.viewId).then(res => { + chartCopy(data.propValue.viewId, state.panel.panelInfo.id).then(res => { const newView = deepCopy(data) newView.id = uuid.v1() newView.propValue.viewId = res.data diff --git a/frontend/src/components/widget/serviceImpl/TimeDateRangeServiceImpl.js b/frontend/src/components/widget/serviceImpl/TimeDateRangeServiceImpl.js index c078919a9e..d06b70a722 100644 --- a/frontend/src/components/widget/serviceImpl/TimeDateRangeServiceImpl.js +++ b/frontend/src/components/widget/serviceImpl/TimeDateRangeServiceImpl.js @@ -227,7 +227,7 @@ class TimeDateRangeServiceImpl extends WidgetService { } getParam(element) { let timeArr = [] - if (element.options.attrs.default.isDynamic) { + if (element.options.attrs.default && element.options.attrs.default.isDynamic) { let value = this.dynamicDateFormNow(element) value = this.formatFilterValue(value) timeArr = this.formatValues(value, element) diff --git a/frontend/src/components/widget/serviceImpl/TimeDateServiceImpl.js b/frontend/src/components/widget/serviceImpl/TimeDateServiceImpl.js index 8e5024cc45..6dfba9a4a4 100644 --- a/frontend/src/components/widget/serviceImpl/TimeDateServiceImpl.js +++ b/frontend/src/components/widget/serviceImpl/TimeDateServiceImpl.js @@ -157,7 +157,7 @@ class TimeDateServiceImpl extends WidgetService { } getParam(element) { let timeArr = [] - if (element.options.attrs.default.isDynamic) { + if (element.options.attrs.default && element.options.attrs.default.isDynamic) { let value = this.dynamicDateFormNow(element) value = this.formatFilterValue(value) timeArr = this.formatValues(value, element) diff --git a/frontend/src/components/widget/serviceImpl/TimeMonthServiceImpl.js b/frontend/src/components/widget/serviceImpl/TimeMonthServiceImpl.js index 7471c381c4..53f8c277f6 100644 --- a/frontend/src/components/widget/serviceImpl/TimeMonthServiceImpl.js +++ b/frontend/src/components/widget/serviceImpl/TimeMonthServiceImpl.js @@ -123,7 +123,7 @@ class TimeMonthServiceImpl extends WidgetService { } getParam(element) { let timeArr = [] - if (element.options.attrs.default.isDynamic) { + if (element.options.attrs.default && element.options.attrs.default.isDynamic) { let value = this.dynamicDateFormNow(element) value = this.formatFilterValue(value) timeArr = this.formatValues(value, element) diff --git a/frontend/src/components/widget/serviceImpl/TimeYearServiceImpl.js b/frontend/src/components/widget/serviceImpl/TimeYearServiceImpl.js index 2ae0a78234..67ce9ec172 100644 --- a/frontend/src/components/widget/serviceImpl/TimeYearServiceImpl.js +++ b/frontend/src/components/widget/serviceImpl/TimeYearServiceImpl.js @@ -114,7 +114,7 @@ class TimeYearServiceImpl extends WidgetService { } getParam(element) { let timeArr = [] - if (element.options.attrs.default.isDynamic) { + if (element.options.attrs.default && element.options.attrs.default.isDynamic) { let value = this.dynamicDateFormNow(element) value = this.formatFilterValue(value) timeArr = this.formatValues(value, element) diff --git a/frontend/src/icons/svg/buddle-map.svg b/frontend/src/icons/svg/buddle-map.svg new file mode 100644 index 0000000000..a56a4cf8c7 --- /dev/null +++ b/frontend/src/icons/svg/buddle-map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/icons/svg/table-normal.svg b/frontend/src/icons/svg/table-normal.svg index 9ca48cc2c7..6e3ca6438f 100644 --- a/frontend/src/icons/svg/table-normal.svg +++ b/frontend/src/icons/svg/table-normal.svg @@ -1 +1 @@ - + diff --git a/frontend/src/icons/svg/table-pivot.svg b/frontend/src/icons/svg/table-pivot.svg new file mode 100644 index 0000000000..9ca48cc2c7 --- /dev/null +++ b/frontend/src/icons/svg/table-pivot.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 708081a2f1..a298b63c1e 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1020,7 +1020,16 @@ export default { table_config: 'Table Config', table_column_width_config: 'Column Width', table_column_adapt: 'Adapt', - table_column_custom: 'Custom' + table_column_custom: 'Custom', + chart_table_pivot: 'Pivot Table', + table_pivot_row: 'Data Row', + field_error_tips: 'This field is changed(Include dimension、quota,field type,deleted),please edit again.', + table_border_color: 'Border Color', + table_header_align: 'Header Align', + table_item_align: 'Body Align', + table_align_left: 'Left', + table_align_center: 'Center', + table_align_right: 'Right' }, dataset: { sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default', @@ -1577,16 +1586,17 @@ export default { }, auth: { - authConfig: 'Auth Config', + authConfig: 'Configure Permissions By User', + sourceConfig: 'Configure Permissions By Source', authQuickConfig: 'Auth Quick Config', dept: 'Dept', role: 'Role', user: 'User', - linkAuth: 'Datasource Permissions', - datasetAuth: 'Dataset Permissions', - chartAuth: 'Chart Permissions', - panelAuth: 'Dashboard Permissions', - menuAuth: 'Menu and operation permission', + linkAuth: 'Datasource', + datasetAuth: 'Dataset', + chartAuth: 'Chart', + panelAuth: 'Panel', + menuAuth: 'Menu And Operation', deptHead: 'All Dept', roleHead: 'All Role', userHead: 'All User', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index fb9592c5ef..8c320c6a3a 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1020,7 +1020,16 @@ export default { table_config: '表格配置', table_column_width_config: '列寬調整', table_column_adapt: '自適應', - table_column_custom: '自定義' + table_column_custom: '自定義', + chart_table_pivot: '透視表', + table_pivot_row: '數據行', + field_error_tips: '該字段所對應的數據集原始字段發生變更(包括維度、指標,字段類型,字段被刪除等),建議重新編輯', + table_border_color: '邊框顏色', + table_header_align: '表頭對齊方式', + table_item_align: '表格對齊方式', + table_align_left: '左對齊', + table_align_center: '居中', + table_align_right: '右對齊' }, dataset: { sheet_warn: '有多個 Sheet 頁,默認抽取第一個', @@ -1586,16 +1595,17 @@ export default { }, auth: { - authConfig: '權限配置', + authConfig: '按用户配置權限', + sourceConfig: '按资源配置權限', authQuickConfig: '權限快捷配置', dept: '組織', role: '角色', user: '用戶', - linkAuth: '數據源權限', - datasetAuth: '數據集權限', - chartAuth: '視圖權限', - panelAuth: '儀錶闆權限', - menuAuth: '菜單和操作權限', + linkAuth: '數據源', + datasetAuth: '數據集', + chartAuth: '視圖', + panelAuth: '儀錶闆', + menuAuth: '菜單和操作', deptHead: '所有組織', roleHead: '所有角色', userHead: '所有用戶', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 6db0149988..71a082b6fd 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1023,7 +1023,16 @@ export default { table_config: '表格配置', table_column_width_config: '列宽调整', table_column_adapt: '自适应', - table_column_custom: '自定义' + table_column_custom: '自定义', + chart_table_pivot: '透视表', + table_pivot_row: '数据行', + field_error_tips: '该字段所对应的数据集原始字段发生变更(包括维度、指标,字段类型,字段被删除等),建议重新编辑', + table_border_color: '边框颜色', + table_header_align: '表头对齐方式', + table_item_align: '表格对齐方式', + table_align_left: '左对齐', + table_align_center: '居中', + table_align_right: '右对齐' }, dataset: { sheet_warn: '有多个 Sheet 页,默认抽取第一个', @@ -1595,16 +1604,17 @@ export default { }, auth: { - authConfig: '权限配置', + authConfig: '按用户配置权限', + sourceConfig: '按资源配置权限', authQuickConfig: '权限快捷配置', dept: '组织', role: '角色', user: '用户', - linkAuth: '数据源权限', - datasetAuth: '数据集权限', - chartAuth: '视图权限', - panelAuth: '仪表板权限', - menuAuth: '菜单和操作权限', + linkAuth: '数据源', + datasetAuth: '数据集', + chartAuth: '视图', + panelAuth: '仪表板', + menuAuth: '菜单和操作', deptHead: '所有组织', roleHead: '所有角色', userHead: '所有用户', diff --git a/frontend/src/main.js b/frontend/src/main.js index 9f8248118f..f4272a1bfb 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -24,9 +24,11 @@ import DeComplexSelect from '@/components/business/condition-table/DeComplexSele import '@/components/canvas/custom-component' // 注册自定义组件 import '@/utils/DateUtil' +import draggable from 'vuedraggable' Vue.config.productionTip = false Vue.use(VueClipboard) Vue.use(widgets) +Vue.component('draggable', draggable) Vue.prototype.$api = api import * as echarts from 'echarts' diff --git a/frontend/src/utils/request.js b/frontend/src/utils/request.js index fa250e5cad..dc79cca838 100644 --- a/frontend/src/utils/request.js +++ b/frontend/src/utils/request.js @@ -14,7 +14,7 @@ import Cookies from 'js-cookie' const getTimeOut = () => { let time = 10 - const url = '/system/requestTimeOut' + const url = process.env.VUE_APP_BASE_API + 'system/requestTimeOut' const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr.readyState === 4 && xhr.status === 200) { diff --git a/frontend/src/views/chart/chart/chart.js b/frontend/src/views/chart/chart/chart.js index 9356fd684b..df770bd6e8 100644 --- a/frontend/src/views/chart/chart/chart.js +++ b/frontend/src/views/chart/chart/chart.js @@ -2,12 +2,13 @@ export const DEFAULT_COLOR_CASE = { value: 'default', colors: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'], alpha: 100, - tableHeaderBgColor: '#4e81bb', - tableItemBgColor: '#c6d9f0', + tableHeaderBgColor: '#e1eaff', + tableItemBgColor: '#ffffff', tableFontColor: '#000000', tableStripe: true, dimensionColor: '#000000', - quotaColor: '#000000' + quotaColor: '#000000', + tableBorderColor: '#cfdaf4' } export const DEFAULT_SIZE = { barDefault: true, @@ -31,8 +32,10 @@ export const DEFAULT_SIZE = { tableTitleHeight: 36, tableItemHeight: 36, tablePageSize: '20', - tableColumnMode: 'adapt', + tableColumnMode: 'custom', tableColumnWidth: 100, + tableHeaderAlign: 'left', + tableItemAlign: 'right', gaugeMin: 0, gaugeMax: 100, gaugeStartAngle: 225, diff --git a/frontend/src/views/chart/chart/common/common_table.js b/frontend/src/views/chart/chart/common/common_table.js index 28a9fef32d..4ffed26eeb 100644 --- a/frontend/src/views/chart/chart/common/common_table.js +++ b/frontend/src/views/chart/chart/common/common_table.js @@ -2,26 +2,81 @@ import { hexColorToRGBA } from '@/views/chart/chart/util' import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '@/views/chart/chart/chart' export function getCustomTheme(chart) { + const headerColor = hexColorToRGBA(DEFAULT_COLOR_CASE.tableHeaderBgColor, DEFAULT_COLOR_CASE.alpha) + const itemColor = hexColorToRGBA(DEFAULT_COLOR_CASE.tableItemBgColor, DEFAULT_COLOR_CASE.alpha) + const borderColor = hexColorToRGBA(DEFAULT_COLOR_CASE.tableBorderColor, DEFAULT_COLOR_CASE.alpha) + const headerAlign = DEFAULT_SIZE.tableHeaderAlign + const itemAlign = DEFAULT_SIZE.tableItemAlign + const theme = { background: { color: '#00000000' }, - colCell: { + splitLine: { + horizontalBorderColor: borderColor, + verticalBorderColor: borderColor + }, + cornerCell: { cell: { - backgroundColor: hexColorToRGBA(DEFAULT_COLOR_CASE.tableHeaderBgColor, DEFAULT_COLOR_CASE.alpha) + backgroundColor: headerColor, + horizontalBorderColor: borderColor, + verticalBorderColor: borderColor + }, + text: { + fill: DEFAULT_COLOR_CASE.tableFontColor, + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign }, bolderText: { fill: DEFAULT_COLOR_CASE.tableFontColor, - fontSize: DEFAULT_SIZE.tableTitleFontSize + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign + } + }, + rowCell: { + cell: { + backgroundColor: headerColor, + horizontalBorderColor: borderColor, + verticalBorderColor: borderColor + }, + text: { + fill: DEFAULT_COLOR_CASE.tableFontColor, + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign + }, + bolderText: { + fill: DEFAULT_COLOR_CASE.tableFontColor, + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign + } + }, + colCell: { + cell: { + backgroundColor: headerColor, + horizontalBorderColor: borderColor, + verticalBorderColor: borderColor + }, + text: { + fill: DEFAULT_COLOR_CASE.tableFontColor, + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign + }, + bolderText: { + fill: DEFAULT_COLOR_CASE.tableFontColor, + fontSize: DEFAULT_SIZE.tableTitleFontSize, + textAlign: headerAlign } }, dataCell: { cell: { - backgroundColor: hexColorToRGBA(DEFAULT_COLOR_CASE.tableItemBgColor, DEFAULT_COLOR_CASE.alpha) + backgroundColor: itemColor, + horizontalBorderColor: borderColor, + verticalBorderColor: borderColor }, text: { fill: DEFAULT_COLOR_CASE.tableFontColor, - fontSize: DEFAULT_SIZE.tableItemFontSize + fontSize: DEFAULT_SIZE.tableItemFontSize, + textAlign: itemAlign } } } @@ -32,16 +87,58 @@ export function getCustomTheme(chart) { // color if (customAttr.color) { const c = JSON.parse(JSON.stringify(customAttr.color)) - theme.colCell.cell.backgroundColor = hexColorToRGBA(c.tableHeaderBgColor, c.alpha) + const h_c = hexColorToRGBA(c.tableHeaderBgColor, c.alpha) + const i_c = hexColorToRGBA(c.tableItemBgColor, c.alpha) + const b_c = c.tableBorderColor ? hexColorToRGBA(c.tableBorderColor, c.alpha) : hexColorToRGBA(DEFAULT_COLOR_CASE.tableBorderColor, c.alpha) + theme.splitLine.horizontalBorderColor = b_c + theme.splitLine.verticalBorderColor = b_c + + theme.cornerCell.cell.backgroundColor = h_c + theme.cornerCell.cell.horizontalBorderColor = b_c + theme.cornerCell.cell.verticalBorderColor = b_c + theme.cornerCell.bolderText.fill = c.tableFontColor + theme.cornerCell.text.fill = c.tableFontColor + + theme.rowCell.cell.backgroundColor = h_c + theme.rowCell.cell.horizontalBorderColor = b_c + theme.rowCell.cell.verticalBorderColor = b_c + theme.rowCell.bolderText.fill = c.tableFontColor + theme.rowCell.text.fill = c.tableFontColor + + theme.colCell.cell.backgroundColor = h_c + theme.colCell.cell.horizontalBorderColor = b_c + theme.colCell.cell.verticalBorderColor = b_c theme.colCell.bolderText.fill = c.tableFontColor - theme.dataCell.cell.backgroundColor = hexColorToRGBA(c.tableItemBgColor, c.alpha) + theme.colCell.text.fill = c.tableFontColor + + theme.dataCell.cell.backgroundColor = i_c + theme.dataCell.cell.horizontalBorderColor = b_c + theme.dataCell.cell.verticalBorderColor = b_c theme.dataCell.text.fill = c.tableFontColor } // size if (customAttr.size) { const s = JSON.parse(JSON.stringify(customAttr.size)) + const h_a = s.tableHeaderAlign ? s.tableHeaderAlign : DEFAULT_SIZE.tableHeaderAlign + const i_a = s.tableItemAlign ? s.tableItemAlign : DEFAULT_SIZE.tableItemAlign + + theme.cornerCell.bolderText.fontSize = parseInt(s.tableTitleFontSize) + theme.cornerCell.bolderText.textAlign = h_a + theme.cornerCell.text.fontSize = parseInt(s.tableTitleFontSize) + theme.cornerCell.text.textAlign = h_a + + theme.rowCell.bolderText.fontSize = parseInt(s.tableTitleFontSize) + theme.rowCell.bolderText.textAlign = h_a + theme.rowCell.text.fontSize = parseInt(s.tableTitleFontSize) + theme.rowCell.text.textAlign = h_a + theme.colCell.bolderText.fontSize = parseInt(s.tableTitleFontSize) + theme.colCell.bolderText.textAlign = h_a + theme.colCell.text.fontSize = parseInt(s.tableTitleFontSize) + theme.colCell.text.textAlign = h_a + theme.dataCell.text.fontSize = parseInt(s.tableItemFontSize) + theme.dataCell.text.textAlign = i_a } } @@ -62,7 +159,7 @@ export function getSize(chart) { size.cellCfg = { height: s.tableItemHeight } - if (!s.tableColumnMode || s.tableColumnMode === 'adapt') { + if (s.tableColumnMode && s.tableColumnMode === 'adapt') { delete size.cellCfg.width size.layoutWidthType = 'compact' } else { diff --git a/frontend/src/views/chart/chart/table/table-info.js b/frontend/src/views/chart/chart/table/table-info.js index 6c0875653c..d5a6f96938 100644 --- a/frontend/src/views/chart/chart/table/table-info.js +++ b/frontend/src/views/chart/chart/table/table-info.js @@ -1,10 +1,10 @@ -import { TableSheet, S2Event } from '@antv/s2' +import { TableSheet, S2Event, PivotSheet } from '@antv/s2' import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table' export function baseTableInfo(s2, container, chart, action, tableData) { const containerDom = document.getElementById(container) - // data + // fields const fields = chart.data.fields if (!fields || fields.length === 0) { if (s2) { @@ -102,7 +102,7 @@ export function baseTableInfo(s2, container, chart, action, tableData) { export function baseTableNormal(s2, container, chart, action, tableData) { const containerDom = document.getElementById(container) - // data + // fields const fields = chart.data.fields if (!fields || fields.length === 0) { if (s2) { @@ -190,3 +190,111 @@ export function baseTableNormal(s2, container, chart, action, tableData) { return s2 } + +export function baseTablePivot(s2, container, chart, action, tableData) { + const containerDom = document.getElementById(container) + + // row and column + const columnFields = JSON.parse(chart.xaxis) + const rowFields = JSON.parse(chart.xaxisExt) + const valueFields = JSON.parse(chart.yaxis) + const c = []; const r = []; const v = [] + columnFields.forEach(ele => { + c.push(ele.dataeaseName) + }) + rowFields.forEach(ele => { + r.push(ele.dataeaseName) + }) + valueFields.forEach(ele => { + v.push(ele.dataeaseName) + }) + + // fields + const fields = chart.data.fields + if (!fields || fields.length === 0) { + if (s2) { + s2.destroy() + } + return + } + + const columns = [] + const meta = [] + + // add drill list + if (chart.drill) { + const drillFields = JSON.parse(chart.drillFields) + const drillField = drillFields[chart.drillFilters.length] + + const drillFilters = JSON.parse(JSON.stringify(chart.drillFilters)) + const drillExp = drillFilters[drillFilters.length - 1].datasetTableField + + // 移除所有下钻字段 + const removeField = [] + for (let i = 0; i < chart.drillFilters.length; i++) { + const ele = chart.drillFilters[i].datasetTableField + removeField.push(ele.dataeaseName) + } + + // build field + fields.forEach(ele => { + if (removeField.indexOf(ele.dataeaseName) < 0) { + // 用下钻字段替换当前字段 + if (drillExp.dataeaseName === ele.dataeaseName) { + columns.push(drillField.dataeaseName) + meta.push({ + field: drillField.dataeaseName, + name: drillField.name + }) + } else { + columns.push(ele.dataeaseName) + meta.push({ + field: ele.dataeaseName, + name: ele.name + }) + } + } + }) + } else { + fields.forEach(ele => { + columns.push(ele.dataeaseName) + meta.push({ + field: ele.dataeaseName, + name: ele.name + }) + }) + } + + // data config + const s2DataConfig = { + fields: { + rows: r, + columns: c, + values: v + }, + meta: meta, + data: tableData + } + + // options + const s2Options = { + width: containerDom.offsetWidth, + height: containerDom.offsetHeight, + style: getSize(chart) + } + + // 开始渲染 + if (s2) { + s2.destroy() + } + s2 = new PivotSheet(containerDom, s2DataConfig, s2Options) + + // click + s2.on(S2Event.DATA_CELL_CLICK, action) + + // theme + const customTheme = getCustomTheme(chart) + s2.setThemeCfg({ theme: customTheme }) + + return s2 +} diff --git a/frontend/src/views/chart/chart/util.js b/frontend/src/views/chart/chart/util.js index 1bec7413d9..4991c2a24b 100644 --- a/frontend/src/views/chart/chart/util.js +++ b/frontend/src/views/chart/chart/util.js @@ -26,3 +26,284 @@ export function digToHex(dig) { } return prefix.concat(num.toString(16).toUpperCase()) } + +export const TYPE_CONFIGS = [ + { + render: 'antv', + category: 'chart.chart_type_table', + value: 'table-normal', + title: 'chart.chart_table_normal', + icon: 'table-normal' + }, + { + render: 'antv', + category: 'chart.chart_type_table', + value: 'table-info', + title: 'chart.chart_table_info', + icon: 'table-info' + }, + { + render: 'antv', + category: 'chart.chart_type_table', + value: 'table-pivot', + title: 'chart.chart_table_pivot', + icon: 'table-pivot' + }, + + { + render: 'antv', + category: 'chart.chart_type_quota', + value: 'text', + title: 'chart.chart_card', + icon: 'text' + }, + { + render: 'antv', + category: 'chart.chart_type_quota', + value: 'gauge', + title: 'chart.chart_gauge', + icon: 'gauge' + }, + { + render: 'antv', + category: 'chart.chart_type_quota', + value: 'liquid', + title: 'chart.chart_liquid', + icon: 'liquid' + }, + + { + render: 'antv', + category: 'chart.chart_type_trend', + value: 'line', + title: 'chart.chart_line', + icon: 'line' + }, + { + render: 'antv', + category: 'chart.chart_type_trend', + value: 'line-stack', + title: 'chart.chart_line_stack', + icon: 'line-stack' + }, + + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'bar', + title: 'chart.chart_bar', + icon: 'bar' + }, + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'bar-stack', + title: 'chart.chart_bar_stack', + icon: 'bar-stack' + }, + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'waterfall', + title: 'chart.chart_waterfall', + icon: 'waterfall' + }, + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'bar-horizontal', + title: 'chart.chart_bar_horizontal', + icon: 'bar-horizontal' + }, + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'bar-stack-horizontal', + title: 'chart.chart_bar_stack_horizontal', + icon: 'bar-stack-horizontal' + }, + + { + render: 'antv', + category: 'chart.chart_type_distribute', + value: 'pie', + title: 'chart.chart_pie', + icon: 'pie' + }, + { + render: 'antv', + category: 'chart.chart_type_distribute', + value: 'pie-rose', + title: 'chart.chart_pie_rose', + icon: 'pie-rose' + }, + { + render: 'antv', + category: 'chart.chart_type_distribute', + value: 'radar', + title: 'chart.chart_radar', + icon: 'radar' + }, + { + render: 'antv', + category: 'chart.chart_type_distribute', + value: 'treemap', + title: 'chart.chart_treemap', + icon: 'treemap' + }, + { + render: 'antv', + category: 'chart.chart_type_distribute', + value: 'word-cloud', + title: 'chart.chart_word_cloud', + icon: 'word-cloud' + }, + + { + render: 'antv', + category: 'chart.chart_type_relation', + value: 'scatter', + title: 'chart.chart_scatter', + icon: 'scatter' + }, + { + render: 'antv', + category: 'chart.chart_type_relation', + value: 'funnel', + title: 'chart.chart_funnel', + icon: 'funnel' + }, + /* 下面是echarts图表类型 */ + { + render: 'echarts', + category: 'chart.chart_type_table', + value: 'table-normal', + title: 'chart.chart_table_normal', + icon: 'table-normal' + }, + { + render: 'echarts', + category: 'chart.chart_type_table', + value: 'table-info', + title: 'chart.chart_table_info', + icon: 'table-info' + }, + + { + render: 'echarts', + category: 'chart.chart_type_quota', + value: 'text', + title: 'chart.chart_card', + icon: 'text' + }, + { + render: 'echarts', + category: 'chart.chart_type_quota', + value: 'gauge', + title: 'chart.chart_gauge', + icon: 'gauge' + }, + + { + render: 'echarts', + category: 'chart.chart_type_trend', + value: 'line', + title: 'chart.chart_line', + icon: 'line' + }, + { + render: 'echarts', + category: 'chart.chart_type_trend', + value: 'line-stack', + title: 'chart.chart_line_stack', + icon: 'line-stack' + }, + { + render: 'echarts', + category: 'chart.chart_type_trend', + value: 'chart-mix', + title: 'chart.chart_mix', + icon: 'chart-mix' + }, + + { + render: 'echarts', + category: 'chart.chart_type_compare', + value: 'bar', + title: 'chart.chart_bar', + icon: 'bar' + }, + { + render: 'echarts', + category: 'chart.chart_type_compare', + value: 'bar-stack', + title: 'chart.chart_bar_stack', + icon: 'bar-stack' + }, + { + render: 'echarts', + category: 'chart.chart_type_compare', + value: 'bar-horizontal', + title: 'chart.chart_bar_horizontal', + icon: 'bar-horizontal' + }, + { + render: 'echarts', + category: 'chart.chart_type_compare', + value: 'bar-stack-horizontal', + title: 'chart.chart_bar_stack_horizontal', + icon: 'bar-stack-horizontal' + }, + + { + render: 'echarts', + category: 'chart.chart_type_distribute', + value: 'pie', + title: 'chart.chart_pie', + icon: 'pie' + }, + { + render: 'echarts', + category: 'chart.chart_type_distribute', + value: 'pie-rose', + title: 'chart.chart_pie_rose', + icon: 'pie-rose' + }, + { + render: 'echarts', + category: 'chart.chart_type_distribute', + value: 'radar', + title: 'chart.chart_radar', + icon: 'radar' + }, + { + render: 'echarts', + category: 'chart.chart_type_distribute', + value: 'treemap', + title: 'chart.chart_treemap', + icon: 'treemap' + }, + + { + render: 'echarts', + category: 'chart.chart_type_relation', + value: 'scatter', + title: 'chart.chart_scatter', + icon: 'scatter' + }, + { + render: 'echarts', + category: 'chart.chart_type_relation', + value: 'funnel', + title: 'chart.chart_funnel', + icon: 'funnel' + }, + + { + render: 'echarts', + category: 'chart.chart_type_space', + value: 'map', + title: 'chart.chart_map', + icon: 'map' + } +] diff --git a/frontend/src/views/chart/components/ChartComponentS2.vue b/frontend/src/views/chart/components/ChartComponentS2.vue index 0b9f2d4490..e4b4b3b1fd 100644 --- a/frontend/src/views/chart/components/ChartComponentS2.vue +++ b/frontend/src/views/chart/components/ChartComponentS2.vue @@ -4,9 +4,10 @@

{{ chart.title }}

-
+
+
{{ $t('chart.total') }} @@ -34,7 +35,7 @@ import { uuid } from 'vue-uuid' import ViewTrackBar from '@/components/canvas/components/Editor/ViewTrackBar' import { hexColorToRGBA } from '@/views/chart/chart/util' -import { baseTableInfo, baseTableNormal } from '@/views/chart/chart/table/table-info' +import { baseTableInfo, baseTableNormal, baseTablePivot } from '@/views/chart/chart/table/table-info' export default { name: 'ChartComponentS2', @@ -134,7 +135,7 @@ export default { methods: { initData() { let datas = [] - if (this.chart.data) { + if (this.chart.data && this.chart.data.fields) { 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 : 20) @@ -189,6 +190,8 @@ export default { this.myChart = baseTableInfo(this.myChart, this.chartId, chart, this.antVAction, this.tableData) } else if (chart.type === 'table-normal') { this.myChart = baseTableNormal(this.myChart, this.chartId, chart, this.antVAction, this.tableData) + } else if (chart.type === 'table-pivot') { + this.myChart = baseTablePivot(this.myChart, this.chartId, chart, this.antVAction, this.tableData) } else { if (this.myChart) { this.antVRenderStatus = false @@ -338,6 +341,7 @@ export default { if (this.$refs.title) { const titleHeight = this.$refs.title.offsetHeight this.chartHeight = (currentHeight - titleHeight) + 'px' + this.$refs.tableContainer.style.height = this.chartHeight } } }) diff --git a/frontend/src/views/chart/components/component-style/BackgroundColorSelector.vue b/frontend/src/views/chart/components/component-style/BackgroundColorSelector.vue index 3ee96ded4d..d51a1ed91c 100644 --- a/frontend/src/views/chart/components/component-style/BackgroundColorSelector.vue +++ b/frontend/src/views/chart/components/component-style/BackgroundColorSelector.vue @@ -1,7 +1,7 @@