feat: 新增charts模块代码

新增charts模块中的相关Handler代码,解决图标显示报错问题
This commit is contained in:
weitang 2025-07-04 17:48:54 +08:00
parent f6a0a25f91
commit abb866fc12
33 changed files with 3782 additions and 3 deletions

View File

@ -0,0 +1,22 @@
package com.stdproject.charts.impl;
import com.stdproject.service.manage.DefaultChartHandler;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import io.gisbi.extensions.view.dto.ChartViewFieldDTO;
import java.util.ArrayList;
public class ExtQuotaChartHandler extends DefaultChartHandler {
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
return result;
}
}

View File

@ -0,0 +1,20 @@
package com.stdproject.charts.impl;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import io.gisbi.extensions.view.dto.ChartViewFieldDTO;
import java.util.ArrayList;
public class GroupChartHandler extends YoyChartHandler {
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var xAxis = new ArrayList<ChartViewFieldDTO>(view.getXAxis());
xAxis.addAll(view.getXAxisExt());
result.getAxisMap().put(ChartAxis.xAxis, xAxis);
return result;
}
}

View File

@ -0,0 +1,187 @@
package com.stdproject.charts.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.service.manage.DefaultChartHandler;
import com.stdproject.service.provider.SQLProvider;
import com.stdproject.utils.Utils;
import com.stdproject.utils.trans.ExtWhere2Str;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import io.gisbi.extensions.view.util.FieldUtil;
import io.gisbi.utils.JsonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 带同环比计算的图表处理器
*/
public class YoyChartHandler extends DefaultChartHandler {
@Override
public <T extends CustomFilterResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, AxisFormatResult formatResult) {
var result = super.customFilter(view, filterList, formatResult);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
String originFilterJson = (String) JsonUtil.toJSONString(filterList);
// 如果设置了同环比的指标字段设置了过滤器那就需要把该过滤器的时间往前回调一年
// 计算完同环比之后再把计算结果和原有的过滤结果对比去除不该出现的前一年的数据
boolean yoyFiltered = checkYoyFilter(filterList, yAxis);
if (yoyFiltered) {
List<ChartExtFilterDTO> originFilter = JsonUtil.parseList(originFilterJson, new TypeReference<>() {
});
formatResult.getContext().put("originFilter", originFilter);
formatResult.getContext().put("yoyFiltered", true);
}
return (T) result;
}
@Override
public Map<String, Object> buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null;
// 带过滤同环比直接返回原始数据,再由视图重新组装
if (yoyFiltered) {
var result = new HashMap<String, Object>();
result.put("data", data);
return result;
}
return buildNormalResult(view, formatResult, filterResult, data);
}
/**
* 构建同环比类型的数据
*
* @param view 视图对象
* @param formatResult 处理后的轴
* @param filterResult 处理后的过滤器
* @param data 原始数据
* @return 视图构建结果
*/
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
return super.buildResult(view, formatResult, filterResult, data);
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
// 这里拿到的可能有一年前的数据
var expandedResult = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
// 检查同环比过滤拿到实际数据
var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null;
if (yoyFiltered) {
var originFilter = (List<ChartExtFilterDTO>) filterResult.getContext().get("originFilter");
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
ExtWhere2Str.extWhere2sqlOjb(sqlMeta, originFilter, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
var originSql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
originSql = provider.rebuildSQL(originSql, sqlMeta, crossDs, dsMap);
var request = new DatasourceRequest();
request.setIsCross(crossDs);
request.setDsList(dsMap);
request.setQuery(originSql);
logger.debug("calcite yoy sql: " + originSql);
// 实际过滤后的数据
var originData = (List<String[]>) provider.fetchResultField(request).get("data");
List<String[]> resultData = new ArrayList<>();
// 包含一年前的数据, 已计算同环比
var yoyData = (List<String[]>) expandedResult.getData().get("data");
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
// 对比维度,只保留实际过滤后的数据
for (String[] yoyDataLine : yoyData) {
StringBuilder x1 = new StringBuilder();
for (int i = 0; i < xAxis.size(); i++) {
x1.append(yoyDataLine[i]);
}
for (String[] originDataLine : originData) {
StringBuilder x2 = new StringBuilder();
for (int i = 0; i < xAxis.size(); i++) {
x2.append(originDataLine[i]);
}
if (StringUtils.equals(x1, x2)) {
resultData.add(yoyDataLine);
break;
}
}
}
yoyData.clear();
yoyData.addAll(resultData);
var result = this.buildNormalResult(view, formatResult, filterResult, yoyData);
expandedResult.setData(result);
expandedResult.setOriginData(resultData);
expandedResult.setQuerySql(originSql);
}
// 同环比数据排序
expandedResult.setOriginData(sortData(view, expandedResult.getOriginData(), formatResult));
return expandedResult;
}
public static List<String[]> sortData(ChartViewDTO view, List<String[]> data, AxisFormatResult formatResult) {
// 维度排序
List<ChartViewFieldDTO> xAxisSortList = view.getXAxis().stream().filter(x -> !StringUtils.equalsIgnoreCase("none", x.getSort())).toList();
// 指标排序
List<ChartViewFieldDTO> yAxisSortList = view.getYAxis().stream().filter(y -> {
//需要针对区间条形图的时间类型判断一下
if (StringUtils.equalsIgnoreCase("bar-range", view.getType()) && StringUtils.equalsIgnoreCase(y.getGroupType(), "d") && y.getDeType() == 1) {
return false;
} else {
return !StringUtils.equalsIgnoreCase("none", y.getSort());
}
}).toList();
// 不包含维度排序时指标排序生效
if (!data.isEmpty() && CollectionUtils.isEmpty(xAxisSortList) && CollectionUtils.isNotEmpty(yAxisSortList)) {
// 指标排序仅第一个生效
ChartViewFieldDTO firstYAxis = yAxisSortList.getFirst();
boolean asc = firstYAxis.getSort().equalsIgnoreCase("asc");
// 维度指标
List<ChartViewFieldDTO> allAxisList = new ArrayList<>();
allAxisList.addAll(formatResult.getAxisMap().get(ChartAxis.xAxis));
allAxisList.addAll(formatResult.getAxisMap().get(ChartAxis.yAxis));
int index = findIndex(allAxisList, firstYAxis.getId());
return sortData(data, asc, index);
}
return data;
}
public static List<String[]> sortData(List<String[]> data, boolean ascending, int index) {
Comparator<String[]> comparator;
if (ascending) {
comparator = Comparator.comparing(item -> toBigDecimal(item[index]), Comparator.nullsFirst(Comparator.naturalOrder()));
} else {
comparator = Comparator.comparing(item -> toBigDecimal(item[index]), Comparator.nullsLast(Comparator.reverseOrder()));
}
return data.stream().sorted(comparator).collect(Collectors.toList());
}
private static BigDecimal toBigDecimal(String value) {
if (value == null) {
return null;
}
try {
return new BigDecimal(value);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid number format: " + value, e);
}
}
public static int findIndex(List<ChartViewFieldDTO> list, Long id) {
for (int i = 0; i < list.size(); i++) {
if (StringUtils.equalsIgnoreCase(list.get(i).getId().toString(), id.toString())) {
return i;
}
}
return -1;
}
}

