diff --git a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java index 2d60576759..a68673c3c1 100644 --- a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java @@ -1,6 +1,5 @@ package io.dataease.auth.filter; -import cn.hutool.core.util.URLUtil; import com.auth0.jwt.algorithms.Algorithm; import io.dataease.auth.entity.ASKToken; import io.dataease.auth.entity.JWTToken; @@ -24,10 +23,8 @@ import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.nio.charset.Charset; public class JWTFilter extends BasicHttpAuthenticationFilter { @@ -161,18 +158,4 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { httpServletResponse.setHeader("authentication-status", "login_expire"); } - @Override - protected boolean onAccessDenied(ServletRequest req, ServletResponse res, Object mappedValue) throws Exception { - HttpServletResponse response = (HttpServletResponse) res; - HttpServletRequest request = (HttpServletRequest) req; - String requestURI = request.getRequestURI(); - String msg = requestURI + " has been denied"; - String encode = URLUtil.encode(msg, Charset.forName("UTF-8")); - Cookie cookie_error = new Cookie("onAccessDeniedMsg", encode); - cookie_error.setPath("/"); - response.addCookie(cookie_error); - response.sendRedirect("/"); - return false; - } - } 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 28bb812286..dbe2e68035 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java @@ -14,6 +14,7 @@ import io.dataease.dto.PermissionProxy; import io.dataease.dto.authModel.VAuthModelDTO; import io.dataease.dto.panel.PanelExport2App; import io.dataease.dto.panel.PanelGroupDTO; +import io.dataease.plugins.common.base.domain.PanelGroup; import io.dataease.service.panel.PanelGroupService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -50,6 +51,12 @@ public class PanelGroupController { return panelGroupService.tree(request); } + @ApiOperation("查询当前用户仪表板") + @GetMapping("/list") + public List list() { + return panelGroupService.list(); + } + @ApiOperation("默认树") @PostMapping("/defaultTree") public List defaultTree(@RequestBody PanelGroupRequest request) { diff --git a/backend/src/main/java/io/dataease/controller/sys/RelationController.java b/backend/src/main/java/io/dataease/controller/sys/RelationController.java new file mode 100644 index 0000000000..df53bc7455 --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/sys/RelationController.java @@ -0,0 +1,53 @@ +package io.dataease.controller.sys; + +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.auth.annotation.DePermission; +import io.dataease.commons.constants.DePermissionType; +import io.dataease.commons.constants.ResourceAuthLevel; +import io.dataease.commons.utils.AuthUtils; +import io.dataease.dto.RelationDTO; +import io.dataease.service.sys.RelationService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author WiSoniC + * @date 2022年12月8日15:01:05 + */ +@Api(tags = "系统:血缘关系") +@ApiSupport(order = 230) +@RequestMapping("/api/relation") +@RestController +public class RelationController { + + @Resource + private RelationService relationService; + + @DePermission(type = DePermissionType.DATASOURCE, level = ResourceAuthLevel.DATASOURCE_LEVEL_USE,value = "datasourceId") + @ApiOperation("获取指定数据库的血源关系") + @GetMapping("/datasource/{datasourceId}") + public List getRelationForDatasource(@PathVariable String datasourceId) { + Long userId = AuthUtils.getUser().getUserId(); + return relationService.getRelationForDatasource(datasourceId, userId); + } + + @DePermission(type = DePermissionType.DATASET, level = ResourceAuthLevel.DATASET_LEVEL_USE,value = "datasetId") + @ApiOperation("获取指定数据集的血缘关系") + @GetMapping("/dataset/{datasetId}") + public RelationDTO getRelationForDataset(@PathVariable String datasetId) { + Long userId = AuthUtils.getUser().getUserId(); + return relationService.getRelationForDataset(datasetId, userId); + } + + @DePermission(type = DePermissionType.PANEL, level = ResourceAuthLevel.PANEL_LEVEL_VIEW,value = "panelId") + @ApiOperation("获取指定仪表板的血源关系") + @GetMapping("/panel/{panelId}") + public List getRelationForPanel(@PathVariable String panelId) { + Long userId = AuthUtils.getUser().getUserId(); + return relationService.getRelationForPanel(panelId, userId); + } +} diff --git a/backend/src/main/java/io/dataease/dto/RelationDTO.java b/backend/src/main/java/io/dataease/dto/RelationDTO.java new file mode 100644 index 0000000000..cb417f6f0f --- /dev/null +++ b/backend/src/main/java/io/dataease/dto/RelationDTO.java @@ -0,0 +1,26 @@ +package io.dataease.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author WiSoniC + * @date 2022年12月8日18:53:10 + */ +@Data +public class RelationDTO { + @ApiModelProperty("ID") + private String id; + @ApiModelProperty("名称") + private String name; + @ApiModelProperty("权限信息") + private String auths; + @ApiModelProperty("类型") + private String type; + @ApiModelProperty("被引用信息") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List subRelation; +} diff --git a/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml b/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml index c4d4d4ad46..8e5db11c37 100644 --- a/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml +++ b/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml @@ -8,14 +8,11 @@ - + SELECT chart_view.* + FROM chart_view + LEFT JOIN panel_view ON chart_view.id = panel_view.chart_view_id + WHERE panel_view.panel_id = #{panelId} - INSERT INTO chart_view_cache ( - 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from - ) SELECT - 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from from chart_view - WHERE - chart_view.id = #{id} + INSERT INTO chart_view_cache (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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time) + SELECT 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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time + from chart_view + WHERE chart_view.id = #{id} - INSERT INTO chart_view_cache ( - 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from - ) SELECT - #{newViewId} as 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from from chart_view_cache - WHERE - chart_view_cache.id = #{sourceViewId} + INSERT INTO chart_view_cache (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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time) + SELECT #{newViewId} as 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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time + from chart_view_cache + WHERE chart_view_cache.id = #{sourceViewId} - INSERT INTO chart_view_cache ( - 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from - ) SELECT - 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, - x_axis_ext, - y_axis, - y_axis_ext, - ext_stack, - ext_bubble, - custom_attr, - custom_style, - custom_filter, - drill_fields, - senior, - SNAPSHOT, - data_from from chart_view - WHERE - chart_view.scene_id = #{panelId} + INSERT INTO chart_view_cache (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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time) + SELECT 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, + x_axis_ext, + y_axis, + y_axis_ext, + ext_stack, + ext_bubble, + custom_attr, + custom_style, + custom_filter, + drill_fields, + senior, + SNAPSHOT, + data_from, + refresh_view_enable, + refresh_unit, + refresh_time + from chart_view + WHERE chart_view.scene_id = #{panelId} - SELECT * FROM chart_view - WHERE - id IN ( - SELECT - chart_view_id - FROM - panel_view - WHERE - panel_id = #{panelId} - ) + SELECT * + FROM chart_view + WHERE id IN (SELECT chart_view_id + FROM panel_view + WHERE panel_id = #{panelId}) @@ -480,10 +482,12 @@ #{viewId} - + - delete from chart_view_cache where id = #{viewId} - + delete + from chart_view_cache + where id = #{viewId} + UPDATE chart_view cv, @@ -514,7 +518,10 @@ cv.drill_fields = cve.drill_fields, cv.senior = cve.senior, cv.SNAPSHOT = cve.SNAPSHOT, - cv.data_from = cve.data_from + cv.data_from = cve.data_from, + cv.refresh_view_enable = cve.refresh_view_enable, + cv.refresh_unit = cve.refresh_unit, + cv.refresh_time = cve.refresh_time where cve.id = cv.id and cv.id in #{viewId} @@ -523,69 +530,75 @@ UPDATE chart_view_cache cv, - chart_view cve + chart_view cve SET cv.`name` = cve.`name`, - cv.title = cve.title, - cv.scene_id = cve.scene_id, - cv.table_id = cve.table_id, - cv.`type` = cve.`type`, - cv.render = cve.render, - cv.result_count = cve.result_count, - cv.result_mode = cve.result_mode, - cv.create_by = cve.create_by, - cv.create_time = cve.create_time, - cv.update_time = cve.update_time, - cv.style_priority = cve.style_priority, - cv.chart_type = cve.chart_type, - cv.is_plugin = cve.is_plugin, - cv.x_axis = cve.x_axis, - cv.x_axis_ext = cve.x_axis_ext, - cv.y_axis = cve.y_axis, - cv.y_axis_ext = cve.y_axis_ext, - cv.ext_stack = cve.ext_stack, - cv.ext_bubble = cve.ext_bubble, - cv.custom_attr = cve.custom_attr, - cv.custom_style = cve.custom_style, - cv.custom_filter = cve.custom_filter, - cv.drill_fields = cve.drill_fields, - cv.senior = cve.senior, - cv.SNAPSHOT = cve.SNAPSHOT, - cv.data_from = cve.data_from - where cve.id = cv.id and cv.id =#{viewId} + cv.title = cve.title, + cv.scene_id = cve.scene_id, + cv.table_id = cve.table_id, + cv.`type` = cve.`type`, + cv.render = cve.render, + cv.result_count = cve.result_count, + cv.result_mode = cve.result_mode, + cv.create_by = cve.create_by, + cv.create_time = cve.create_time, + cv.update_time = cve.update_time, + cv.style_priority = cve.style_priority, + cv.chart_type = cve.chart_type, + cv.is_plugin = cve.is_plugin, + cv.x_axis = cve.x_axis, + cv.x_axis_ext = cve.x_axis_ext, + cv.y_axis = cve.y_axis, + cv.y_axis_ext = cve.y_axis_ext, + cv.ext_stack = cve.ext_stack, + cv.ext_bubble = cve.ext_bubble, + cv.custom_attr = cve.custom_attr, + cv.custom_style = cve.custom_style, + cv.custom_filter = cve.custom_filter, + cv.drill_fields = cve.drill_fields, + cv.senior = cve.senior, + cv.SNAPSHOT = cve.SNAPSHOT, + cv.data_from = cve.data_from, + cv.refresh_view_enable = cve.refresh_view_enable, + cv.refresh_unit = cve.refresh_unit, + cv.refresh_time = cve.refresh_time + where cve.id = cv.id and cv.id =#{viewId} UPDATE chart_view_cache cve, - chart_view cv + chart_view cv SET cv.`name` = cve.`name`, - cv.title = cve.title, - cv.scene_id = cve.scene_id, - cv.table_id = cve.table_id, - cv.`type` = cve.`type`, - cv.render = cve.render, - cv.result_count = cve.result_count, - cv.result_mode = cve.result_mode, - cv.create_by = cve.create_by, - cv.create_time = cve.create_time, - cv.update_time = cve.update_time, - cv.style_priority = cve.style_priority, - cv.chart_type = cve.chart_type, - cv.is_plugin = cve.is_plugin, - cv.x_axis = cve.x_axis, - cv.x_axis_ext = cve.x_axis_ext, - cv.y_axis = cve.y_axis, - cv.y_axis_ext = cve.y_axis_ext, - cv.ext_stack = cve.ext_stack, - cv.ext_bubble = cve.ext_bubble, - cv.custom_attr = cve.custom_attr, - cv.custom_style = cve.custom_style, - cv.custom_filter = cve.custom_filter, - cv.drill_fields = cve.drill_fields, - cv.senior = cve.senior, - cv.SNAPSHOT = cve.SNAPSHOT, - cv.data_from = cve.data_from - where cve.id = cv.id and cv.id =#{viewId} + cv.title = cve.title, + cv.scene_id = cve.scene_id, + cv.table_id = cve.table_id, + cv.`type` = cve.`type`, + cv.render = cve.render, + cv.result_count = cve.result_count, + cv.result_mode = cve.result_mode, + cv.create_by = cve.create_by, + cv.create_time = cve.create_time, + cv.update_time = cve.update_time, + cv.style_priority = cve.style_priority, + cv.chart_type = cve.chart_type, + cv.is_plugin = cve.is_plugin, + cv.x_axis = cve.x_axis, + cv.x_axis_ext = cve.x_axis_ext, + cv.y_axis = cve.y_axis, + cv.y_axis_ext = cve.y_axis_ext, + cv.ext_stack = cve.ext_stack, + cv.ext_bubble = cve.ext_bubble, + cv.custom_attr = cve.custom_attr, + cv.custom_style = cve.custom_style, + cv.custom_filter = cve.custom_filter, + cv.drill_fields = cve.drill_fields, + cv.senior = cve.senior, + cv.SNAPSHOT = cve.SNAPSHOT, + cv.data_from = cve.data_from, + cv.refresh_view_enable = cve.refresh_view_enable, + cv.refresh_unit = cve.refresh_unit, + cv.refresh_time = cve.refresh_time + where cve.id = cv.id and cv.id =#{viewId} @@ -600,55 +613,49 @@ - INSERT INTO chart_view_field ( - id, - table_id, - chart_id, - origin_name, - `name`, - dataease_name, - group_type, - `type`, - `size`, - de_type, - de_type_format, - de_extract_type, - ext_field, - `checked`, - column_index, - last_sync_time - ) SELECT - uuid() AS id, - chart_view_field.table_id, - chart_view_field.pv_copy.chart_view_id AS chart_id, - chart_view_field.origin_name, - chart_view_field.`name`, - chart_view_field.dataease_name, - chart_view_field.group_type, - chart_view_field.`type`, - chart_view_field.`size`, - chart_view_field.de_type, - chart_view_field.de_type_format, - chart_view_field.de_extract_type, - chart_view_field.ext_field, - chart_view_field.`checked`, - chart_view_field.column_index, - chart_view_field.last_sync_time - FROM - ( - SELECT - panel_id, - copy_from_view, - chart_view_id - FROM - panel_view - WHERE - copy_id = #{copyId} - ) pv_copy - INNER JOIN chart_view_field ON chart_view_field.chart_id = pv_copy.copy_from_view + INSERT INTO chart_view_field (id, + table_id, + chart_id, + origin_name, + `name`, + dataease_name, + group_type, + `type`, + `size`, + de_type, + de_type_format, + de_extract_type, + ext_field, + `checked`, + column_index, + last_sync_time) + SELECT uuid() AS id, + chart_view_field.table_id, + chart_view_field.pv_copy.chart_view_id AS chart_id, + chart_view_field.origin_name, + chart_view_field.`name`, + chart_view_field.dataease_name, + chart_view_field.group_type, + chart_view_field.`type`, + chart_view_field.`size`, + chart_view_field.de_type, + chart_view_field.de_type_format, + chart_view_field.de_extract_type, + chart_view_field.ext_field, + chart_view_field.`checked`, + chart_view_field.column_index, + chart_view_field.last_sync_time + FROM (SELECT panel_id, + copy_from_view, + chart_view_id + FROM panel_view + WHERE copy_id = #{copyId}) pv_copy + INNER JOIN chart_view_field ON chart_view_field.chart_id = pv_copy.copy_from_view diff --git a/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.java b/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.java index 4c6684cbcd..9690db0954 100644 --- a/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.java +++ b/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.java @@ -1,6 +1,7 @@ package io.dataease.ext; import io.dataease.controller.request.dataset.DataSetTableRequest; +import io.dataease.dto.RelationDTO; import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.plugins.common.base.domain.DatasetTable; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ public interface ExtDataSetTableMapper { List findByTableIds(@Param("tableIds") List tableIds); + RelationDTO queryDatasetRelation(@Param("datasetId") String datasetId, @Param("userId")Long userId); + } diff --git a/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.xml b/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.xml index 38440ec0c7..b51d1e3d16 100644 --- a/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.xml +++ b/backend/src/main/java/io/dataease/ext/ExtDataSetTableMapper.xml @@ -156,4 +156,84 @@ #{item} + + diff --git a/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.java b/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.java index 18e91bf687..f3ca151aa7 100644 --- a/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.java +++ b/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.java @@ -1,6 +1,7 @@ package io.dataease.ext; import io.dataease.controller.request.DatasourceUnionRequest; +import io.dataease.dto.RelationDTO; import io.dataease.dto.DatasourceDTO; import io.dataease.ext.query.GridExample; import org.apache.ibatis.annotations.Param; @@ -19,5 +20,5 @@ public interface ExtDataSourceMapper { DatasourceDTO queryDetails(@Param("datasourceId") String datasourceId, @Param("userId") String userId); - + List queryDatasourceRelation(@Param("datasourceId") String datasourceId, @Param("userId")Long userId); } diff --git a/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.xml b/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.xml index 782da6288a..e20645682e 100644 --- a/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.xml +++ b/backend/src/main/java/io/dataease/ext/ExtDataSourceMapper.xml @@ -6,6 +6,17 @@ extends="io.dataease.plugins.common.base.mapper.DatasourceMapper.ResultMapWithBLOBs"> + + + + + + + + + + + - + diff --git a/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.java b/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.java index e75ce9a805..30dbcd2c75 100644 --- a/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.java +++ b/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.java @@ -1,7 +1,9 @@ package io.dataease.ext; import io.dataease.controller.request.panel.PanelGroupRequest; +import io.dataease.dto.RelationDTO; import io.dataease.dto.panel.PanelGroupDTO; +import io.dataease.plugins.common.base.domain.PanelGroup; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -28,6 +30,7 @@ public interface ExtPanelGroupMapper { List panelGroupInit(); + List queryPanelRelation(@Param("panelId") String panelId, @Param("userId") Long userId); - + List listPanelByUser(@Param("userId") long userId); } diff --git a/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.xml b/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.xml index 1354bc5b56..4c6343e5e3 100644 --- a/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.xml +++ b/backend/src/main/java/io/dataease/ext/ExtPanelGroupMapper.xml @@ -14,6 +14,18 @@ + + + + + + + + + + + + + select + ds.id, + ds.name, + ds_auth.auths, + 'link' `type`, + dt.id dt_id, + dt.name dt_name, + dt_auth.auths dt_auths, + if(dt.id is not null,'dataset',null) dt_type + from + panel_group pg + join + chart_view cv on cv.scene_id = pg.id + join + dataset_table dt on cv.table_id = dt.id + left join + ( + select + t_dt.id,group_concat(distinct sad.privilege_type) auths + from + dataset_table t_dt + left join sys_auth sa on sa.auth_source = t_dt.id + left join sys_auth_detail sad on sa.id = sad.auth_id + where + sa.auth_source_type = 'dataset' + and + sad.privilege_value = 1 + and + ( + ( + sa.auth_target_type = 'dept' + AND sa.auth_target in ( SELECT dept_id FROM sys_user WHERE user_id = #{userId,jdbcType=BIGINT} ) + ) + or + ( + sa.auth_target_type = 'user' + AND sa.auth_target = #{userId,jdbcType=BIGINT} + ) + or + ( + sa.auth_target_type = 'role' + AND sa.auth_target in ( SELECT role_id FROM sys_users_roles WHERE user_id = #{userId,jdbcType=BIGINT} ) + ) + ) + group by sa.auth_source + ) dt_auth on dt.id = dt_auth.id + join datasource ds on dt.data_source_id = ds.id + left join + ( + select + t_pg.id,group_concat(distinct sad.privilege_type) auths + from + panel_group t_pg + left join sys_auth sa on sa.auth_source = t_pg.id + left join sys_auth_detail sad on sa.id = sad.auth_id + where + sa.auth_source_type = 'link' + and + sad.privilege_value = 1 + and + ( + ( + sa.auth_target_type = 'dept' + AND sa.auth_target in ( SELECT dept_id FROM sys_user WHERE user_id = #{userId,jdbcType=BIGINT} ) + ) + OR + ( + sa.auth_target_type = 'user' + AND sa.auth_target = #{userId,jdbcType=BIGINT} + ) + OR + ( + sa.auth_target_type = 'role' + AND sa.auth_target in ( SELECT role_id FROM sys_users_roles WHERE user_id = #{userId,jdbcType=BIGINT} ) + ) + ) + group by sa.auth_source + ) ds_auth on ds_auth.id = ds.id + where pg.id=#{panelId,jdbcType=VARCHAR} + group by dt.id + + + 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 24f8b99a41..d06d88f47f 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -279,6 +279,12 @@ public class ChartViewService { if (result == null) { DataEaseException.throwException(Translator.get("i18n_chart_delete")); } + DatasetTable datasetTable = dataSetTableService.get(result.getTableId()); + if (ObjectUtils.isNotEmpty(datasetTable)) { + result.setDatasetMode(datasetTable.getMode()); + Datasource datasource = datasourceService.get(datasetTable.getDataSourceId()); + result.setDatasourceType(datasource != null ? datasource.getType() : null); + } return result; } catch (Exception e) { e.printStackTrace(); @@ -645,13 +651,23 @@ public class ChartViewService { // 直连明细表分页 Map mapAttr = gson.fromJson(view.getCustomAttr(), Map.class); Map mapSize = (Map) mapAttr.get("size"); - if (StringUtils.equalsIgnoreCase(view.getType(), "table-info") && table.getMode() == 0 && StringUtils.equalsIgnoreCase((String) mapSize.get("tablePageMode"), "page")) { - if (chartExtRequest.getGoPage() == null) { - chartExtRequest.setGoPage(1L); - } - if (chartExtRequest.getPageSize() == null) { - String pageSize = (String) mapSize.get("tablePageSize"); - chartExtRequest.setPageSize(Long.parseLong(pageSize)); + if (StringUtils.equalsIgnoreCase(view.getType(), "table-info") && table.getMode() == 0) { + if (StringUtils.equalsIgnoreCase((String) mapSize.get("tablePageMode"), "page")) { + if (chartExtRequest.getGoPage() == null) { + chartExtRequest.setGoPage(1L); + } + if (chartExtRequest.getPageSize() == null) { + String pageSize = (String) mapSize.get("tablePageSize"); + chartExtRequest.setPageSize(Math.min(Long.parseLong(pageSize), view.getResultCount().longValue())); + } + } else { + if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) { + chartExtRequest.setGoPage(1L); + chartExtRequest.setPageSize(view.getResultCount().longValue()); + } else { + chartExtRequest.setGoPage(null); + chartExtRequest.setPageSize(null); + } } } else { chartExtRequest.setGoPage(null); @@ -910,7 +926,13 @@ public class ChartViewService { String totalPageSql = null; PageInfo pageInfo = new PageInfo(); pageInfo.setGoPage(chartExtRequest.getGoPage()); - pageInfo.setPageSize(chartExtRequest.getPageSize()); + if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) { + if (StringUtils.equalsIgnoreCase(view.getType(), "table-info") && table.getMode() == 0) { + pageInfo.setPageSize(Math.min(view.getResultCount() - (chartExtRequest.getGoPage() - 1) * chartExtRequest.getPageSize(), chartExtRequest.getPageSize())); + } + } else { + pageInfo.setPageSize(chartExtRequest.getPageSize()); + } List detailFieldList = new ArrayList<>(); String detailFieldSql = null; diff --git a/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java b/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java index e720913b17..f2c03fcbdb 100644 --- a/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java +++ b/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java @@ -15,6 +15,9 @@ import java.util.*; import java.util.stream.Collectors; public class ChartDataBuild { + + private final static String format = "(%s)"; + // AntV public static Map transChartDataAntV(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, boolean isDrill) { Map map = new HashMap<>(); @@ -969,7 +972,7 @@ public class ChartDataBuild { Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> ArrayUtil.join(ArrayUtil.sub(item, 0, xEndIndex), "-de-", "(", ")"))); tableRow.forEach(row -> { - String key = xAxis.stream().map(x -> row.get(x.getDataeaseName()).toString()).collect(Collectors.joining("-de-", "(", ")")); + String key = xAxis.stream().map(x -> String.format(format, row.get(x.getDataeaseName()).toString())).collect(Collectors.joining("-de-")); List detailFieldValueList = groupDataList.get(key); List> detailValueMapList = detailFieldValueList.stream().map((detailArr -> { Map temp = new HashMap<>(); 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 947073c9dd..64f48249e3 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java @@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import io.dataease.auth.annotation.DeCleaner; +import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.commons.constants.*; import io.dataease.commons.utils.*; import io.dataease.controller.request.authModel.VAuthModelRequest; @@ -151,6 +152,17 @@ public class PanelGroupService { return TreeUtils.mergeTree(panelGroupDTOList, "default_panel"); } + public List list() { + CurrentUserDto user = AuthUtils.getUser(); + if (user.getIsAdmin()) { + PanelGroupExample example = new PanelGroupExample(); + example.setOrderByClause("name"); + example.createCriteria().andNodeTypeEqualTo("panel"); + return panelGroupMapper.selectByExample(example); + } + return extPanelGroupMapper.listPanelByUser(user.getUserId()); + } + @DeCleaner(value = DePermissionType.PANEL, key = "pid") public String save(PanelGroupRequest request) { checkPanelName(request.getName(), request.getPid(), PanelConstants.OPT_TYPE_INSERT, null, request.getNodeType()); diff --git a/backend/src/main/java/io/dataease/service/sys/RelationService.java b/backend/src/main/java/io/dataease/service/sys/RelationService.java new file mode 100644 index 0000000000..b4d425fa84 --- /dev/null +++ b/backend/src/main/java/io/dataease/service/sys/RelationService.java @@ -0,0 +1,40 @@ +package io.dataease.service.sys; + +import io.dataease.dto.RelationDTO; +import io.dataease.ext.ExtDataSetTableMapper; +import io.dataease.ext.ExtDataSourceMapper; +import io.dataease.ext.ExtPanelGroupMapper; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author WiSoniC + * @date 2022年12月8日15:17:17 + */ +@Service +public class RelationService { + + @Resource + private ExtDataSourceMapper extDataSourceMapper; + + @Resource + private ExtDataSetTableMapper extDataSetTableMapper; + + @Resource + private ExtPanelGroupMapper extPanelGroupMapper; + + public List getRelationForDatasource(String datasourceId, Long userId) { + return extDataSourceMapper.queryDatasourceRelation(datasourceId, userId); + } + + public RelationDTO getRelationForDataset(String datasetId, Long userId) { + return extDataSetTableMapper.queryDatasetRelation(datasetId, userId); + } + + public List getRelationForPanel(String panelId, Long userId) { + return extPanelGroupMapper.queryPanelRelation(panelId, userId); + } + +} diff --git a/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java b/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java index 658c23aa91..978f11c73b 100644 --- a/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java +++ b/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java @@ -29,56 +29,56 @@ import java.util.stream.Collectors; @Service public class TemplateMarketService { - private final static String POSTS_API="/api/content/posts?page=0&size=2000"; - private final static String CATEGORIES_API="/api/content/categories"; + private final static String POSTS_API = "/api/content/posts?page=0&size=2000"; + private final static String CATEGORIES_API = "/api/content/categories"; @Resource private SystemParameterService systemParameterService; /** - * @Description Get template file from template market * @param templateUrl template url + * @Description Get template file from template market */ - public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl){ - if(StringUtils.isNotEmpty(templateUrl)){ + public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl) { + if (StringUtils.isNotEmpty(templateUrl)) { String sufUrl = systemParameterService.templateMarketInfo().getTemplateMarketUlr(); Gson gson = new Gson(); - String templateInfo = HttpClientUtil.get(sufUrl+templateUrl,null); + String templateInfo = HttpClientUtil.get(sufUrl + templateUrl, null); return gson.fromJson(templateInfo, PanelTemplateFileDTO.class); - }else{ + } else { return null; } } /** - * @Description Get info from template market content api * @param url content api url + * @Description Get info from template market content api */ - public String marketGet(String url,String accessKey){ + public String marketGet(String url, String accessKey) { HttpClientConfig config = new HttpClientConfig(); - config.addHeader("API-Authorization",accessKey); - return HttpClientUtil.get(url,config); + config.addHeader("API-Authorization", accessKey); + return HttpClientUtil.get(url, config); } - public MarketBaseResponse searchTemplate(TemplateMarketSearchRequest request){ - try{ + public MarketBaseResponse searchTemplate(TemplateMarketSearchRequest request) { + try { BasicInfo basicInfo = systemParameterService.templateMarketInfo(); - String result = marketGet(basicInfo.getTemplateMarketUlr()+POSTS_API,basicInfo.getTemplateAccessKey()); - List postsResult = JSONObject.parseObject(result).getJSONObject("data").getJSONArray("content").toJavaList(TemplateMarketDTO.class); - return new MarketBaseResponse(basicInfo.getTemplateMarketUlr(),postsResult); - }catch (Exception e){ + String result = marketGet(basicInfo.getTemplateMarketUlr() + POSTS_API, basicInfo.getTemplateAccessKey()); + List postsResult = JSONObject.parseObject(result).getJSONObject("data").getJSONArray("content").toJavaList(TemplateMarketDTO.class); + return new MarketBaseResponse(basicInfo.getTemplateMarketUlr(), postsResult); + } catch (Exception e) { DataEaseException.throwException(e); } return null; } - public List getCategories(){ + public List getCategories() { BasicInfo basicInfo = systemParameterService.templateMarketInfo(); - String resultStr = marketGet(basicInfo.getTemplateMarketUlr()+CATEGORIES_API,basicInfo.getTemplateAccessKey()); + String resultStr = marketGet(basicInfo.getTemplateMarketUlr() + CATEGORIES_API, basicInfo.getTemplateAccessKey()); List categories = JSONObject.parseObject(resultStr).getJSONArray("data").toJavaList(TemplateCategory.class); - if(CollectionUtils.isNotEmpty(categories)){ - return categories.stream().sorted(Comparator.comparing(TemplateCategory::getPriority)).map(TemplateCategory :: getName).collect(Collectors.toList()); - }else{ + if (CollectionUtils.isNotEmpty(categories)) { + return categories.stream().filter(item -> !"应用系列".equals(item.getName())).sorted(Comparator.comparing(TemplateCategory::getPriority)).map(TemplateCategory::getName).collect(Collectors.toList()); + } else { return null; } diff --git a/backend/src/main/resources/db/migration/V46__1.18.sql b/backend/src/main/resources/db/migration/V46__1.18.sql index 6d1a5fa29b..a6e13beab1 100644 --- a/backend/src/main/resources/db/migration/V46__1.18.sql +++ b/backend/src/main/resources/db/migration/V46__1.18.sql @@ -10,8 +10,25 @@ ALTER TABLE `sys_task` ADD COLUMN `status` tinyint(1) NULL DEFAULT 1 COMMENT '运行状态' AFTER `create_time`; -INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`) VALUES (1100, 1, 0, 1, '血缘关系', 'sys-relationship', 'system/relationship/index', 1002, 'sys-relationship', 'relationship', 0, 0, 0, 'relationship:read'); +INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, + `path`, `i_frame`, `cache`, `hidden`, `permission`) +VALUES (1100, 1, 0, 1, '血缘关系', 'sys-relationship', 'system/relationship/index', 1002, 'sys-relationship', + 'relationship', 0, 0, 0, 'relationship:read'); -UPDATE `sys_menu` SET `menu_sort` = 1003 WHERE (`menu_id` = 101); +UPDATE `sys_menu` +SET `menu_sort` = 1003 +WHERE (`menu_id` = 101); -UPDATE `my_plugin` SET `version` = '1.18.0' where `plugin_id` > 0; +UPDATE `my_plugin` +SET `version` = '1.18.0' +where `plugin_id` > 0; + +ALTER TABLE `chart_view` + ADD COLUMN `refresh_view_enable` tinyint(1) NULL DEFAULT 0 COMMENT '是否开启刷新' AFTER `view_fields`, +ADD COLUMN `refresh_unit` varchar(255) NULL DEFAULT 'minute' COMMENT '刷新时间单位' AFTER `refresh_view_enable`, +ADD COLUMN `refresh_time` int(13) NULL DEFAULT 5 COMMENT '刷新时间' AFTER `refresh_unit`; + +ALTER TABLE `chart_view_cache` + ADD COLUMN `refresh_view_enable` tinyint(1) NULL DEFAULT 0 COMMENT '是否开启刷新' AFTER `view_fields`, +ADD COLUMN `refresh_unit` varchar(255) NULL DEFAULT 'minute' COMMENT '刷新时间单位' AFTER `refresh_view_enable`, +ADD COLUMN `refresh_time` int(13) NULL DEFAULT 5 COMMENT '刷新时间' AFTER `refresh_unit`; diff --git a/frontend/src/components/canvas/components/editor/ComponentWrapper.vue b/frontend/src/components/canvas/components/editor/ComponentWrapper.vue index b12a130c2e..bba9a44403 100644 --- a/frontend/src/components/canvas/components/editor/ComponentWrapper.vue +++ b/frontend/src/components/canvas/components/editor/ComponentWrapper.vue @@ -279,7 +279,7 @@ export default { } else { return { ... - getStyle(style, ['top', 'left', 'width', 'height', 'rotate']), + getStyle(style, ['top', 'left', 'width', 'height', 'rotate']), position: 'relative' } } diff --git a/frontend/src/components/canvas/components/editor/EditBar.vue b/frontend/src/components/canvas/components/editor/EditBar.vue index 471c4186f2..7c7e833cc5 100644 --- a/frontend/src/components/canvas/components/editor/EditBar.vue +++ b/frontend/src/components/canvas/components/editor/EditBar.vue @@ -137,7 +137,7 @@ :target="curComponent.hyperlinks.openMode " :href="curComponent.hyperlinks.content " > - + @@ -496,19 +496,7 @@ export default { }, // 清除相同sourceViewId 的 联动条件 clearLinkage() { - this.componentData.forEach(item => { - if (item.linkageFilters && item.linkageFilters.length > 0) { - const newList = item.linkageFilters.filter(linkage => linkage.sourceViewId !== this.element.propValue.viewId) - item.linkageFilters.splice(0, item.linkageFilters.length) - // 重新push 可保证数组指针不变 可以watch到 - if (newList.length > 0) { - newList.forEach(newLinkage => { - item.linkageFilters.push(newLinkage) - }) - } - } - }) - bus.$emit('clear_panel_linkage', { viewId: this.element.propValue.viewId }) + this.$store.commit('clearViewLinkage', this.element.propValue.viewId) }, goFile() { this.$refs.files.click() diff --git a/frontend/src/components/canvas/customComponent/UserView.vue b/frontend/src/components/canvas/customComponent/UserView.vue index eab9fd0802..c21d6d056b 100644 --- a/frontend/src/components/canvas/customComponent/UserView.vue +++ b/frontend/src/components/canvas/customComponent/UserView.vue @@ -305,6 +305,7 @@ export default { }, data() { return { + innerRefreshTimer: null, mobileChartDetailsVisible: false, chartDetailsVisible: false, showChartInfo: {}, @@ -350,7 +351,7 @@ export default { }, computed: { - //首次加载且非编辑状态新复制的视图,使用外部filter + // 首次加载且非编辑状态新复制的视图,使用外部filter initLoad() { return !(this.isEdit && this.currentCanvasNewId.includes(this.element.id)) && this.isFirstLoad }, @@ -393,7 +394,7 @@ export default { return this.httpRequest.status && this.chart.type && this.chart.type === 'label' }, loadingFlag() { - return (this.canvasStyleData.refreshViewLoading || this.searchCount === 0) && this.requestStatus === 'waiting' + return (this.canvasStyleData.refreshViewLoading || (!this.innerRefreshTimer && this.searchCount === 0)) && this.requestStatus === 'waiting' }, panelInfo() { return this.$store.state.panel.panelInfo @@ -520,7 +521,8 @@ export default { }, // 监听外部计时器变化 searchCount: function(val1) { - if (val1 > 0 && this.requestStatus !== 'waiting') { + // 内部计时器启动 忽略外部计时器 + if (val1 > 0 && this.requestStatus !== 'waiting' && !this.innerRefreshTimer) { this.getData(this.element.propValue.viewId) } }, @@ -547,6 +549,7 @@ export default { }, beforeDestroy() { + this.innerRefreshTimer && clearInterval(this.innerRefreshTimer) bus.$off('plugin-chart-click', this.pluginChartClick) bus.$off('plugin-jump-click', this.pluginJumpClick) bus.$off('plugin-add-view-track-filter', this.pluginAddViewTrackFilter) @@ -566,6 +569,20 @@ export default { } }, methods: { + //编辑状态下 不启动刷新 + buildInnerRefreshTimer(refreshViewEnable = false, refreshUnit = 'minute', refreshTime = 5) { + if (this.editMode === 'preview' && !this.innerRefreshTimer && refreshViewEnable) { + this.innerRefreshTimer && clearInterval(this.innerRefreshTimer) + const timerRefreshTime = refreshUnit === 'second' ? refreshTime * 1000 : refreshTime * 60000 + this.innerRefreshTimer = setInterval(() => { + this.clearViewLinkage() + this.getData(this.element.propValue.viewId) + }, timerRefreshTime) + } + }, + clearViewLinkage() { + this.$store.commit('clearViewLinkage', this.element.propValue.viewId) + }, responseResetButton() { if (!this.cfilters?.length) { this.getData(this.element.propValue.viewId, false) @@ -741,6 +758,7 @@ export default { if (response.success) { this.chart = response.data this.view = response.data + this.buildInnerRefreshTimer(this.chart.refreshViewEnable, this.chart.refreshUnit, this.chart.refreshTime) this.$emit('fill-chart-2-parent', this.chart) this.getDataOnly(response.data, dataBroadcast) this.chart['position'] = this.inTab ? 'tab' : 'panel' @@ -1269,7 +1287,6 @@ export default { display: block !important; } - .mobile-dialog-css ::v-deep .el-dialog__headerbtn { top: 7px } diff --git a/frontend/src/components/deDrag/index.vue b/frontend/src/components/deDrag/index.vue index 18d983d94d..2591f61ad6 100644 --- a/frontend/src/components/deDrag/index.vue +++ b/frontend/src/components/deDrag/index.vue @@ -66,7 +66,7 @@ @mousedown.stop.prevent="handleDown(handlei, $event)" @touchstart.stop.prevent="handleTouchDown(handlei, $event)" > - +
- +
@@ -2170,31 +2170,31 @@ export default { } .de-drag-top { - left: 0; - top: 0; + left: 1px; + top: 1px; height: 12px; - width: 100%; + width: calc(100% - 2px); } .de-drag-right { - right: 0; - top: 0; + right: 1px; + top: 1px; width: 16px; - height: 100%; + height: calc(100% - 30px); } .de-drag-bottom { - left: 0; - bottom: 0; + left: 1px; + bottom: 1px; height: 12px; - width: 100%; + width: calc(100% - 2px); } .de-drag-left { - left: 0; - top: 0; + left: 1px; + top: 1px; width: 16px; - height: 100%; + height: calc(100% - 2px); } diff --git a/frontend/src/components/deIconPicker/deIconGroupPicker/index.vue b/frontend/src/components/deIconPicker/deIconGroupPicker/index.vue index 0de188ea20..bb80907527 100644 --- a/frontend/src/components/deIconPicker/deIconGroupPicker/index.vue +++ b/frontend/src/components/deIconPicker/deIconGroupPicker/index.vue @@ -217,7 +217,10 @@ export default { return '' } }, - options: {}, + options: { + type: Object, + default: () => {} + }, width: { type: Number, default() { diff --git a/frontend/src/components/deIconPicker/index.vue b/frontend/src/components/deIconPicker/index.vue index f47284928e..f6ac0ce3a0 100644 --- a/frontend/src/components/deIconPicker/index.vue +++ b/frontend/src/components/deIconPicker/index.vue @@ -180,7 +180,10 @@ export default { return '' } }, - options: {}, + options: { + type: Object, + default: () => {} + }, width: { type: Number, default() { diff --git a/frontend/src/components/widget/deWidget/DeTabs.vue b/frontend/src/components/widget/deWidget/DeTabs.vue index fa9c821dfc..23c51cb41c 100644 --- a/frontend/src/components/widget/deWidget/DeTabs.vue +++ b/frontend/src/components/widget/deWidget/DeTabs.vue @@ -640,7 +640,7 @@ export default { while (len--) { if (this.element.options.tabList[len].name === param.name) { this.element.options.tabList.splice(len, 1) - + this.$store.commit('deleteComponentsWithCanvasId', this.element.id + '-' + param.name) const activeIndex = (len - 1 + this.element.options.tabList.length) % this.element.options.tabList.length this.activeTabName = this.element.options.tabList[activeIndex].name } diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 0d1b11ca47..601aabdfed 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -931,6 +931,7 @@ export default { password_input_error: 'Original password input error' }, chart: { + chart_refresh_tips: 'View refresh setting takes precedence over panel refresh setting', '1-trend': 'trend', '2-state': 'State', '3-rank': 'Rank', @@ -1480,9 +1481,9 @@ export default { total_sort_desc: 'DESC', total_sort_field: 'Sort Field', empty_data_strategy: 'Empty Data Strategy', - break_line: 'Disconnection', + break_line: 'Keep', set_zero: 'Set Zero', - ignore_data: 'Ignore Data', + ignore_data: 'Hide Data', sub_dimension_tip: 'This field is required, and cannot be included in the type axis, you should choose non-group chart if you don\'t need it, or you will get unexpected chart.', drill_dimension_tip: 'Only fields in the dataset can be drilled', table_scroll_tip: 'The detail table is only effective when the pagination mode is "Drop-down".', @@ -1924,6 +1925,7 @@ export default { field_description: 'Field description', table_description: 'Table description', relational_database: 'Relational database', + data_warehouse_lake: 'Data Warehouse/Data Lake', non_relational_database: 'Non relational database', all: 'All', other: 'other', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 4641716985..86904cd527 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -930,6 +930,7 @@ export default { password_input_error: '原始密碼輸入錯誤' }, chart: { + chart_refresh_tips: '視圖刷新設置優先於儀表板刷新設置', '1-trend': '趨勢', '2-state': '狀態', '3-rank': '排名', @@ -1479,9 +1480,9 @@ export default { total_sort_desc: '降序', total_sort_field: '排序字段', empty_data_strategy: '空值處理', - break_line: '線條斷開', - set_zero: '置為0,線條不斷開', - ignore_data: '跳過空值,不展示', + break_line: '保持為空', + set_zero: '置為0', + ignore_data: '隱藏空值', sub_dimension_tip: '該字段為必填項,且不應使用類別軸中的字段,若無需該字段,請選擇基礎圖表進行展示,否則展示效果不理想', drill_dimension_tip: '鑽取字段僅支持數據集中的字段', table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。', @@ -1918,6 +1919,7 @@ export default { field_description: '欄位描述', table_description: '表描述', relational_database: '關係型數據庫', + data_warehouse_lake: '數倉/數據湖', non_relational_database: '非關係型數據庫', all: '所有', other: '其他', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index b9078e74b6..9255752a76 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -929,6 +929,7 @@ export default { password_input_error: '原始密码输入错误' }, chart: { + chart_refresh_tips: '视图刷新设置优先于仪表板刷新设置', '1-trend': '趋势', '2-state': '状态', '3-rank': '排名', @@ -1478,9 +1479,9 @@ export default { total_sort_desc: '降序', total_sort_field: '排序字段', empty_data_strategy: '空值处理', - break_line: '线条断开', - set_zero: '置为0,线条不断开', - ignore_data: '跳过空值,不展示', + break_line: '保持为空', + set_zero: '置为0', + ignore_data: '隐藏空值', sub_dimension_tip: '该字段为必填项,且不应使用类别轴中的字段,若无需该字段,请选择基础图表进行展示,否则展示效果不理想。', drill_dimension_tip: '钻取字段仅支持数据集中的字段', table_scroll_tip: '明细表仅在分页模式为"下拉"时生效。', @@ -1917,6 +1918,7 @@ export default { field_description: '字段描述', table_description: '表描述', relational_database: '关系型数据库', + data_warehouse_lake: '数仓/数据湖', non_relational_database: '非关系型数据库', all: '所有', other: '其他', diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index fda7afc92e..d2f832d71d 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -503,6 +503,9 @@ const data = { const element = state.componentData[index] if (element.id && element.id === id) { state.componentData.splice(index, 1) + if (element.type === 'de-tabs') { + this.commit('deleteComponentsWithCanvasId', element.id) + } break } } @@ -811,6 +814,33 @@ const data = { state.mousePointShadowMap.mouseY = mousePoint.mouseY state.mousePointShadowMap.width = mousePoint.width state.mousePointShadowMap.height = mousePoint.height + }, + deleteComponentsWithCanvasId(state, canvasId) { + if (canvasId && canvasId.length > 10) { + for (let index = 0; index < state.componentData.length; index++) { + const element = state.componentData[index] + if (element.canvasId && element.canvasId.includes(canvasId)) { + state.componentData.splice(index, 1) + } + } + } + }, + // 清除相同sourceViewId 的 联动条件 + clearViewLinkage(state, viewId) { + state.componentData.forEach(item => { + if (item.linkageFilters && item.linkageFilters.length > 0) { + const newList = item.linkageFilters.filter(linkage => linkage.sourceViewId !== viewId) + item.linkageFilters.splice(0, item.linkageFilters.length) + // 重新push 可保证数组指针不变 可以watch到 + if (newList.length > 0) { + newList.forEach(newLinkage => { + item.linkageFilters.push(newLinkage) + }) + } + } + }) + + bus.$emit('clear_panel_linkage', { viewId: viewId }) } }, modules: { diff --git a/frontend/src/views/background/BackgroundOverall.vue b/frontend/src/views/background/BackgroundOverall.vue index d3a9d706ec..0aa5fc5553 100644 --- a/frontend/src/views/background/BackgroundOverall.vue +++ b/frontend/src/views/background/BackgroundOverall.vue @@ -36,7 +36,10 @@ :span="6" style="padding-top: 5px" > - + {{ $t('chart.color') }} @@ -75,9 +78,12 @@ :span="4" style="padding-top: 5px" > - {{ - $t('panel.background') - }} + {{ + $t('panel.background') + }} @@ -113,7 +119,7 @@ :http-request="upload" :file-list="fileList" > - + 0) { + if (extStack?.length > 0 || xaxisExt?.length > 0) { f = yAxis[0] } else { for (let i = 0; i < yAxis.length; i++) { @@ -371,7 +376,7 @@ export function getTooltip(chart) { } else { res = param.value } - obj.value = res + obj.value = res === null ? '' : res return obj } } diff --git a/frontend/src/views/chart/chart/formatter.js b/frontend/src/views/chart/chart/formatter.js index 9c3be428e3..5a51c89dda 100644 --- a/frontend/src/views/chart/chart/formatter.js +++ b/frontend/src/views/chart/chart/formatter.js @@ -23,6 +23,9 @@ export const formatterType = [ ] export function valueFormatter(value, formatter) { + if (value === null || value === undefined) { + return null + } // 1.unit 2.decimal 3.thousand separator and suffix let result if (formatter.type === 'auto') { diff --git a/frontend/src/views/chart/chart/line/line_antv.js b/frontend/src/views/chart/chart/line/line_antv.js index f6b876a934..b8111e6c79 100644 --- a/frontend/src/views/chart/chart/line/line_antv.js +++ b/frontend/src/views/chart/chart/line/line_antv.js @@ -89,6 +89,7 @@ export function baseLineOptionAntV(plot, container, chart, action) { } // custom color options.color = antVCustomColor(chart) + // 处理空值 if (chart.senior) { let emptyDataStrategy = JSON.parse(chart.senior)?.functionCfg?.emptyDataStrategy if (!emptyDataStrategy) { @@ -119,7 +120,7 @@ export function baseAreaOptionAntV(plot, container, chart, action, isStack) { const xAxis = getXAxis(chart) const yAxis = getYAxis(chart) // data - const data = chart.data.data + const data = _.cloneDeep(chart.data.data) // config const slider = getSlider(chart) const analyse = getAnalyse(chart) @@ -197,6 +198,14 @@ export function baseAreaOptionAntV(plot, container, chart, action, isStack) { } } } + // 处理空值 + if (chart.senior) { + let emptyDataStrategy = JSON.parse(chart.senior)?.functionCfg?.emptyDataStrategy + if (!emptyDataStrategy) { + emptyDataStrategy = 'breakLine' + } + handleEmptyDataStrategy(emptyDataStrategy, chart, data, options) + } // 开始渲染 if (plot) { diff --git a/frontend/src/views/chart/components/ChartComponent.vue b/frontend/src/views/chart/components/ChartComponent.vue index 5b5c9f6fd4..6b5057a14f 100644 --- a/frontend/src/views/chart/components/ChartComponent.vue +++ b/frontend/src/views/chart/components/ChartComponent.vue @@ -332,6 +332,13 @@ export default { }) return } + if (this.canvasStyleData.panel.themeColor === 'dark') { + chart_option.legend['pageIconColor'] = '#ffffff' + chart_option.legend['pageIconInactiveColor'] = '#8c8c8c' + } else { + chart_option.legend['pageIconColor'] = '#000000' + chart_option.legend['pageIconInactiveColor'] = '#8c8c8c' + } this.myEcharts(chart_option) this.$nextTick(() => (this.linkageActive())) }, diff --git a/frontend/src/views/chart/components/ChartComponentG2.vue b/frontend/src/views/chart/components/ChartComponentG2.vue index 5c1a727b62..650a73cf27 100644 --- a/frontend/src/views/chart/components/ChartComponentG2.vue +++ b/frontend/src/views/chart/components/ChartComponentG2.vue @@ -58,6 +58,7 @@ import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart' import { baseMixOptionAntV } from '@/views/chart/chart/mix/mix_antv' import ChartTitleUpdate from './ChartTitleUpdate.vue' import { equalsAny } from '@/utils/StringUtils' +import { mapState } from 'vuex' export default { name: 'ChartComponentG2', @@ -140,7 +141,10 @@ export default { chartInfo() { const { id, title } = this.chart return { id, title } - } + }, + ...mapState([ + 'canvasStyleData' + ]) }, watch: { chart: { @@ -280,6 +284,24 @@ export default { if (this.myChart && chart.type !== 'liquid' && this.searchCount > 0) { this.myChart.options.animation = false } + if (this.myChart.options.legend) { + let pageNavigatorInactiveFill, pageNavigatorFill + if (this.canvasStyleData.panel.themeColor === 'dark') { + pageNavigatorFill = '#ffffff' + pageNavigatorInactiveFill = '#8c8c8c' + } else { + pageNavigatorFill = '#000000' + pageNavigatorInactiveFill = '#8c8c8c' + } + this.myChart.options.legend['pageNavigator'] = { + marker: { + style: { + inactiveFill: pageNavigatorInactiveFill, // 不能点击的颜色 + fill: pageNavigatorFill // 正常的颜色 + } + } + } + } if (this.antVRenderStatus) { this.myChart.render() diff --git a/frontend/src/views/chart/components/senior/FunctionCfg.vue b/frontend/src/views/chart/components/senior/FunctionCfg.vue index 4fe2252ca1..31f96f2968 100644 --- a/frontend/src/views/chart/components/senior/FunctionCfg.vue +++ b/frontend/src/views/chart/components/senior/FunctionCfg.vue @@ -68,7 +68,7 @@ /> @@ -174,7 +174,7 @@ span{ } .form-item ::v-deep .el-radio-group{ display: flex; - flex-direction: row; + flex-direction: column; flex-wrap: wrap; label { line-height: 28px; diff --git a/frontend/src/views/chart/group/Group.vue b/frontend/src/views/chart/group/Group.vue index 63aa526890..89ec69c2ec 100644 --- a/frontend/src/views/chart/group/Group.vue +++ b/frontend/src/views/chart/group/Group.vue @@ -13,7 +13,7 @@ @click="add('group')" /> - + - {{ searchMap[searchType] }} + {{ searchMap[searchType] }} {{ $t('commons.all') }} @@ -63,7 +63,7 @@ > - + - + - +
{{ $t('chart.cancel') }} + >{{ $t('chart.cancel') }} + {{ $t('chart.confirm') }} + >{{ $t('chart.confirm') }} +
@@ -264,7 +266,7 @@ :label="$t('commons.name')" prop="name" > - +
{{ $t('chart.cancel') }} + >{{ $t('chart.cancel') }} + {{ $t('chart.confirm') }} + >{{ $t('chart.confirm') }} +
@@ -318,8 +322,8 @@ :active="createActive" align-center > - - + + {{ $t('chart.cancel') }} + >{{ $t('chart.cancel') }} + {{ $t('chart.preview') - }} + >{{ + $t('chart.preview') + }} {{ $t('dataset.cancel') }} + >{{ $t('dataset.cancel') }} + {{ - $t('dataset.confirm') }} + $t('dataset.confirm') + }} @@ -465,14 +473,16 @@ {{ $t('dataset.cancel') }} + >{{ $t('dataset.cancel') }} + {{ - $t('dataset.confirm') }} + $t('dataset.confirm') + }} @@ -480,27 +490,26 @@ diff --git a/frontend/src/views/chart/view/ChartEdit.vue b/frontend/src/views/chart/view/ChartEdit.vue index 4931d8baba..1fb3e092a3 100644 --- a/frontend/src/views/chart/view/ChartEdit.vue +++ b/frontend/src/views/chart/view/ChartEdit.vue @@ -192,7 +192,7 @@ @command="chartFieldEdit" > - + - + {{ $t('chart.change_chart_type') }} - + @@ -406,6 +406,68 @@ + + + + + + + + {{ $t('panel.refresh_frequency') }} + + +
+ {{ $t('chart.chart_refresh_tips') }} +
+ +
+ + + {{ $t('panel.enable_refresh_view') }} + + + + + + + + +
{{ - $t('chart.drag_block_table_data_column') - }} + $t('chart.drag_block_table_data_column') + }} {{ $t('chart.drag_block_type_axis') }} @@ -499,18 +561,18 @@ v-else-if="view.type && view.type.includes('pie')" >{{ $t('chart.drag_block_pie_label') }} {{ - $t('chart.drag_block_funnel_split') - }} + $t('chart.drag_block_funnel_split') + }} {{ - $t('chart.drag_block_radar_label') - }} + $t('chart.drag_block_radar_label') + }} {{ $t('chart.area') }} {{ - $t('chart.drag_block_treemap_label') - }} + $t('chart.drag_block_treemap_label') + }} {{ - $t('chart.drag_block_word_cloud_label') - }} + $t('chart.drag_block_word_cloud_label') + }} {{ $t('chart.drag_block_label') }} / {{ $t('chart.dimension') }} @@ -633,8 +695,8 @@ > {{ - $t('chart.drag_block_table_data_column') - }} + $t('chart.drag_block_table_data_column') + }} {{ $t('chart.drag_block_value_axis') }} @@ -642,30 +704,30 @@ v-else-if="view.type && view.type.includes('pie')" >{{ $t('chart.drag_block_pie_angel') }} {{ - $t('chart.drag_block_funnel_width') - }} + $t('chart.drag_block_funnel_width') + }} {{ - $t('chart.drag_block_radar_length') - }} + $t('chart.drag_block_radar_length') + }} {{ - $t('chart.drag_block_gauge_angel') - }} + $t('chart.drag_block_gauge_angel') + }} {{ $t('chart.drag_block_label_value') }} {{ $t('chart.chart_data') }} {{ - $t('chart.drag_block_treemap_size') - }} + $t('chart.drag_block_treemap_size') + }} {{ - $t('chart.drag_block_value_axis_main') - }} + $t('chart.drag_block_value_axis_main') + }} {{ $t('chart.drag_block_progress') }} {{ - $t('chart.drag_block_word_cloud_size') - }} + $t('chart.drag_block_word_cloud_size') + }} / {{ $t('chart.quota') }} - + @@ -1293,7 +1355,7 @@ width="800px" class="dialog-css" > - +