mirror of
https://github.com/dataease/dataease.git
synced 2026-05-14 21:12:33 +08:00
feat(图表): 指标卡支持联动并支持在嵌入时将过滤参数向外传递
This commit is contained in:
@@ -44,6 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -223,11 +224,17 @@ public class ChartDataManage {
|
||||
}
|
||||
|
||||
List<ChartExtFilterDTO> filters = new ArrayList<>();
|
||||
FilterTreeObj customLinkageFilter = null;
|
||||
// 联动条件
|
||||
if (ObjectUtils.isNotEmpty(chartExtRequest.getLinkageFilters())) {
|
||||
filters.addAll(chartExtRequest.getLinkageFilters());
|
||||
for(ChartExtFilterDTO linkageFilter: chartExtRequest.getLinkageFilters()) {
|
||||
if (3 == linkageFilter.getFilterType()) {
|
||||
customLinkageFilter = linkageFilter.getCustomFilter();
|
||||
} else {
|
||||
filters.add(linkageFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 外部参数条件
|
||||
if (ObjectUtils.isNotEmpty(chartExtRequest.getOuterParamsFilters())) {
|
||||
filters.addAll(chartExtRequest.getOuterParamsFilters());
|
||||
@@ -355,6 +362,10 @@ public class ChartDataManage {
|
||||
}
|
||||
// 字段过滤器
|
||||
FilterTreeObj fieldCustomFilter = view.getCustomFilter();
|
||||
// 指标表联动时 使用的CustomFilter
|
||||
if (customLinkageFilter != null) {
|
||||
fieldCustomFilter = customLinkageFilter;
|
||||
}
|
||||
chartFilterTreeService.searchFieldAndSet(fieldCustomFilter);
|
||||
fieldCustomFilter = chartFilterTreeService.charReplace(fieldCustomFilter);
|
||||
// 获取dsMap,union sql
|
||||
|
||||
@@ -392,18 +392,21 @@ const calcData = (view, callback) => {
|
||||
|
||||
const trackClick = trackAction => {
|
||||
const param = state.pointParam
|
||||
if (!param?.data?.dimensionList) {
|
||||
if (!param?.data?.dimensionList && !param?.data?.quotaList) {
|
||||
return
|
||||
}
|
||||
const linkageParam = {
|
||||
option: 'linkage',
|
||||
innerType: 'indicator',
|
||||
name: state.pointParam.data.name,
|
||||
viewId: view.value.id,
|
||||
dimensionList: state.pointParam.data.dimensionList,
|
||||
quotaList: state.pointParam.data.quotaList
|
||||
quotaList: state.pointParam.data.quotaList,
|
||||
customFilter: state.pointParam.data.customFilter
|
||||
}
|
||||
const jumpParam = {
|
||||
option: 'jump',
|
||||
innerType: 'indicator',
|
||||
name: state.pointParam.data.name,
|
||||
viewId: view.value.id,
|
||||
dimensionList: state.pointParam.data.dimensionList,
|
||||
@@ -413,10 +416,12 @@ const trackClick = trackAction => {
|
||||
|
||||
const clickParams = {
|
||||
option: 'pointClick',
|
||||
innerType: 'indicator',
|
||||
name: state.pointParam.data.name,
|
||||
viewId: view.value.id,
|
||||
dimensionList: state.pointParam.data.dimensionList,
|
||||
quotaList: state.pointParam.data.quotaList
|
||||
quotaList: state.pointParam.data.quotaList,
|
||||
customFilter: state.pointParam.data.customFilter
|
||||
}
|
||||
|
||||
switch (trackAction) {
|
||||
@@ -477,6 +482,10 @@ const trackMenu = computed(() => {
|
||||
return trackMenuInfo
|
||||
})
|
||||
|
||||
const showCursor = computed(() => {
|
||||
return trackMenu.value.length || embeddedCallBack.value === 'yes'
|
||||
})
|
||||
|
||||
const pointClickTrans = () => {
|
||||
if (embeddedCallBack.value === 'yes') {
|
||||
trackClick('pointClick')
|
||||
@@ -516,11 +525,10 @@ const onPointClick = () => {
|
||||
// 模拟点击
|
||||
const params = {
|
||||
data: {
|
||||
data: {
|
||||
name: axis.name,
|
||||
dimensionList: [],
|
||||
quotaList: view.value.yAxis
|
||||
}
|
||||
name: axis.name,
|
||||
dimensionList: view.value.xAxis,
|
||||
quotaList: view.value.yAxis,
|
||||
customFilter: view.value.customFilter
|
||||
}
|
||||
}
|
||||
action(params)
|
||||
@@ -534,7 +542,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :style="contentStyle" @click="onPointClick">
|
||||
<div :class="{ 'menu-point': showCursor }" :style="contentStyle" @click="onPointClick">
|
||||
<view-track-bar
|
||||
ref="viewTrack"
|
||||
:track-menu="trackMenu"
|
||||
@@ -554,4 +562,8 @@ defineExpose({
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less"></style>
|
||||
<style scoped lang="less">
|
||||
.menu-point {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1005,11 +1005,19 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
}
|
||||
const preActiveComponentIds = []
|
||||
const checkQDList = [...data.dimensionList, ...data.quotaList]
|
||||
const customFilterInfo = data.customFilter
|
||||
for (let indexOuter = 0; indexOuter < this.componentData.length; indexOuter++) {
|
||||
const element = this.componentData[indexOuter]
|
||||
if (element.id !== viewId) {
|
||||
if (['UserView', 'VQuery'].includes(element.component)) {
|
||||
this.trackFilterCursor(element, checkQDList, trackInfo, preActiveComponentIds, viewId)
|
||||
this.trackFilterCursor(
|
||||
element,
|
||||
checkQDList,
|
||||
trackInfo,
|
||||
preActiveComponentIds,
|
||||
viewId,
|
||||
customFilterInfo
|
||||
)
|
||||
this.componentData[indexOuter] = element
|
||||
} else if (element.component === 'Group') {
|
||||
element.propValue?.forEach((groupItem, index) => {
|
||||
@@ -1018,7 +1026,8 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
checkQDList,
|
||||
trackInfo,
|
||||
preActiveComponentIds,
|
||||
viewId
|
||||
viewId,
|
||||
customFilterInfo
|
||||
)
|
||||
element.propValue[index] = groupItem
|
||||
})
|
||||
@@ -1030,7 +1039,8 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
checkQDList,
|
||||
trackInfo,
|
||||
preActiveComponentIds,
|
||||
viewId
|
||||
viewId,
|
||||
customFilterInfo
|
||||
)
|
||||
tabItem.componentData[index] = tabComponent
|
||||
})
|
||||
@@ -1314,11 +1324,25 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
})
|
||||
}
|
||||
},
|
||||
trackFilterCursor(element, checkQDList, trackInfo, preActiveComponentIds, viewId) {
|
||||
trackFilterCursor(
|
||||
element,
|
||||
checkQDList,
|
||||
trackInfo,
|
||||
preActiveComponentIds,
|
||||
viewId,
|
||||
customFilter?
|
||||
) {
|
||||
let currentFilters = element.linkageFilters || [] // 当前联动filter
|
||||
if (['table-info', 'table-normal'].includes(element.innerType)) {
|
||||
currentFilters = []
|
||||
}
|
||||
if (currentFilters.length) {
|
||||
for (let i = currentFilters.length - 1; i >= 0; i--) {
|
||||
if (currentFilters[i].filterType === 3) {
|
||||
currentFilters.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 联动的图表情况历史条件
|
||||
// const currentFilters = []
|
||||
checkQDList.forEach(QDItem => {
|
||||
@@ -1330,38 +1354,46 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
const targetInfoArray = targetInfo.split('#')
|
||||
const targetViewId = targetInfoArray[0] // 目标图表
|
||||
if (element.component === 'UserView' && element.id === targetViewId) {
|
||||
// 如果目标图表 和 当前循环组件id相等 则进行条件增减
|
||||
const targetFieldId = targetInfoArray[1] // 目标图表列ID
|
||||
let condition
|
||||
if (QDItem.timeValue && Array.isArray(QDItem.timeValue)) {
|
||||
// 如果dimension.timeValue存在值且是数组 目前判断为是时间组件
|
||||
condition = {
|
||||
fieldId: targetFieldId,
|
||||
operator: 'between',
|
||||
value: QDItem.timeValue,
|
||||
viewIds: [targetViewId],
|
||||
sourceViewId: viewId
|
||||
}
|
||||
// 如果含有customFilter 仅加入customFilter
|
||||
if (customFilter) {
|
||||
currentFilters.push({
|
||||
filterType: 3,
|
||||
customFilter: customFilter
|
||||
})
|
||||
} else {
|
||||
condition = {
|
||||
fieldId: targetFieldId,
|
||||
operator: 'eq',
|
||||
value: [QDItem.value],
|
||||
viewIds: [targetViewId],
|
||||
sourceViewId: viewId
|
||||
// 如果目标图表 和 当前循环组件id相等 则进行条件增减
|
||||
const targetFieldId = targetInfoArray[1] // 目标图表列ID
|
||||
let condition
|
||||
if (QDItem.timeValue && Array.isArray(QDItem.timeValue)) {
|
||||
// 如果dimension.timeValue存在值且是数组 目前判断为是时间组件
|
||||
condition = {
|
||||
fieldId: targetFieldId,
|
||||
operator: 'between',
|
||||
value: QDItem.timeValue,
|
||||
viewIds: [targetViewId],
|
||||
sourceViewId: viewId
|
||||
}
|
||||
} else {
|
||||
condition = {
|
||||
fieldId: targetFieldId,
|
||||
operator: 'eq',
|
||||
value: [QDItem.value],
|
||||
viewIds: [targetViewId],
|
||||
sourceViewId: viewId
|
||||
}
|
||||
}
|
||||
}
|
||||
let j = currentFilters.length
|
||||
while (j--) {
|
||||
const filter = currentFilters[j]
|
||||
// 兼容性准备 viewIds 只会存放一个值
|
||||
if (targetFieldId === filter.fieldId && filter.viewIds.includes(targetViewId)) {
|
||||
currentFilters.splice(j, 1)
|
||||
let j = currentFilters.length
|
||||
while (j--) {
|
||||
const filter = currentFilters[j]
|
||||
// 兼容性准备 viewIds 只会存放一个值
|
||||
if (targetFieldId === filter.fieldId && filter.viewIds.includes(targetViewId)) {
|
||||
currentFilters.splice(j, 1)
|
||||
}
|
||||
}
|
||||
// 不存在该条件 且 条件有效 直接保存该条件
|
||||
// !filterExist && vValid && currentFilters.push(condition)
|
||||
currentFilters.push(condition)
|
||||
}
|
||||
// 不存在该条件 且 条件有效 直接保存该条件
|
||||
// !filterExist && vValid && currentFilters.push(condition)
|
||||
currentFilters.push(condition)
|
||||
preActiveComponentIds.includes(element.id) || preActiveComponentIds.push(element.id)
|
||||
}
|
||||
if (element.component === 'VQuery') {
|
||||
|
||||
@@ -4,6 +4,7 @@ package io.dataease.extensions.view.dto;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
|
||||
import io.dataease.extensions.view.filter.FilterTreeObj;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@@ -25,6 +26,6 @@ public class ChartExtFilterDTO {
|
||||
private String datePattern;
|
||||
@JsonIgnore
|
||||
private List<String> originValue;
|
||||
private int filterType;// 0-过滤组件,1-下钻,2-联动,外部参数
|
||||
|
||||
private int filterType;// 0-过滤组件,1-下钻,2-联动,外部参数 3-联动 自定义参数
|
||||
private FilterTreeObj customFilter;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user