View File

@ -0,0 +1,31 @@
package com.stdproject.charts.impl.line;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class AreaHandler extends LineHandler {
@Getter
private String type = "area";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
result.getAxisMap().put(ChartAxis.xAxis, view.getXAxis());
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult.getFilterList().stream().anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
return ChartDataBuild.transChartData(xAxis, yAxis, view, data, isDrill);
}
}

View File

@ -0,0 +1,99 @@
package com.stdproject.charts.impl.line;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class LineHandler extends YoyChartHandler {
@Getter
private String type = "line";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
xAxis.addAll(view.getXAxisExt());
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.xAxisExt, view.getXAxisExt());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var drillAxis = xAxis.stream().filter(axis -> FieldSource.DRILL == axis.getSource()).toList();
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size() - drillAxis.size());
return ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
var result = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
try {
//如果有同环比过滤,应该用原始sql
var originSql = result.getQuerySql();
var dynamicAssistFields = getDynamicAssistFields(view);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var assistFields = getAssistFields(dynamicAssistFields, yAxis);
if (CollectionUtils.isNotEmpty(assistFields)) {
var req = new DatasourceRequest();
req.setIsCross(crossDs);
req.setDsList(dsMap);
List<ChartSeniorAssistDTO> assists = dynamicAssistFields.stream().filter(ele -> !StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assists)) {
var assistSql = assistSQL(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSql);
logger.debug("calcite assistSql sql: " + assistSql);
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistData(assistData);
result.setDynamicAssistFields(assists);
}
List<ChartSeniorAssistDTO> assistsOriginList = dynamicAssistFields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assistsOriginList)) {
var assistSqlOriginList = assistSQLOriginList(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSqlOriginList);
logger.debug("calcite assistSql sql origin list: " + assistSqlOriginList);
var assistDataOriginList = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistDataOriginList(assistDataOriginList);
result.setDynamicAssistFieldsOriginList(assistsOriginList);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

View File

@ -0,0 +1,132 @@
package com.stdproject.charts.impl.line;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.utils.ChartDataBuild;
import com.stdproject.utils.Utils;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Component
public class StackAreaHandler extends YoyChartHandler {
@Getter
private String type = "area-stack";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
xAxis.addAll(view.getExtStack());
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.extStack, view.getExtStack());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var drillAxis = xAxis.stream().filter(axis -> FieldSource.DRILL == axis.getSource()).toList();
var xAxisBase = xAxis.subList(0, xAxis.size() - extStack.size() - drillAxis.size());
return ChartDataBuild.transStackChartDataAntV(xAxisBase, xAxis, yAxis, view, data, extStack, isDrill);
}
@Override
public <T extends CustomFilterResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, AxisFormatResult formatResult) {
var result = super.customFilter(view, filterList, formatResult);
List<ChartDrillRequest> drillRequestList = view.getChartExtRequest().getDrill();
var drillFields = formatResult.getAxisMap().get(ChartAxis.drill);
// 堆叠维度下钻
if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) {
List<ChartExtFilterDTO> noDrillFilterList = filterList
.stream()
.filter(ele -> ele.getFilterType() != 1)
.collect(Collectors.toList());
var noDrillFieldAxis = formatResult.getAxisMap().get(ChartAxis.xAxis)
.stream()
.filter(ele -> ele.getSource() != FieldSource.DRILL)
.collect(Collectors.toList());
List<ChartExtFilterDTO> drillFilters = new ArrayList<>();
ArrayList<ChartViewFieldDTO> fieldsToFilter = new ArrayList<>();
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
if (ObjectUtils.isNotEmpty(extStack) &&
Objects.equals(drillFields.get(0).getId(), extStack.get(0).getId())) {
fieldsToFilter.addAll(view.getXAxis());
}
groupStackDrill(noDrillFieldAxis, noDrillFilterList, fieldsToFilter, drillFields, drillRequestList);
formatResult.getAxisMap().put(ChartAxis.xAxis, noDrillFieldAxis);
result.setFilterList(noDrillFilterList);
}
return (T) result;
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
var result = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
try {
//如果有同环比过滤,应该用原始sql
var originSql = result.getQuerySql();
var dynamicAssistFields = getDynamicAssistFields(view);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var assistFields = getAssistFields(dynamicAssistFields, yAxis);
if (CollectionUtils.isNotEmpty(assistFields)) {
var req = new DatasourceRequest();
req.setIsCross(crossDs);
req.setDsList(dsMap);
List<ChartSeniorAssistDTO> assists = dynamicAssistFields.stream().filter(ele -> !StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assists)) {
var assistSql = assistSQL(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSql);
logger.debug("calcite assistSql sql: " + assistSql);
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistData(assistData);
result.setDynamicAssistFields(assists);
}
List<ChartSeniorAssistDTO> assistsOriginList = dynamicAssistFields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assistsOriginList)) {
var assistSqlOriginList = assistSQLOriginList(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSqlOriginList);
logger.debug("calcite assistSql sql origin list: " + assistSqlOriginList);
var assistDataOriginList = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistDataOriginList(assistDataOriginList);
result.setDynamicAssistFieldsOriginList(assistsOriginList);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

View File

@ -0,0 +1,20 @@
package com.stdproject.charts.impl.map;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class BubbleMapHandler extends ExtQuotaChartHandler {
@Getter
private String type = "bubble-map";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
return super.formatAxis(view);
}
}

View File

@ -0,0 +1,26 @@
package com.stdproject.charts.impl.map;
import com.stdproject.charts.impl.GroupChartHandler;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Optional;
@Component
public class FlowMapHandler extends GroupChartHandler {
@Getter
private String type = "flow-map";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
xAxis.addAll(Optional.ofNullable(view.getFlowMapStartName()).orElse(new ArrayList<>()));
xAxis.addAll(Optional.ofNullable(view.getFlowMapEndName()).orElse(new ArrayList<>()));
result.getAxisMap().put(ChartAxis.xAxis, xAxis);
return result;
}
}

View File

@ -0,0 +1,28 @@
package com.stdproject.charts.impl.map;
import com.stdproject.service.manage.DefaultChartHandler;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class HeatMapHandler extends DefaultChartHandler {
@Getter
private String type = "heat-map";
@Override
public Map<String, Object> buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
Map<String, Object> result = ChartDataBuild.transHeatMapChartDataAntV(xAxis, xAxis, yAxis, view, data, isDrill);
return result;
}
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.map;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class MapHandler extends ExtQuotaChartHandler {
@Getter
private String type = "map";
}

View File

@ -0,0 +1,32 @@
package com.stdproject.charts.impl.mix;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import io.gisbi.extensions.view.dto.CustomFilterResult;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class DualLineMixHandler extends GroupMixHandler {
@Getter
private final String type = "chart-mix-dual-line";
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
return ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, true);
}
}

View File

@ -0,0 +1,52 @@
package com.stdproject.charts.impl.mix;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class GroupMixHandler extends MixHandler {
@Getter
private final String type = "chart-mix-group";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var context = new HashMap<String, Object>();
AxisFormatResult result = new AxisFormatResult(axisMap, context);
//左轴分组子维度,非分组不需要
axisMap.put(ChartAxis.xAxisExt, view.getXAxisExt());
//左轴堆叠子维度,非堆叠不需要
axisMap.put(ChartAxis.extStack, Collections.emptyList());
//左轴指标
axisMap.put(ChartAxis.yAxis, view.getYAxis());
//右轴分组子维度
axisMap.put(ChartAxis.extBubble, view.getExtBubble());
//右轴指标
axisMap.put(ChartAxis.yAxisExt, view.getYAxisExt());
//去除除了x轴以外的排序
axisMap.forEach((k, v) -> {
if (!ChartAxis.xAxisExt.equals(k)) {
v.forEach(x -> x.setSort("none"));
}
});
axisMap.put(ChartAxis.extLabel, view.getExtLabel());
axisMap.put(ChartAxis.extTooltip, view.getExtTooltip());
//图表整体主维度
var xAxis = new ArrayList<>(view.getXAxis());
var xAxisGroup = new ArrayList<>(view.getXAxis());
xAxisGroup.addAll(view.getXAxisExt());
axisMap.put(ChartAxis.xAxis, xAxisGroup);
context.put("xAxisBase", xAxis);
axisMap.put(ChartAxis.drill, new ArrayList<>(view.getDrillFields()));
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
return super.buildNormalResult(view, formatResult, filterResult, data);
}
}

View File

@ -0,0 +1,246 @@
package com.stdproject.charts.impl.mix;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.utils.ChartDataBuild;
import com.stdproject.utils.Utils;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class MixHandler extends YoyChartHandler {
@Getter
private final String type = "chart-mix";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var context = new HashMap<String, Object>();
AxisFormatResult result = new AxisFormatResult(axisMap, context);
//左轴分组子维度,非分组不需要
axisMap.put(ChartAxis.xAxisExt, Collections.emptyList());
//左轴堆叠子维度,非堆叠不需要
axisMap.put(ChartAxis.extStack, Collections.emptyList());
//左轴指标
axisMap.put(ChartAxis.yAxis, view.getYAxis());
//右轴分组子维度
axisMap.put(ChartAxis.extBubble, view.getExtBubble());
//右轴指标
axisMap.put(ChartAxis.yAxisExt, view.getYAxisExt());
//去除除了x轴以外的排序
axisMap.forEach((k, v) -> {
v.forEach(x -> x.setSort("none"));
});
axisMap.put(ChartAxis.extLabel, view.getExtLabel());
axisMap.put(ChartAxis.extTooltip, view.getExtTooltip());
//图表整体主维度
axisMap.put(ChartAxis.xAxis, new ArrayList<>(view.getXAxis()));
context.put("xAxisBase", new ArrayList<>(view.getXAxis()));
axisMap.put(ChartAxis.drill, new ArrayList<>(view.getDrillFields()));
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
if (StringUtils.equals((String) formatResult.getContext().get("isRight"), "isRight")) {
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
return ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, true);
}
var xAxisBase = (List<ChartViewFieldDTO>) formatResult.getContext().get("xAxisBase");
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var result = ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, false);
return result;
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
//计算左轴, 包含 xAxis, yAxis
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
var leftResult = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
var dynamicAssistFields = getDynamicAssistFields(view);
try {
//如果有同环比过滤,应该用原始sql
var originSql = leftResult.getQuerySql();
var leftAssistFields = dynamicAssistFields.stream().filter(x -> StringUtils.equalsAnyIgnoreCase(x.getYAxisType(), "left")).toList();
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var assistFields = getAssistFields(leftAssistFields, yAxis);
if (CollectionUtils.isNotEmpty(assistFields)) {
var req = new DatasourceRequest();
req.setIsCross(crossDs);
req.setDsList(dsMap);
List<ChartSeniorAssistDTO> assists = leftAssistFields.stream().filter(ele -> !StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assists)) {
var assistSql = assistSQL(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSql);
logger.debug("calcite assistSql sql: " + assistSql);
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
leftResult.setAssistData(assistData);
leftResult.setDynamicAssistFields(assists);
}
List<ChartSeniorAssistDTO> assistsOriginList = leftAssistFields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assistsOriginList)) {
var assistSqlOriginList = assistSQLOriginList(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSqlOriginList);
logger.debug("calcite assistSql sql origin list: " + assistSqlOriginList);
var assistDataOriginList = (List<String[]>) provider.fetchResultField(req).get("data");
leftResult.setAssistDataOriginList(assistDataOriginList);
leftResult.setDynamicAssistFieldsOriginList(assistsOriginList);
}
}
} catch (Exception e) {
e.printStackTrace();
}
AxisFormatResult formatResult2 = new AxisFormatResult();
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
axisMap.put(ChartAxis.extLabel, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extLabel)));
axisMap.put(ChartAxis.extTooltip, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extTooltip)));
axisMap.put(ChartAxis.drill, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.drill)));
formatResult2.setAxisMap(axisMap);
formatResult2.setContext(formatResult.getContext());
// 计算右轴包含 xAxis,xAxisExt,yAxisExt,需要去掉 group stack
var xAxis = new ArrayList<>(view.getXAxis());
var extBubble = new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extBubble));
xAxis.addAll(extBubble);
var dillAxis = (ArrayList<ChartViewFieldDTO>) formatResult.getContext().get("dillAxis");
var fields = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet());
for (ChartViewFieldDTO dillAxi : dillAxis) {
if (!fields.contains(dillAxi.getId())) {
xAxis.add(dillAxi);
}
}
formatResult2.getAxisMap().put(ChartAxis.xAxis, xAxis);
formatResult2.getAxisMap().put(ChartAxis.xAxisExt, extBubble);
var yAxisExt = new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.yAxisExt));
formatResult2.getAxisMap().put(ChartAxis.yAxis, yAxisExt);
formatResult2.getContext().remove("yoyFiltered");
formatResult2.getContext().put("isRight", "isRight");
formatResult.getContext().put("subAxisMap", axisMap);
// 右轴重新检测同环比过滤
customFilter(view, filterResult.getFilterList(), formatResult2);
var rightResult = (T) super.calcChartResult(view, formatResult2, filterResult, sqlMap, sqlMeta, provider);
try {
//如果有同环比过滤,应该用原始sql
var originSql = rightResult.getQuerySql();
var rightAssistFields = dynamicAssistFields.stream().filter(x -> StringUtils.equalsAnyIgnoreCase(x.getYAxisType(), "right")).toList();
var yAxis = formatResult2.getAxisMap().get(ChartAxis.yAxis);
var assistFields = getAssistFields(rightAssistFields, yAxis);
if (CollectionUtils.isNotEmpty(assistFields)) {
var req = new DatasourceRequest();
req.setIsCross(crossDs);
req.setDsList(dsMap);
List<ChartSeniorAssistDTO> assists = rightAssistFields.stream().filter(ele -> !StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assists)) {
var assistSql = assistSQL(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSql);
logger.debug("calcite assistSql sql: " + assistSql);
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
rightResult.setAssistData(assistData);
rightResult.setDynamicAssistFields(assists);
}
List<ChartSeniorAssistDTO> assistsOriginList = rightAssistFields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assistsOriginList)) {
var assistSqlOriginList = assistSQLOriginList(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSqlOriginList);
logger.debug("calcite assistSql sql origin list: " + assistSqlOriginList);
var assistDataOriginList = (List<String[]>) provider.fetchResultField(req).get("data");
rightResult.setAssistDataOriginList(assistDataOriginList);
rightResult.setDynamicAssistFieldsOriginList(assistsOriginList);
}
}
} catch (Exception e) {
e.printStackTrace();
}
var mixResult = (T) new ChartCalcDataResult();
var data = new HashMap<String, Object>();
data.put("left", leftResult);
data.put("right", rightResult);
mixResult.setData(data);
mixResult.setContext(filterResult.getContext());
return mixResult;
}
@Override
public ChartViewDTO buildChart(ChartViewDTO view, ChartCalcDataResult calcResult, AxisFormatResult formatResult, CustomFilterResult filterResult) {
var desensitizationList = (Map<String, ColumnPermissionItem>) filterResult.getContext().get("desensitizationList");
var leftCalcResult = (ChartCalcDataResult) calcResult.getData().get("left");
var leftFields = new ArrayList<ChartViewFieldDTO>();
leftFields.addAll(formatResult.getAxisMap().get(ChartAxis.xAxis));
leftFields.addAll(formatResult.getAxisMap().get(ChartAxis.yAxis));
List<ChartSeniorAssistDTO> chartSeniorAssistDTOSLeft = mergeAssistField(leftCalcResult.getDynamicAssistFields(), leftCalcResult.getAssistData(), leftCalcResult.getDynamicAssistFieldsOriginList(), leftCalcResult.getAssistDataOriginList());
var leftOriginData = leftCalcResult.getOriginData();
var leftTable = ChartDataBuild.transTableNormal(leftFields, view, leftOriginData, desensitizationList);
var leftData = new HashMap<String, Object>(leftTable);
leftData.putAll(leftCalcResult.getData());
leftData.put("dynamicAssistLines", chartSeniorAssistDTOSLeft);
var rightCalcResult = (ChartCalcDataResult) calcResult.getData().get("right");
var rightFields = new ArrayList<ChartViewFieldDTO>();
var subAxisMap = (HashMap<ChartAxis, List<ChartViewFieldDTO>>) formatResult.getContext().get("subAxisMap");
rightFields.addAll(subAxisMap.get(ChartAxis.xAxis));
rightFields.addAll(subAxisMap.get(ChartAxis.yAxis));
List<ChartSeniorAssistDTO> chartSeniorAssistDTOSRight = mergeAssistField(rightCalcResult.getDynamicAssistFields(), rightCalcResult.getAssistData(), rightCalcResult.getDynamicAssistFieldsOriginList(), rightCalcResult.getAssistDataOriginList());
var rightOriginData = rightCalcResult.getOriginData();
var rightTable = ChartDataBuild.transTableNormal(rightFields, view, rightOriginData, desensitizationList);
var rightData = new HashMap<String, Object>(rightTable);
rightData.putAll(rightCalcResult.getData());
rightData.put("dynamicAssistLines", chartSeniorAssistDTOSRight);
// 构建结果
Map<String, Object> chartData = new TreeMap<>();
chartData.put("left", leftData);
chartData.put("right", rightData);
var drillFilters = filterResult.getFilterList().stream().filter(f -> f.getFilterType() == 1).collect(Collectors.toList());
// 日期下钻替换回去
drillFilters.forEach(f -> {
if (CollectionUtils.isNotEmpty(f.getOriginValue())) {
f.setValue(f.getOriginValue());
}
});
var isDrill = CollectionUtils.isNotEmpty(drillFilters);
view.setDrillFilters(drillFilters);
view.setDrill(isDrill);
view.setSql(Base64.getEncoder().encodeToString(leftCalcResult.getQuerySql().getBytes()));
view.setData(chartData);
return view;
}
}

View File

@ -0,0 +1,72 @@
package com.stdproject.charts.impl.mix;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class StackMixHandler extends MixHandler {
@Getter
private final String type = "chart-mix-stack";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var context = new HashMap<String, Object>();
AxisFormatResult result = new AxisFormatResult(axisMap, context);
//左轴分组子维度,非分组不需要
axisMap.put(ChartAxis.xAxisExt, Collections.emptyList());
//左轴堆叠子维度,非堆叠不需要
axisMap.put(ChartAxis.extStack, view.getExtStack());
//左轴指标
axisMap.put(ChartAxis.yAxis, view.getYAxis());
//右轴分组子维度
axisMap.put(ChartAxis.extBubble, view.getExtBubble());
//右轴指标
axisMap.put(ChartAxis.yAxisExt, view.getYAxisExt());
//去除除了x轴以外的排序
axisMap.forEach((k, v) -> {
if (!ChartAxis.extStack.equals(k)) {
v.forEach(x -> x.setSort("none"));
}
});
axisMap.put(ChartAxis.extLabel, view.getExtLabel());
axisMap.put(ChartAxis.extTooltip, view.getExtTooltip());
//图表整体主维度
var xAxis = new ArrayList<>(view.getXAxis());
var xAxisStack = new ArrayList<>(view.getXAxis());
xAxisStack.addAll(view.getExtStack());
axisMap.put(ChartAxis.xAxis, xAxisStack);
context.put("xAxisBase", xAxis);
axisMap.put(ChartAxis.drill, new ArrayList<>(view.getDrillFields()));
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
if (CollectionUtils.isNotEmpty(extStack)) {
// 堆叠左轴
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var drillAxis = xAxis.stream().filter(axis -> FieldSource.DRILL == axis.getSource()).toList();
var xAxisBase = xAxis.subList(0, xAxis.size() - extStack.size() - drillAxis.size());
//var xAxisBase = (List<ChartViewFieldDTO>) formatResult.getContext().get("xAxisBase");
return ChartDataBuild.transMixChartStackDataAntV(xAxisBase, xAxis, extStack, yAxis, view, data, isDrill);
} else {
//无堆叠左轴和右轴还是走原逻辑
var xAxisBase = (List<ChartViewFieldDTO>) formatResult.getContext().get("xAxisBase");
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
return super.buildNormalResult(view, formatResult, filterResult, data);
}
}
}

View File

@ -0,0 +1,45 @@
package com.stdproject.charts.impl.numeric;
import com.stdproject.service.manage.DatasetTableFieldManage;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import io.gisbi.extensions.view.dto.ChartViewFieldDTO;
import jakarta.annotation.Resource;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class GaugeHandler extends NumericalChartHandler {
@Getter
private String type = "gauge";
@Resource
private DatasetTableFieldManage datasetTableFieldManage;
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var yAxis = new ArrayList<>(view.getYAxis());
Map<String, Object> customAttr = view.getCustomAttr();
Map<String, Object> size = (Map<String, Object>) customAttr.get("misc");
ChartViewFieldDTO gaugeMinViewField = getDynamicField(size, "gaugeMinType", "gaugeMinField");
if (gaugeMinViewField != null) {
yAxis.add(gaugeMinViewField);
}
ChartViewFieldDTO gaugeMaxViewField = getDynamicField(size, "gaugeMaxType", "gaugeMaxField");
if (gaugeMaxViewField != null) {
yAxis.add(gaugeMaxViewField);
}
axisMap.put(ChartAxis.xAxis, new ArrayList<>());
axisMap.put(ChartAxis.yAxis, yAxis);
var context = new HashMap<String, Object>();
var result = new AxisFormatResult(axisMap, context);
return result;
}
}

View File

@ -0,0 +1,65 @@
package com.stdproject.charts.impl.numeric;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class IndicatorHandler extends YoyChartHandler {
@Getter
private String render = "custom";
@Getter
private String type = "indicator";
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult.getFilterList().stream().anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
return ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isDrill);
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
this.setIndicatorHandlerXAxis(formatResult, filterResult);
return (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
}
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var yAxis = new ArrayList<>(view.getYAxis());
axisMap.put(ChartAxis.xAxis, new ArrayList<>());
axisMap.put(ChartAxis.yAxis, yAxis);
var context = new HashMap<String, Object>();
return new AxisFormatResult(axisMap, context);
}
private void setIndicatorHandlerXAxis(AxisFormatResult formatResult, CustomFilterResult filterResult) {
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
ChartViewFieldDTO yAxisChartViewFieldDTO = yAxis.get(0);
ChartFieldCompareDTO compareCalc = yAxisChartViewFieldDTO.getCompareCalc();
boolean isYoy = org.apache.commons.lang3.StringUtils.isNotEmpty(compareCalc.getType())
&& !org.apache.commons.lang3.StringUtils.equalsIgnoreCase(compareCalc.getType(), "none");
if (isYoy) {
xAxis.clear();
// 设置维度字段从同环比中获取用户选择的字段
xAxis.addAll(allFields.stream().filter(i -> org.springframework.util.StringUtils.endsWithIgnoreCase(i.getId().toString(), compareCalc.getField().toString())).toList());
xAxis.get(0).setSort("desc");
if(Objects.isNull(compareCalc.getCustom())){
xAxis.get(0).setDateStyle("y_M_d");
}else{
xAxis.get(0).setDateStyle(compareCalc.getCustom().getTimeType());
}
}
formatResult.getAxisMap().put(ChartAxis.xAxis, xAxis);
}
}

View File

@ -0,0 +1,36 @@
package com.stdproject.charts.impl.numeric;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import io.gisbi.extensions.view.dto.ChartViewFieldDTO;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class LiquidHandler extends NumericalChartHandler {
@Getter
private String type = "liquid";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
var yAxis = new ArrayList<>(view.getYAxis());
Map<String, Object> customAttr = view.getCustomAttr();
Map<String, Object> misc = (Map<String, Object>) customAttr.get("misc");
ChartViewFieldDTO liquidMaxViewField = getDynamicField(misc, "liquidMaxType", "liquidMaxField");
if (liquidMaxViewField != null) {
yAxis.add(liquidMaxViewField);
}
axisMap.put(ChartAxis.xAxis, new ArrayList<>());
axisMap.put(ChartAxis.yAxis, yAxis);
var context = new HashMap<String, Object>();
var result = new AxisFormatResult(axisMap, context);
return result;
}
}

View File

@ -0,0 +1,84 @@
package com.stdproject.charts.impl.numeric;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.service.manage.DefaultChartHandler;
import com.stdproject.service.provider.SQLProvider;
import com.stdproject.utils.ChartDataBuild;
import com.stdproject.utils.Utils;
import com.stdproject.utils.trans.Quota2SQLObj;
import io.gisbi.exception.DEException;
import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import io.gisbi.extensions.view.util.FieldUtil;
import io.gisbi.i18n.Translator;
import io.gisbi.utils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class NumericalChartHandler extends DefaultChartHandler {
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = Utils.isCrossDs(dsMap);
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setIsCross(((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross());
datasourceRequest.setDsList(dsMap);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
datasourceRequest.setQuery(querySql);
logger.debug("calcite chart sql: " + querySql);
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
boolean isdrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
Map<String, Object> result = ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isdrill);
T calcResult = (T) new ChartCalcDataResult();
calcResult.setData(result);
calcResult.setContext(filterResult.getContext());
calcResult.setQuerySql(querySql);
calcResult.setOriginData(data);
return calcResult;
}
protected ChartViewFieldDTO getDynamicField(Map<String, Object> target, String type, String field) {
String maxType = (String) target.get(type);
if (StringUtils.equalsIgnoreCase("dynamic", maxType)) {
Map<String, Object> maxField = (Map<String, Object>) target.get(field);
if (maxField.get("id") == null || StringUtils.isEmpty(maxField.get("id").toString())) {
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
}
Long id = Long.valueOf((String) maxField.get("id"));
String summary = (String) maxField.get("summary");
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(id);
if (ObjectUtils.isNotEmpty(datasetTableField)) {
ChartViewFieldDTO dto = new ChartViewFieldDTO();
BeanUtils.copyBean(dto, datasetTableField);
if (StringUtils.isEmpty(dto.getSummary())) {
dto.setSummary(summary);
}
return dto;
} else {
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
}
}
return null;
}
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class FunnelHandler extends ExtQuotaChartHandler {
@Getter
private String type = "funnel";
}

View File

@ -0,0 +1,25 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.YoyChartHandler;
import io.gisbi.extensions.view.dto.AxisFormatResult;
import io.gisbi.extensions.view.dto.ChartAxis;
import io.gisbi.extensions.view.dto.ChartViewDTO;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class RadarHandler extends YoyChartHandler {
@Getter
private String type = "radar";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
return result;
}
}

View File

@ -0,0 +1,13 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.YoyChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class RichTextHandler extends YoyChartHandler {
@Getter
private String type = "rich-text";
@Getter
private String render = "custom";
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.GroupChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class SankeyHandler extends GroupChartHandler {
@Getter
private String type = "sankey";
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class TreemapHandler extends ExtQuotaChartHandler {
@Getter
private String type = "treemap";
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class WaterfallHandler extends ExtQuotaChartHandler {
@Getter
private String type = "waterfall";
}

View File

@ -0,0 +1,11 @@
package com.stdproject.charts.impl.others;
import com.stdproject.charts.impl.ExtQuotaChartHandler;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Component
public class WordCloudHandler extends ExtQuotaChartHandler {
@Getter
private String type = "word-cloud";
}

View File

@ -0,0 +1,103 @@
package com.stdproject.charts.impl.pie;
import com.stdproject.charts.impl.YoyChartHandler;
import io.gisbi.extensions.view.dto.*;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Component
public class PieHandler extends YoyChartHandler {
@Override
public void init() {
chartHandlerManager.registerChartHandler(this.getRender(), "pie", this);
chartHandlerManager.registerChartHandler(this.getRender(), "pie-rose", this);
chartHandlerManager.registerChartHandler(this.getRender(), "pie-donut", this);
chartHandlerManager.registerChartHandler(this.getRender(), "pie-donut-rose", this);
}
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
return result;
}
@Override
public ChartViewDTO buildChart(ChartViewDTO view, ChartCalcDataResult calcResult, AxisFormatResult formatResult, CustomFilterResult filterResult) {
ChartViewDTO result = super.buildChart(view, calcResult, formatResult, filterResult);
filterPositiveData(result, "data", AxisChartDataAntVDTO.class);
filterPositiveData(result, "tableRow", Map.class, view.getYAxis().get(0).getGisbiName());
return result;
}
/**
* 过滤正数数据根据data
* @param result
* @param key
* @param clazz
* @param <T>
*/
private <T> void filterPositiveData(ChartViewDTO result, String key, Class<T> clazz) {
if (result.getData().containsKey(key)) {
List<T> list = ((List<T>) result.getData().get(key))
.stream()
.filter(item -> {
if (clazz == AxisChartDataAntVDTO.class) {
if (Objects.isNull(((AxisChartDataAntVDTO) item).getValue())) return false;
return ((AxisChartDataAntVDTO) item).getValue().compareTo(BigDecimal.ZERO) >= 0;
} else if (clazz == Map.class) {
return isPositive(((Map<String, Object>) item).get("value"));
}
return false;
})
.collect(Collectors.toList());
result.getData().put(key, list);
}
}
/**
* 过滤正数数据根据tableRow
* @param result
* @param key
* @param clazz
* @param yAxisName
* @param <T>
*/
private <T> void filterPositiveData(ChartViewDTO result, String key, Class<T> clazz, String yAxisName) {
if (result.getData().containsKey(key)) {
List<T> list = ((List<T>) result.getData().get(key))
.stream()
.filter(item -> {
if (clazz == Map.class) {
Object value = ((Map<String, Object>) item).get(yAxisName);
return isPositive(value);
}
return false;
})
.collect(Collectors.toList());
result.getData().put(key, list);
}
}
private boolean isPositive(Object value) {
if (value instanceof String) {
try {
return new BigDecimal((String) value).compareTo(BigDecimal.ZERO) >= 0;
} catch (NumberFormatException e) {
return false;
}
} else if (value instanceof BigDecimal) {
return ((BigDecimal) value).compareTo(BigDecimal.ZERO) >= 0;
}
return false;
}
}

View File

@ -0,0 +1,40 @@
package com.stdproject.charts.impl.scatter;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class QuadrantHandler extends YoyChartHandler {
@Getter
private String type = "quadrant";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var yAxis = new ArrayList<>(view.getYAxis());
yAxis.addAll(view.getYAxisExt());
yAxis.addAll(view.getExtBubble());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
result.getAxisMap().put(ChartAxis.extBubble, view.getExtBubble());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
result.getAxisMap().put(ChartAxis.yAxisExt, view.getYAxisExt());
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult.getFilterList().stream().anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
Map<String, Object> result = ChartDataBuild.transMixChartDataAntV(xAxis, xAxis, new ArrayList<>(), yAxis, view, data, isDrill);
return result;
}
}

View File

@ -0,0 +1,54 @@
package com.stdproject.charts.impl.scatter;
import com.stdproject.charts.impl.YoyChartHandler;
import com.stdproject.utils.ChartDataBuild;
import io.gisbi.extensions.view.dto.*;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Component
public class ScatterHandler extends YoyChartHandler {
@Getter
private String type = "scatter";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var yAxis = new ArrayList<>(view.getYAxis());
yAxis.addAll(view.getExtBubble());
yAxis.addAll(view.getExtLabel());
yAxis.addAll(view.getExtTooltip());
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
result.getAxisMap().put(ChartAxis.extBubble, view.getExtBubble());
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
return result;
}
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult.getFilterList().stream().anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var yAxisTemp = new ArrayList<>(yAxis);
var extBubble = formatResult.getAxisMap().get(ChartAxis.extBubble);
if (!extBubble.isEmpty()) {
// 剔除气泡大小移除一个
Iterator<ChartViewFieldDTO> iterator = yAxisTemp.iterator();
while (iterator.hasNext()) {
ChartViewFieldDTO obj = iterator.next();
if (obj.getId().equals(extBubble.getFirst().getId())) {
iterator.remove();
break;
}
}
}
Map<String, Object> result = ChartDataBuild.transScatterDataAntV(xAxis, yAxisTemp, view, data, extBubble, isDrill);
return result;
}
}

View File

@ -0,0 +1,85 @@
package com.stdproject.charts.impl.table;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.service.manage.DefaultChartHandler;
import com.stdproject.service.provider.SQLProvider;
import com.stdproject.utils.ChartDataBuild;
import com.stdproject.utils.Utils;
import com.stdproject.utils.trans.Dimension2SQLObj;
import com.stdproject.utils.trans.Quota2SQLObj;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import io.gisbi.extensions.view.util.ChartDataUtil;
import io.gisbi.extensions.view.util.FieldUtil;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class TableHeatmapHandler extends DefaultChartHandler {
@Getter
private String type = "t-heatmap";
@Override
public AxisFormatResult formatAxis(ChartViewDTO view) {
var result = super.formatAxis(view);
var xAxis = new ArrayList<ChartViewFieldDTO>(view.getXAxis());
xAxis.addAll(view.getXAxisExt());
var yAxis = new ArrayList<ChartViewFieldDTO>(view.getYAxis());
yAxis.addAll(view.getExtColor());
result.getAxisMap().put(ChartAxis.xAxis, xAxis);
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
return result;
}
public Map<String, Object> buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
Map<String, Object> result = ChartDataBuild.transChartData( xAxis, new ArrayList<>(), view, data, false);
return result;
}
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = Utils.isCrossDs(dsMap);
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setIsCross(((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross());
datasourceRequest.setDsList(dsMap);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
datasourceRequest.setQuery(querySql);
logger.debug("calcite chart sql: " + querySql);
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
//自定义排序
data = ChartDataUtil.resultCustomSort(xAxis, yAxis, view.getSortPriority(), data);
//数据重组逻辑可重载
var result = this.buildResult(view, formatResult, filterResult, data);
T calcResult = (T) new ChartCalcDataResult();
calcResult.setData(result);
calcResult.setContext(filterResult.getContext());
calcResult.setQuerySql(querySql);
calcResult.setOriginData(data);
return calcResult;
}
}

View File

@ -0,0 +1,377 @@
package com.stdproject.charts.impl.table;
import com.stdproject.charts.impl.GroupChartHandler;
import com.stdproject.constant.ExtFieldConstant;
import com.stdproject.entity.union.DatasetGroupInfoDTO;
import com.stdproject.service.provider.SQLProvider;
import com.stdproject.utils.Utils;
import com.stdproject.utils.trans.Dimension2SQLObj;
import com.stdproject.utils.trans.Quota2SQLObj;
import io.gisbi.constant.DeTypeConstants;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.model.SQLMeta;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.extensions.view.dto.*;
import io.gisbi.extensions.view.util.FieldUtil;
import io.gisbi.utils.BeanUtils;
import io.gisbi.utils.IDUtils;
import io.gisbi.utils.JsonUtil;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class TablePivotHandler extends GroupChartHandler {
@Getter
private String type = "table-pivot";
@Override
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
T result = super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
Map<String, Object> customCalc = calcCustomExpr(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
result.getData().put("customCalc", customCalc);
try {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
var originSql = result.getQuerySql();
var dynamicAssistFields = getDynamicThresholdFields(view);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var assistFields = getAssistFields(dynamicAssistFields, yAxis);
if (CollectionUtils.isNotEmpty(assistFields)) {
var req = new DatasourceRequest();
req.setIsCross(crossDs);
req.setDsList(dsMap);
List<ChartSeniorAssistDTO> assists = dynamicAssistFields.stream().filter(ele -> !StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assists)) {
var assistSql = assistSQL(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSql);
logger.debug("calcite assistSql sql: " + assistSql);
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistData(assistData);
result.setDynamicAssistFields(assists);
}
List<ChartSeniorAssistDTO> assistsOriginList = dynamicAssistFields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getSummary(), "last_item")).toList();
if (ObjectUtils.isNotEmpty(assistsOriginList)) {
var assistSqlOriginList = assistSQLOriginList(originSql, assistFields, dsMap, crossDs);
req.setQuery(assistSqlOriginList);
logger.debug("calcite assistSql sql origin list: " + assistSqlOriginList);
var assistDataOriginList = (List<String[]>) provider.fetchResultField(req).get("data");
result.setAssistDataOriginList(assistDataOriginList);
result.setDynamicAssistFieldsOriginList(assistsOriginList);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
public Map<String, Object> buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
var result = new HashMap<String, Object>();
var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null;
// 带过滤同环比直接返回原始数据,再由视图重新组装
if (yoyFiltered) {
result.put("data", data);
}
return result;
}
private Map<String, Object> calcCustomExpr(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
Object totalStr = JsonUtil.toJSONString(view.getCustomAttr().get("tableTotal"));
TableTotal tableTotal = JsonUtil.parseObject((String) totalStr, TableTotal.class);
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
dsList.add(next.getValue().getType());
}
boolean needOrder = Utils.isNeedOrder(dsList);
boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross();
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDsList(dsMap);
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
var rowAxis = view.getXAxis();
var colAxis = view.getXAxisExt();
var dataMap = new HashMap<String, Object>();
if (CollectionUtils.isEmpty(rowAxis)) {
return dataMap;
}
// 行总计列维度聚合加上自定义字段
var row = tableTotal.getRow();
if (row.isShowGrandTotals()) {
var yAxis = getCustomFields(view, row.getCalcTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var result = getData(sqlMeta, colAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
dataMap.put("rowTotal", tmp);
tmp.put("data", buildCustomCalcResult(data, colAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
}
}
// 行小计列维度聚合自定义指标数 * (行维度的数量 - 1)
if (row.isShowSubTotals()) {
var yAxis = getCustomFields(view, row.getCalcSubTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpData = new ArrayList<Map<String, Object>>();
dataMap.put("rowSubTotal", tmpData);
for (int i = 0; i < rowAxis.size(); i++) {
if (i == rowAxis.size() - 1) {
break;
}
var xAxis = new ArrayList<>(colAxis);
var subRowAxis = rowAxis.subList(0, i + 1);
xAxis.addAll(subRowAxis);
if (!yAxis.isEmpty()) {
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var result = getData(sqlMeta, xAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
tmpData.add(tmp);
}
}
}
}
// 列总计行维度聚合加上自定义字段
var col = tableTotal.getCol();
if (col.isShowGrandTotals() && CollectionUtils.isNotEmpty(colAxis)) {
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var result = getData(sqlMeta, rowAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
dataMap.put("colTotal", tmp);
tmp.put("data", buildCustomCalcResult(data, rowAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
}
}
// 列小计行维度聚合自定义指标数 * (列维度的数量 - 1)
if (col.isShowSubTotals() && colAxis.size() >= 2) {
var yAxis = getCustomFields(view, col.getCalcSubTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpData = new ArrayList<Map<String, Object>>();
dataMap.put("colSubTotal", tmpData);
for (int i = 0; i < colAxis.size(); i++) {
if (i == colAxis.size() - 1) {
break;
}
var xAxis = new ArrayList<>(rowAxis);
var subColAxis = colAxis.subList(0, i + 1);
xAxis.addAll(subColAxis);
if (!yAxis.isEmpty()) {
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var result = getData(sqlMeta, xAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
tmpData.add(tmp);
}
}
}
}
// 行列交叉部分总计无聚合直接算用列总计公式
if (row.isShowGrandTotals() && col.isShowGrandTotals()) {
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
if (!yAxis.isEmpty()) {
// 清掉聚合轴
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var result = getData(sqlMeta, Collections.emptyList(), yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
dataMap.put("rowColTotal", tmp);
var tmpData = new HashMap<String, String>();
for (int i = 0; i < yAxis.size(); i++) {
var a = yAxis.get(i);
tmpData.put(a.getGisbiName(), data.getFirst()[i]);
}
tmp.put("data", tmpData);
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
}
}
// 行总计里面的列小计
if (row.isShowGrandTotals() && col.isShowSubTotals() && colAxis.size() >= 2) {
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpData = new ArrayList<Map<String, Object>>();
dataMap.put("colSubInRowTotal", tmpData);
for (int i = 0; i < colAxis.size(); i++) {
if (i == colAxis.size() - 1) {
break;
}
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var xAxis = colAxis.subList(0, i + 1);
var result = getData(sqlMeta, xAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
tmpData.add(tmp);
}
}
}
// 列总计里面的行小计
if (col.isShowGrandTotals() && row.isShowSubTotals() && rowAxis.size() >= 2) {
var yAxis = getCustomFields(view, row.getCalcSubTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpData = new ArrayList<Map<String, Object>>();
dataMap.put("rowSubInColTotal", tmpData);
for (int i = 0; i < rowAxis.size(); i++) {
if (i == rowAxis.size() - 1) {
break;
}
var tmpList = new ArrayList<>(allFields);
tmpList.addAll(yAxis);
var xAxis = rowAxis.subList(0, i + 1);
var result = getData(sqlMeta, xAxis, yAxis, tmpList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
tmpData.add(tmp);
}
}
}
// 行小计和列小计相交部分
if (row.isShowSubTotals() && col.isShowSubTotals() && colAxis.size() >= 2 && rowAxis.size() >= 2) {
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
if (!yAxis.isEmpty()) {
var tmpData = new ArrayList<List<Map<String, Object>>>();
dataMap.put("rowSubInColSub", tmpData);
for (int i = 0; i < rowAxis.size(); i++) {
if (i == rowAxis.size() - 1) {
break;
}
var tmpList = new ArrayList<Map<String, Object>>();
tmpData.add(tmpList);
var subRow = rowAxis.subList(0, i + 1);
for (int j = 0; j < colAxis.size(); j++) {
if (j == colAxis.size() - 1) {
break;
}
var xAxis = new ArrayList<>(subRow);
var subCol = colAxis.subList(0, j + 1);
xAxis.addAll(subCol);
var tmpAllList = new ArrayList<>(allFields);
tmpAllList.addAll(yAxis);
var result = getData(sqlMeta, xAxis, yAxis, tmpAllList, crossDs, dsMap, view, provider, needOrder);
var querySql = result.getT1();
var data = result.getT2();
var tmp = new HashMap<String, Object>();
tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis));
tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes()));
tmpList.add(tmp);
}
}
}
}
return dataMap;
}
private Map<String, Object> buildCustomCalcResult(List<String[]> data, List<ChartViewFieldDTO> dimAxis, List<ChartViewFieldDTO> quotaAxis) {
var rootResult = new HashMap<String, Object>();
if (CollectionUtils.isEmpty(dimAxis)) {
var rowData = data.getFirst();
for (int i = 0; i < rowData.length; i++) {
var qAxis = quotaAxis.get(i);
rootResult.put(qAxis.getGisbiName(), rowData[i]);
}
return rootResult;
}
for (int i = 0; i < data.size(); i++) {
var rowData = data.get(i);
Map<String, Object> curSubMap = rootResult;
for (int j = 0; j < dimAxis.size(); j++) {
var tmpMap = curSubMap.get(rowData[j]);
if (tmpMap == null) {
tmpMap = new HashMap<String, Object>();
curSubMap.put(rowData[j], tmpMap);
curSubMap = (Map<String, Object>) tmpMap;
} else {
curSubMap = (Map<String, Object>) tmpMap;
}
if (j == dimAxis.size() - 1) {
for (int k = 0; k < quotaAxis.size(); k++) {
var qAxis = quotaAxis.get(k);
curSubMap.put(qAxis.getGisbiName(), rowData[j + k + 1]);
}
}
}
}
return rootResult;
}
private Tuple2<String, List<String[]>> getData(SQLMeta sqlMeta, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis,
List<ChartViewFieldDTO> allFields, boolean crossDs, Map<Long, DatasourceSchemaDTO> dsMap,
ChartViewDTO view, Provider provider, boolean needOrder) {
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setIsCross(crossDs);
datasourceRequest.setDsList(dsMap);
Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage);
String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
datasourceRequest.setQuery(querySql);
logger.debug("calcite chart sql: " + querySql);
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
nullToBlank(data);
return Tuples.of(querySql, data);
}
private void nullToBlank(List<String[]> data) {
data.forEach(r -> {
for (int i = 0; i < r.length; i++) {
if (r[i] == null) {
r[i] = "";
}
}
});
}
private List<ChartViewFieldDTO> getCustomFields(ChartViewDTO view, List<TableCalcTotalCfg> cfgList) {
var quotaIds = view.getYAxis().stream().map(ChartViewFieldDTO::getGisbiName).collect(Collectors.toSet());
var customFields = new ArrayList<ChartViewFieldDTO>();
for (TableCalcTotalCfg totalCfg : cfgList) {
if (!quotaIds.contains(totalCfg.getGisbiName())) {
continue;
}
if (StringUtils.equalsIgnoreCase(totalCfg.getAggregation(), "CUSTOM")) {
var field = new ChartViewFieldDTO();
field.setDeType(DeTypeConstants.DE_FLOAT);
BeanUtils.copyBean(field, totalCfg);
field.setId(IDUtils.snowID());
field.setExtField(ExtFieldConstant.EXT_CALC);
customFields.add(field);
}
}
return customFields;
}
}

View File

@ -280,11 +280,11 @@ private Long jwtExpirationMs;
} }
@GetMapping("/ipInfo") @GetMapping("/ipInfo")
public CurIpVO ipInfo() { public ResponseResult ipInfo() {
CurIpVO curIpVO = new CurIpVO(); CurIpVO curIpVO = new CurIpVO();
curIpVO.setAccount("admin"); curIpVO.setAccount("admin");
curIpVO.setName("管理员"); curIpVO.setName("管理员");
curIpVO.setIp(IPUtils.get()); curIpVO.setIp(IPUtils.get());
return curIpVO; return ResponseResult.successData(curIpVO);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ export default defineConfig({
cors: true, cors: true,
proxy: { proxy: {
'/api': { '/api': {
target: 'http://192.168.1.38:8083', target: 'http://192.168.1.20:8083',
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
rewrite: path => path.replace(/^\/api/, '') rewrite: path => path.replace(/^\/api/, '')