diff --git a/backend/src/main/java/com/stdproject/charts/impl/ExtQuotaChartHandler.java b/backend/src/main/java/com/stdproject/charts/impl/ExtQuotaChartHandler.java new file mode 100644 index 0000000..46e4a77 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/ExtQuotaChartHandler.java @@ -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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/GroupChartHandler.java b/backend/src/main/java/com/stdproject/charts/impl/GroupChartHandler.java new file mode 100644 index 0000000..fe95b91 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/GroupChartHandler.java @@ -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(view.getXAxis()); + xAxis.addAll(view.getXAxisExt()); + result.getAxisMap().put(ChartAxis.xAxis, xAxis); + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/YoyChartHandler.java b/backend/src/main/java/com/stdproject/charts/impl/YoyChartHandler.java new file mode 100644 index 0000000..93d9c3a --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/YoyChartHandler.java @@ -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 customFilter(ChartViewDTO view, List 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 originFilter = JsonUtil.parseList(originFilterJson, new TypeReference<>() { + }); + formatResult.getContext().put("originFilter", originFilter); + formatResult.getContext().put("yoyFiltered", true); + } + return (T) result; + } + + @Override + public Map buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null; + // 带过滤同环比直接返回原始数据,再由视图重新组装 + if (yoyFiltered) { + var result = new HashMap(); + result.put("data", data); + return result; + } + return buildNormalResult(view, formatResult, filterResult, data); + } + + /** + * 构建同环比类型的数据 + * + * @param view 视图对象 + * @param formatResult 处理后的轴 + * @param filterResult 处理后的过滤器 + * @param data 原始数据 + * @return 视图构建结果 + */ + public Map buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + return super.buildResult(view, formatResult, filterResult, data); + } + + @Override + public T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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) filterResult.getContext().get("originFilter"); + var allFields = (List) 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) provider.fetchResultField(request).get("data"); + List resultData = new ArrayList<>(); + // 包含一年前的数据, 已计算同环比 + var yoyData = (List) 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 sortData(ChartViewDTO view, List data, AxisFormatResult formatResult) { + // 维度排序 + List xAxisSortList = view.getXAxis().stream().filter(x -> !StringUtils.equalsIgnoreCase("none", x.getSort())).toList(); + // 指标排序 + List 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 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 sortData(List data, boolean ascending, int index) { + Comparator 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 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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/line/AreaHandler.java b/backend/src/main/java/com/stdproject/charts/impl/line/AreaHandler.java new file mode 100644 index 0000000..60573a2 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/line/AreaHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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); + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/line/LineHandler.java b/backend/src/main/java/com/stdproject/charts/impl/line/LineHandler.java new file mode 100644 index 0000000..937f8e9 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/line/LineHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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 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) provider.fetchResultField(req).get("data"); + result.setAssistData(assistData); + result.setDynamicAssistFields(assists); + } + + List 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) provider.fetchResultField(req).get("data"); + result.setAssistDataOriginList(assistDataOriginList); + result.setDynamicAssistFieldsOriginList(assistsOriginList); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/line/StackAreaHandler.java b/backend/src/main/java/com/stdproject/charts/impl/line/StackAreaHandler.java new file mode 100644 index 0000000..02ebd23 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/line/StackAreaHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 customFilter(ChartViewDTO view, List filterList, AxisFormatResult formatResult) { + var result = super.customFilter(view, filterList, formatResult); + List drillRequestList = view.getChartExtRequest().getDrill(); + var drillFields = formatResult.getAxisMap().get(ChartAxis.drill); + // 堆叠维度下钻 + if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) { + List 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 drillFilters = new ArrayList<>(); + ArrayList 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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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 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) provider.fetchResultField(req).get("data"); + result.setAssistData(assistData); + result.setDynamicAssistFields(assists); + } + + List 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) provider.fetchResultField(req).get("data"); + result.setAssistDataOriginList(assistDataOriginList); + result.setDynamicAssistFieldsOriginList(assistsOriginList); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/map/BubbleMapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/map/BubbleMapHandler.java new file mode 100644 index 0000000..891dec4 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/map/BubbleMapHandler.java @@ -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); + } +} + + diff --git a/backend/src/main/java/com/stdproject/charts/impl/map/FlowMapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/map/FlowMapHandler.java new file mode 100644 index 0000000..7202e7a --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/map/FlowMapHandler.java @@ -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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/map/HeatMapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/map/HeatMapHandler.java new file mode 100644 index 0000000..10f6eac --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/map/HeatMapHandler.java @@ -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 buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 result = ChartDataBuild.transHeatMapChartDataAntV(xAxis, xAxis, yAxis, view, data, isDrill); + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/map/MapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/map/MapHandler.java new file mode 100644 index 0000000..b34078d --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/map/MapHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/mix/DualLineMixHandler.java b/backend/src/main/java/com/stdproject/charts/impl/mix/DualLineMixHandler.java new file mode 100644 index 0000000..9124381 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/mix/DualLineMixHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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); + } + +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/mix/GroupMixHandler.java b/backend/src/main/java/com/stdproject/charts/impl/mix/GroupMixHandler.java new file mode 100644 index 0000000..c256dd1 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/mix/GroupMixHandler.java @@ -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>(); + var context = new HashMap(); + 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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + return super.buildNormalResult(view, formatResult, filterResult, data); + } + +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/mix/MixHandler.java b/backend/src/main/java/com/stdproject/charts/impl/mix/MixHandler.java new file mode 100644 index 0000000..0214022 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/mix/MixHandler.java @@ -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>(); + var context = new HashMap(); + 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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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) 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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + //计算左轴, 包含 xAxis, yAxis + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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 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) provider.fetchResultField(req).get("data"); + leftResult.setAssistData(assistData); + leftResult.setDynamicAssistFields(assists); + } + + List 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) provider.fetchResultField(req).get("data"); + leftResult.setAssistDataOriginList(assistDataOriginList); + leftResult.setDynamicAssistFieldsOriginList(assistsOriginList); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + AxisFormatResult formatResult2 = new AxisFormatResult(); + var axisMap = new HashMap>(); + 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) 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 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) provider.fetchResultField(req).get("data"); + rightResult.setAssistData(assistData); + rightResult.setDynamicAssistFields(assists); + } + + List 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) 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(); + 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) filterResult.getContext().get("desensitizationList"); + var leftCalcResult = (ChartCalcDataResult) calcResult.getData().get("left"); + var leftFields = new ArrayList(); + leftFields.addAll(formatResult.getAxisMap().get(ChartAxis.xAxis)); + leftFields.addAll(formatResult.getAxisMap().get(ChartAxis.yAxis)); + List 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(leftTable); + leftData.putAll(leftCalcResult.getData()); + leftData.put("dynamicAssistLines", chartSeniorAssistDTOSLeft); + + var rightCalcResult = (ChartCalcDataResult) calcResult.getData().get("right"); + var rightFields = new ArrayList(); + + var subAxisMap = (HashMap>) formatResult.getContext().get("subAxisMap"); + rightFields.addAll(subAxisMap.get(ChartAxis.xAxis)); + rightFields.addAll(subAxisMap.get(ChartAxis.yAxis)); + + List 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(rightTable); + rightData.putAll(rightCalcResult.getData()); + rightData.put("dynamicAssistLines", chartSeniorAssistDTOSRight); + + // 构建结果 + Map 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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/mix/StackMixHandler.java b/backend/src/main/java/com/stdproject/charts/impl/mix/StackMixHandler.java new file mode 100644 index 0000000..eca72ad --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/mix/StackMixHandler.java @@ -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>(); + var context = new HashMap(); + 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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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) formatResult.getContext().get("xAxisBase"); + return ChartDataBuild.transMixChartStackDataAntV(xAxisBase, xAxis, extStack, yAxis, view, data, isDrill); + } else { + //无堆叠左轴和右轴还是走原逻辑 + var xAxisBase = (List) 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); + } + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/numeric/GaugeHandler.java b/backend/src/main/java/com/stdproject/charts/impl/numeric/GaugeHandler.java new file mode 100644 index 0000000..9ba9f44 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/numeric/GaugeHandler.java @@ -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>(); + var yAxis = new ArrayList<>(view.getYAxis()); + Map customAttr = view.getCustomAttr(); + Map size = (Map) 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(); + var result = new AxisFormatResult(axisMap, context); + return result; + } + +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/numeric/IndicatorHandler.java b/backend/src/main/java/com/stdproject/charts/impl/numeric/IndicatorHandler.java new file mode 100644 index 0000000..1c3560e --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/numeric/IndicatorHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map 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>(); + var yAxis = new ArrayList<>(view.getYAxis()); + axisMap.put(ChartAxis.xAxis, new ArrayList<>()); + axisMap.put(ChartAxis.yAxis, yAxis); + var context = new HashMap(); + 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) 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); + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/numeric/LiquidHandler.java b/backend/src/main/java/com/stdproject/charts/impl/numeric/LiquidHandler.java new file mode 100644 index 0000000..e17b039 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/numeric/LiquidHandler.java @@ -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>(); + var yAxis = new ArrayList<>(view.getYAxis()); + Map customAttr = view.getCustomAttr(); + Map misc = (Map) 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(); + var result = new AxisFormatResult(axisMap, context); + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/numeric/NumericalChartHandler.java b/backend/src/main/java/com/stdproject/charts/impl/numeric/NumericalChartHandler.java new file mode 100644 index 0000000..9ea76e1 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/numeric/NumericalChartHandler.java @@ -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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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) 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 data = (List) provider.fetchResultField(datasourceRequest).get("data"); + boolean isdrill = filterResult + .getFilterList() + .stream() + .anyMatch(ele -> ele.getFilterType() == 1); + Map 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 target, String type, String field) { + String maxType = (String) target.get(type); + if (StringUtils.equalsIgnoreCase("dynamic", maxType)) { + Map maxField = (Map) 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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/FunnelHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/FunnelHandler.java new file mode 100644 index 0000000..ec2cdb3 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/FunnelHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/RadarHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/RadarHandler.java new file mode 100644 index 0000000..e2f261d --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/RadarHandler.java @@ -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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/RichTextHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/RichTextHandler.java new file mode 100644 index 0000000..d030af2 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/RichTextHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/SankeyHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/SankeyHandler.java new file mode 100644 index 0000000..b20abeb --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/SankeyHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/TreemapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/TreemapHandler.java new file mode 100644 index 0000000..7e198c6 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/TreemapHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/WaterfallHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/WaterfallHandler.java new file mode 100644 index 0000000..aa910ae --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/WaterfallHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/others/WordCloudHandler.java b/backend/src/main/java/com/stdproject/charts/impl/others/WordCloudHandler.java new file mode 100644 index 0000000..569f4e0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/others/WordCloudHandler.java @@ -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"; +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/pie/PieHandler.java b/backend/src/main/java/com/stdproject/charts/impl/pie/PieHandler.java new file mode 100644 index 0000000..a11b33b --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/pie/PieHandler.java @@ -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 + */ + private void filterPositiveData(ChartViewDTO result, String key, Class clazz) { + if (result.getData().containsKey(key)) { + List list = ((List) 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) item).get("value")); + } + return false; + }) + .collect(Collectors.toList()); + result.getData().put(key, list); + } + } + + /** + * 过滤正数数据根据tableRow + * @param result + * @param key + * @param clazz + * @param yAxisName + * @param + */ + private void filterPositiveData(ChartViewDTO result, String key, Class clazz, String yAxisName) { + if (result.getData().containsKey(key)) { + List list = ((List) result.getData().get(key)) + .stream() + .filter(item -> { + if (clazz == Map.class) { + Object value = ((Map) 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; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/scatter/QuadrantHandler.java b/backend/src/main/java/com/stdproject/charts/impl/scatter/QuadrantHandler.java new file mode 100644 index 0000000..2767015 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/scatter/QuadrantHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 result = ChartDataBuild.transMixChartDataAntV(xAxis, xAxis, new ArrayList<>(), yAxis, view, data, isDrill); + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/scatter/ScatterHandler.java b/backend/src/main/java/com/stdproject/charts/impl/scatter/ScatterHandler.java new file mode 100644 index 0000000..5d1c334 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/scatter/ScatterHandler.java @@ -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 buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List 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 iterator = yAxisTemp.iterator(); + while (iterator.hasNext()) { + ChartViewFieldDTO obj = iterator.next(); + if (obj.getId().equals(extBubble.getFirst().getId())) { + iterator.remove(); + break; + } + } + } + Map result = ChartDataBuild.transScatterDataAntV(xAxis, yAxisTemp, view, data, extBubble, isDrill); + return result; + } +} diff --git a/backend/src/main/java/com/stdproject/charts/impl/table/TableHeatmapHandler.java b/backend/src/main/java/com/stdproject/charts/impl/table/TableHeatmapHandler.java new file mode 100644 index 0000000..d4a75a0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/table/TableHeatmapHandler.java @@ -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(view.getXAxis()); + xAxis.addAll(view.getXAxisExt()); + var yAxis = new ArrayList(view.getYAxis()); + yAxis.addAll(view.getExtColor()); + result.getAxisMap().put(ChartAxis.xAxis, xAxis); + result.getAxisMap().put(ChartAxis.yAxis, yAxis); + return result; + } + + public Map buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis); + Map result = ChartDataBuild.transChartData( xAxis, new ArrayList<>(), view, data, false); + return result; + } + + @Override + public T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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) 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 data = (List) 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; + } + +} + + diff --git a/backend/src/main/java/com/stdproject/charts/impl/table/TablePivotHandler.java b/backend/src/main/java/com/stdproject/charts/impl/table/TablePivotHandler.java new file mode 100644 index 0000000..5646c41 --- /dev/null +++ b/backend/src/main/java/com/stdproject/charts/impl/table/TablePivotHandler.java @@ -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 calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + T result = super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider); + Map 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) 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 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) provider.fetchResultField(req).get("data"); + result.setAssistData(assistData); + result.setDynamicAssistFields(assists); + } + + List 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) provider.fetchResultField(req).get("data"); + result.setAssistDataOriginList(assistDataOriginList); + result.setDynamicAssistFieldsOriginList(assistsOriginList); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + @Override + public Map buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + var result = new HashMap(); + var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null; + // 带过滤同环比直接返回原始数据,再由视图重新组装 + if (yoyFiltered) { + result.put("data", data); + } + return result; + } + + private Map calcCustomExpr(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + Object totalStr = JsonUtil.toJSONString(view.getCustomAttr().get("tableTotal")); + TableTotal tableTotal = JsonUtil.parseObject((String) totalStr, TableTotal.class); + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry 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) filterResult.getContext().get("allFields"); + var rowAxis = view.getXAxis(); + var colAxis = view.getXAxisExt(); + var dataMap = new HashMap(); + 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(); + 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>(); + 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(); + 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(); + 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>(); + 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(); + 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(); + dataMap.put("rowColTotal", tmp); + var tmpData = new HashMap(); + 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>(); + 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(); + 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>(); + 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(); + 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>>(); + dataMap.put("rowSubInColSub", tmpData); + for (int i = 0; i < rowAxis.size(); i++) { + if (i == rowAxis.size() - 1) { + break; + } + var tmpList = new ArrayList>(); + 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(); + tmp.put("data", buildCustomCalcResult(data, xAxis, yAxis)); + tmp.put("sql", Base64.getEncoder().encodeToString(querySql.getBytes())); + tmpList.add(tmp); + } + } + } + } + return dataMap; + } + + private Map buildCustomCalcResult(List data, List dimAxis, List quotaAxis) { + var rootResult = new HashMap(); + 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 curSubMap = rootResult; + for (int j = 0; j < dimAxis.size(); j++) { + var tmpMap = curSubMap.get(rowData[j]); + if (tmpMap == null) { + tmpMap = new HashMap(); + curSubMap.put(rowData[j], tmpMap); + curSubMap = (Map) tmpMap; + } else { + curSubMap = (Map) 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> getData(SQLMeta sqlMeta, List xAxis, List yAxis, + List allFields, boolean crossDs, Map 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 data = (List) provider.fetchResultField(datasourceRequest).get("data"); + nullToBlank(data); + return Tuples.of(querySql, data); + } + + private void nullToBlank(List data) { + data.forEach(r -> { + for (int i = 0; i < r.length; i++) { + if (r[i] == null) { + r[i] = ""; + } + } + }); + } + + private List getCustomFields(ChartViewDTO view, List cfgList) { + var quotaIds = view.getYAxis().stream().map(ChartViewFieldDTO::getGisbiName).collect(Collectors.toSet()); + var customFields = new ArrayList(); + 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; + } +} diff --git a/backend/src/main/java/com/stdproject/controller/UserController.java b/backend/src/main/java/com/stdproject/controller/UserController.java index 7de06c5..2e491bc 100644 --- a/backend/src/main/java/com/stdproject/controller/UserController.java +++ b/backend/src/main/java/com/stdproject/controller/UserController.java @@ -280,11 +280,11 @@ private Long jwtExpirationMs; } @GetMapping("/ipInfo") - public CurIpVO ipInfo() { + public ResponseResult ipInfo() { CurIpVO curIpVO = new CurIpVO(); curIpVO.setAccount("admin"); curIpVO.setName("管理员"); curIpVO.setIp(IPUtils.get()); - return curIpVO; + return ResponseResult.successData(curIpVO); } } diff --git a/backend/src/main/java/com/stdproject/utils/ChartDataBuild.java b/backend/src/main/java/com/stdproject/utils/ChartDataBuild.java new file mode 100644 index 0000000..c1ac7f7 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/ChartDataBuild.java @@ -0,0 +1,1819 @@ +package com.stdproject.utils; + +import com.stdproject.entity.dto.ScatterChartDataDTO; +import com.stdproject.entity.dto.Series; +import io.gisbi.extensions.view.dto.*; +import io.gisbi.i18n.Lang; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.IDUtils; +import io.gisbi.utils.JsonUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +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, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + if (StringUtils.containsIgnoreCase(view.getType(), "table")) { + for (int i = 0; i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + if (j > -1) { + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } + dataList.add(axisChartDataDTO); + } + } else { + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + } + map.put("data", dataList); + return map; + } + + public static Map transHeatMapChartDataAntV(List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + List> dataList = new ArrayList<>(); + + if (xAxisBase.size() != 2) { + map.put("data", dataList); + return map; + } + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + + Map object = JsonUtil.parse((String) JsonUtil.toJSONString(axisChartDataDTO), HashMap.class); + + object.put("x", new BigDecimal(row[0])); + object.put("y", new BigDecimal(row[1])); + + dataList.add(object); + } + + } + map.put("data", dataList); + return map; + } + + public static Map transBaseGroupDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + StringBuilder b = new StringBuilder(); + for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() - 1) { + b.append(row[i]); + } else { + b.append(row[i]).append("\n"); + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(b.toString()); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + + if ("line".equals(view.getType())) { + if (ObjectUtils.isEmpty(xAxisExt)) { + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } else { + // 多指标只取第一个 + break; + } + } + } + } + map.put("data", dataList); + return map; + } + + // AntV柱状堆叠图 + public static Map transStackChartDataAntV(List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + + if (ObjectUtils.isNotEmpty(extStack)) { + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + axisChartDataDTO.setCategory(row[xAxisBase.size()]); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + dataList.add(axisChartDataDTO); + } + } else { + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + dataList.add(axisChartDataDTO); + } + } + } + map.put("data", dataList); + return map; + } + + //AntV scatter + public static Map transScatterDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size() + extBubble.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size() + extBubble.size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, ObjectUtils.isNotEmpty(extBubble) ? extSize - 1 : extSize); + // pop + if (ObjectUtils.isNotEmpty(extBubble)) { + try { + axisChartDataDTO.setPopSize(StringUtils.isEmpty(row[2]) ? null : new BigDecimal(row[2])); + ChartQuotaDTO bubbleQuotaDTO = new ChartQuotaDTO(); + bubbleQuotaDTO.setId(extBubble.get(0).getId()); + quotaList.add(bubbleQuotaDTO); + } catch (Exception e) { + axisChartDataDTO.setPopSize(new BigDecimal(0)); + } + } + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // antv radar + public static Map transRadarChartDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // antV组合图形 + public static Map transMixChartDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + return transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, false); + } + + public static Map transMixChartDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill, boolean isLine) { + + Map map = new HashMap<>(); + + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + Set categories = new HashSet<>(); + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int ii = 0; ii < xAxisBase.size(); ii++) { + if (ii == xAxisBase.size() - 1) { + a.append(d[ii]); + } else { + a.append(d[ii]).append("\n"); + } + } + } + StringBuilder b = new StringBuilder(); + for (int ii = xAxisBase.size(); ii < xAxisBase.size() + xAxisExt.size(); ii++) { + if (ii == xAxisBase.size() + xAxisExt.size() - 1) { + b.append(d[ii]); + } else { + b.append(d[ii]).append("\n"); + } + } + + axisChartDataDTO.setName(a.toString()); + axisChartDataDTO.setField(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + + String category = StringUtils.defaultIfBlank(b.toString(), + StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + + if (isLine) { + if (ObjectUtils.isEmpty(xAxisExt)) { + category = StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName()); + } + } + + axisChartDataDTO.setCategory(category); + categories.add(category); + + buildDynamicValue(view, axisChartDataDTO, d, size, extSize); + series.get(j).getData().add(axisChartDataDTO); + } + } + if (CollectionUtils.isNotEmpty(series)) { + series.get(0).setCategories(categories); + } + + map.put("data", series); + return map; + } + + public static Map transMixChartStackDataAntV(List xAxisBase, List xAxis, List extStack, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + + if (CollectionUtils.isEmpty(extStack)) { + return transMixChartDataAntV(xAxisBase, xAxis, new ArrayList<>(), yAxis, view, data, isDrill); + } + + Map map = new HashMap<>(); + + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + Set categories = new HashSet<>(); + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + String category = row[xAxisBase.size()]; + axisChartDataDTO.setCategory(category); + if (category != null) { + categories.add(category); + } + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(0).getData().add(axisChartDataDTO); + } + + if (CollectionUtils.isNotEmpty(series)) { + series.get(0).setCategories(categories); + } + + map.put("data", series); + return map; + } + + // 基础图形 + public static Map transChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // 组合图形 + public static Map transMixChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(j).getData().add(axisChartDataDTO); + } + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 文本卡图形 + public static Map transLabelChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + Series series1 = new Series(); + series1.setName(xAxis.get(0).getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + series.get(0).getData().add(a.toString()); + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 常规图形 + public static Map transNormalChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + int j = i - xAxis.size(); + try { + series.get(j).getData().add(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + series.get(j).getData().add(new BigDecimal(0)); + } + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // radar图 + public static Map transRadarChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + int j = i - xAxis.size(); + try { + series.get(j).getData().add(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + series.get(j).getData().add(new BigDecimal(0)); + } + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 堆叠图 + public static Map transStackChartData(List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List stack = new ArrayList<>(); + List series = new ArrayList<>(); + + if (ObjectUtils.isNotEmpty(extStack)) { + AxisChartDataDTO defaultAxisChartDataDTO = new AxisChartDataDTO(); + BigDecimal defaultValue = StringUtils.containsIgnoreCase(view.getType(), "line") ? new BigDecimal(0) : null; + defaultAxisChartDataDTO.setValue(defaultValue); + // 构建横轴 + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + x = x.stream().distinct().collect(Collectors.toList()); + // 构建堆叠 + for (String[] d : data) { + stack.add(d[xAxis.size()]); + } + stack = stack.stream().distinct().collect(Collectors.toList()); + for (String s : stack) { + Series series1 = new Series(); + series1.setName(s); + series1.setType(view.getType()); + List list = new ArrayList<>(); + for (int i = 0; i < x.size(); i++) { + list.add(defaultAxisChartDataDTO); + } + series1.setData(list); + series.add(series1); + } + for (Series ss : series) { + for (int i = 0; i < x.size(); i++) { + for (String[] row : data) { + String stackColumn = row[xAxis.size()]; + if (StringUtils.equals(ss.getName(), stackColumn)) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int j = 0; j < xAxis.size(); j++) { + if (j == xAxis.size() - 1) { + a.append(row[j]); + } else { + a.append(row[j]).append("\n"); + } + } + } + if (StringUtils.equals(a.toString(), x.get(i))) { + if (row.length > xAxis.size() + extStack.size()) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(extStack.get(0).getId()); + chartDimensionDTO.setValue(row[xAxis.size()]); + dimensionList.add(chartDimensionDTO); + axisChartDataDTO.setDimensionList(dimensionList); + + String s = row[xAxis.size() + extStack.size()]; + if (StringUtils.isNotEmpty(s)) { + axisChartDataDTO.setValue(new BigDecimal(s)); + ss.getData().set(i, axisChartDataDTO); + } + } + break; + } + } + } + } + } + } else { + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(j).getData().add(axisChartDataDTO); + } + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 散点图 + public static Map transScatterData(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + ScatterChartDataDTO scatterChartDataDTO = new ScatterChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + scatterChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + scatterChartDataDTO.setQuotaList(quotaList); + + if (ObjectUtils.isNotEmpty(extBubble) && extBubble.size() > 0) { + try { + scatterChartDataDTO.setValue(new Object[]{ + a.toString(), + StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i]), + StringUtils.isEmpty(d[xAxis.size() + yAxis.size()]) ? null : new BigDecimal(d[xAxis.size() + yAxis.size()]) + }); + } catch (Exception e) { + scatterChartDataDTO.setValue(new Object[]{a.toString(), new BigDecimal(0), new BigDecimal(0)}); + } + } else { + try { + scatterChartDataDTO.setValue(new Object[]{ + a.toString(), + StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i]) + }); + } catch (Exception e) { + scatterChartDataDTO.setValue(new Object[]{a.toString(), new BigDecimal(0)}); + } + } + series.get(j).getData().add(scatterChartDataDTO); + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 表格 + public static Map transTableNormal(List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, Map desensitizationList) { + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) { + fields.addAll(xAxis); + } + if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { + if (ObjectUtils.isNotEmpty(extStack)) { + fields.addAll(extStack); + } + } + fields.addAll(yAxis); + return transTableNormal(fields, view, data, desensitizationList); + } + + public static Map transTableNormalWithDetail(List xAxis, List yAxis, List data, List detailFields, List detailData, Map desensitizationList) { + int detailIndex = xAxis.size(); + + List realDetailFields = detailFields.subList(detailIndex, detailFields.size()); + + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) + fields.addAll(xAxis); + if (ObjectUtils.isNotEmpty(yAxis)) + fields.addAll(yAxis); + Map map = transTableNormal(fields, null, data, desensitizationList); + List> tableRow = (List>) map.get("tableRow"); + final int xEndIndex = detailIndex; + Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> "(" + StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), ")-de-(") + ")")); + + tableRow.forEach(row -> { + String key = xAxis.stream().map(x -> String.format(format, row.get(x.getGisbiName()).toString())).collect(Collectors.joining("-de-")); + List detailFieldValueList = groupDataList.get(key); + List> detailValueMapList = detailFieldValueList.stream().map((detailArr -> { + Map temp = new HashMap<>(); + for (int i = 0; i < realDetailFields.size(); i++) { + ChartViewFieldDTO realDetailField = realDetailFields.get(i); + temp.put(realDetailField.getGisbiName(), detailArr[detailIndex + i]); + } + return temp; + })).collect(Collectors.toList()); + row.put("details", detailValueMapList); + }); + + ChartViewFieldDTO detailFieldDTO = new ChartViewFieldDTO(); + detailFieldDTO.setId(IDUtils.snowID()); + detailFieldDTO.setName("detail"); + detailFieldDTO.setGisbiName("detail"); + fields.add(detailFieldDTO); + map.put("fields", fields); + map.put("detailFields", realDetailFields); + map.put("tableRow", tableRow); + return map; + } + + // 表格 + public static Map transTableNormal(Map> fieldMap, ChartViewDTO view, List data, Map desensitizationList) { + + List fields = new ArrayList<>(); + List yfields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(fieldMap.get("xAxis"))) fields.addAll(fieldMap.get("xAxis")); + if (ObjectUtils.isNotEmpty(fieldMap.get("tooltipAxis"))) { + fieldMap.get("tooltipAxis").forEach(field -> { + Integer deType = field.getDeType(); + if (deType == 2 || deType == 3) { + yfields.add(field); + } else { + fields.add(field); + } + }); + } + if (ObjectUtils.isNotEmpty(fieldMap.get("labelAxis"))) { + fieldMap.get("labelAxis").forEach(field -> { + Integer deType = field.getDeType(); + if (deType == 2 || deType == 3) { + yfields.add(field); + } else { + fields.add(field); + } + }); + } + if (ObjectUtils.isNotEmpty(fieldMap.get("yAxis"))) fields.addAll(fieldMap.get("yAxis")); + if (ObjectUtils.isNotEmpty(yfields)) fields.addAll(yfields); + return transTableNormal(fields, view, data, desensitizationList); + } + + public static String desensitizationValue(ColumnPermissionItem columnPermissionItem, String originStr) { + String desensitizationStr = ""; + if (!columnPermissionItem.getDesensitizationRule().getBuiltInRule().toString().equalsIgnoreCase("custom")) { + switch (columnPermissionItem.getDesensitizationRule().getBuiltInRule()) { + case CompleteDesensitization: + desensitizationStr = ColumnPermissionItem.CompleteDesensitization; + break; + case KeepMiddleThreeCharacters: + if (StringUtils.isEmpty(originStr) || originStr.length() < 4) { + desensitizationStr = ColumnPermissionItem.KeepMiddleThreeCharacters; + } else { + desensitizationStr = "***" + StringUtils.substring(originStr, originStr.length() / 2 - 1, originStr.length() / 2 + 2) + "***"; + } + break; + case KeepFirstAndLastThreeCharacters: + if (StringUtils.isEmpty(originStr) || originStr.length() < 7) { + desensitizationStr = ColumnPermissionItem.KeepFirstAndLastThreeCharacters; + } else { + desensitizationStr = StringUtils.substring(originStr, 0, 3) + "***" + StringUtils.substring(originStr, originStr.length() - 3, originStr.length()); + } + break; + default: + break; + + } + } else { + switch (columnPermissionItem.getDesensitizationRule().getCustomBuiltInRule()) { + case RetainBeforeMAndAfterN: + if (StringUtils.isEmpty(originStr) || originStr.length() < columnPermissionItem.getDesensitizationRule().getM() + columnPermissionItem.getDesensitizationRule().getN()) { + desensitizationStr = String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getM(), "X")) + "***" + String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getN(), "X")); + } else { + desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM()) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN(), originStr.length()); + } + break; + case RetainMToN: + if (columnPermissionItem.getDesensitizationRule().getM() > columnPermissionItem.getDesensitizationRule().getN()) { + desensitizationStr = "*** ***"; + break; + } + if (StringUtils.isEmpty(originStr) || originStr.length() < columnPermissionItem.getDesensitizationRule().getM()) { + desensitizationStr = "*** ***"; + break; + } + if (columnPermissionItem.getDesensitizationRule().getM() == 1) { + desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***"; + break; + } else { + desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***"; + break; + } + default: + break; + + } + } + return desensitizationStr; + } + + public static Map transTableNormal(List fields, ChartViewDTO view, List data, Map desensitizationList) { + Map map = new TreeMap<>(); + List> tableRow = new ArrayList<>(); + data.forEach(ele -> { + Map d = new HashMap<>(); + for (int i = 0; i < fields.size(); i++) { + if (ObjectUtils.isNotEmpty(desensitizationList.keySet()) && desensitizationList.containsKey(fields.get(i).getGisbiName())) { + String desensitizationValue = desensitizationValue(desensitizationList.get(fields.get(i).getGisbiName()), String.valueOf(ele[i])); + ele[i] = desensitizationValue; + d.put(fields.get(i).getGisbiName(), desensitizationValue); + continue; + } + if (i == ele.length) break; + ChartViewFieldDTO chartViewFieldDTO = fields.get(i); + if (chartViewFieldDTO.getDeType() == 0 || chartViewFieldDTO.getDeType() == 1 || chartViewFieldDTO.getDeType() == 5 || chartViewFieldDTO.getDeType() == 7) { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? "" : ele[i]); + } else if (chartViewFieldDTO.getDeType() == 2 || chartViewFieldDTO.getDeType() == 3 || chartViewFieldDTO.getDeType() == 4) { + if (view.getIsExcelExport()) { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? "" : ele[i]); + } else { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? null : new BigDecimal(ele[i]).setScale(8, RoundingMode.HALF_UP)); + } + } + } + tableRow.add(d); + }); + map.put("fields", fields); + map.put("tableRow", tableRow); + return map; + } + + public static Map transGroupStackDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, List extStack, List data, ChartViewDTO view, boolean isDrill) { + // 堆叠柱状图 + if (ObjectUtils.isEmpty(xAxisExt)) { + return transStackChartDataAntV(xAxisBase, xAxis, yAxis, view, data, extStack, isDrill); + // 分组柱状图 + } else if (ObjectUtils.isNotEmpty(xAxisExt) && ObjectUtils.isEmpty(extStack)) { + return transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill); + // 分组堆叠柱状图 + } else { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder xField = new StringBuilder(); + if (isDrill) { + xField.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + xField.append(row[i]); + } else { + xField.append(row[i]).append("\n"); + } + } + } + + StringBuilder groupField = new StringBuilder(); + for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() - 1) { + groupField.append(row[i]); + } else { + groupField.append(row[i]).append("\n"); + } + } + + StringBuilder stackField = new StringBuilder(); + for (int i = xAxisBase.size() + xAxisExt.size(); i < xAxisBase.size() + xAxisExt.size() + extStack.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() + extStack.size() - 1) { + stackField.append(row[i]); + } else { + stackField.append(row[i]).append("\n"); + } + } + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(xField.toString()); + axisChartDataDTO.setName(xField.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setGroup(groupField.toString()); + axisChartDataDTO.setCategory(stackField.toString()); + dataList.add(axisChartDataDTO); + } + map.put("data", dataList); + return map; + } + } + + // 计算动态标签和提示 + private static void buildDynamicValue(ChartViewDTO view, AxisChartDataAntVDTO axisChartDataDTO, String[] row, int size, int extSize) { + List dynamicLabelValue = new ArrayList<>(); + List dynamicTooltipValue = new ArrayList<>(); + // 计算动态标签和提示 + if (ObjectUtils.isNotEmpty(view.getExtLabel())) { + for (int ii = 0; ii < view.getExtLabel().size(); ii++) { + DynamicValueDTO valueDTO = new DynamicValueDTO(); + ChartViewFieldDTO chartViewFieldDTO = view.getExtLabel().get(ii); + BigDecimal value = StringUtils.isEmpty(row[ii + (size - extSize)]) ? null : new BigDecimal(row[ii + (size - extSize)]); + valueDTO.setFieldId(chartViewFieldDTO.getId()); + valueDTO.setValue(value); + dynamicLabelValue.add(valueDTO); + } + } + if (ObjectUtils.isNotEmpty(view.getExtTooltip())) { + for (int ii = 0; ii < view.getExtTooltip().size(); ii++) { + DynamicValueDTO valueDTO = new DynamicValueDTO(); + ChartViewFieldDTO chartViewFieldDTO = view.getExtTooltip().get(ii); + BigDecimal value = StringUtils.isEmpty(row[ii + (size - extSize) + view.getExtLabel().size()]) ? null : new BigDecimal(row[ii + (size - extSize) + view.getExtLabel().size()]); + valueDTO.setFieldId(chartViewFieldDTO.getId()); + valueDTO.setValue(value); + dynamicTooltipValue.add(valueDTO); + } + } + + axisChartDataDTO.setDynamicLabelValue(dynamicLabelValue); + axisChartDataDTO.setDynamicTooltipValue(dynamicTooltipValue); + } + + //AntV quadrant + public static Map transQuadrantDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + for (int i = 0; i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + if (j > -1) { + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + axisChartDataDTO.setField(yAxis.get(j).getOriginName()); + axisChartDataDTO.setName(yAxis.get(j).getName()); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + public static Map transBarRangeDataAntV(boolean skipBarRange, boolean isDate, List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + + Map map = new HashMap<>(); + if (skipBarRange) { + map.put("data", new ArrayList<>()); + return map; + } + + List dates = new ArrayList<>(); + List numbers = new ArrayList<>(); + + ChartViewFieldDTO dateAxis1 = null; + + SimpleDateFormat sdf = null; + if (isDate) { + if (BooleanUtils.isTrue(view.getAggregate())) { + dateAxis1 = yAxis.get(0); + } else { + dateAxis1 = xAxis.get(xAxisBase.size()); + } + sdf = new SimpleDateFormat(getDateFormat(dateAxis1.getDateStyle(), dateAxis1.getDatePattern())); + } + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder xField = new StringBuilder(); + if (isDrill) { + xField.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + xField.append(row[i]); + } else { + xField.append(row[i]).append("\n"); + } + } + } + + + Map obj = new HashMap<>(); + obj.put("field", xField.toString()); + obj.put("category", xField.toString()); + + List dimensionList = new ArrayList<>(); + + for (int i = 0; i < xAxisBase.size(); i++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(i).getId()); + chartDimensionDTO.setValue(row[i]); + dimensionList.add(chartDimensionDTO); + } + if (isDrill) { + int index = xAxis.size() - 1; + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(index).getId()); + chartDimensionDTO.setValue(row[index]); + dimensionList.add(chartDimensionDTO); + } + obj.put("dimensionList", dimensionList); + + + List values = new ArrayList<>(); + + if (row[xAxisBase.size()] == null || row[xAxisBase.size() + 1] == null) { + continue; + } + + if (isDate) { + int index; + if (BooleanUtils.isTrue(view.getAggregate())) { + index = xAxis.size(); + } else { + index = xAxisBase.size(); + } + + values.add(row[index]); + values.add(row[index + 1]); + obj.put("values", values); + Date date1 = null, date2 = null; + try { + date1 = sdf.parse(row[index]); + if (date1 != null) { + dates.add(date1); + } + } catch (Exception ignore) { + } + try { + date2 = sdf.parse(row[index + 1]); + if (date2 != null) { + dates.add(date2); + } + } catch (Exception ignore) { + } + //间隔时间 + obj.put("gap", getTimeGap(date1, date2, dateAxis1.getDateStyle())); + + } else { + values.add(new BigDecimal(row[xAxis.size()])); + values.add(new BigDecimal(row[xAxis.size() + 1])); + obj.put("values", values); + + numbers.add(new BigDecimal(row[xAxis.size()])); + numbers.add(new BigDecimal(row[xAxis.size() + 1])); + + //间隔差 + obj.put("gap", new BigDecimal(row[xAxis.size() + 1]).subtract(new BigDecimal(row[xAxis.size()]))); + } + + dataList.add(obj); + } + + if (isDate) { + Date minDate = dates.stream().min(Date::compareTo).orElse(null); + if (minDate != null) { + map.put("minTime", sdf.format(minDate)); + } + Date maxDate = dates.stream().max(Date::compareTo).orElse(null); + if (maxDate != null) { + map.put("maxTime", sdf.format(maxDate)); + } + } else { + map.put("min", numbers.stream().min(BigDecimal::compareTo).orElse(null)); + map.put("max", numbers.stream().max(BigDecimal::compareTo).orElse(null)); + } + + map.put("isDate", isDate); + map.put("data", dataList); + return map; + + } + + private static String getDateFormat(String dateStyle, String datePattern) { + String split; + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + split = "/"; + } else { + split = "-"; + } + switch (dateStyle) { + case "y": + return "yyyy"; + case "y_M": + return "yyyy" + split + "MM"; + case "y_M_d": + return "yyyy" + split + "MM" + split + "dd"; + case "M_d": + return "MM" + split + "dd"; + case "H_m_s": + return "HH:mm:ss"; + case "y_M_d_H": + return "yyyy" + split + "MM" + split + "dd" + " HH"; + case "y_M_d_H_m": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm"; + case "y_M_d_H_m_s": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm:ss"; + default: + return "yyyy-MM-dd HH:mm:ss"; + } + } + + private static String getTimeGap(Date from, Date to, String dateStyle) { + if (from == null || to == null) { + return ""; + } + Calendar fromCalender = Calendar.getInstance(); + fromCalender.setTime(from); + + Calendar toCalender = Calendar.getInstance(); + toCalender.setTime(to); + + long yearGap = 0; + long monthGap = 0; + long dayGap = (toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600 * 24); + long hourGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600)) % 24; + long minuteGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 60)) % 60; + long secondGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / 1000) % 60; + + String language = "zh-CN"; //国际化 + Lang lang = Lang.getLangWithoutDefault(language); + boolean isEnUs = Lang.en_US.equals(lang); + String splitter = isEnUs ? " " : ""; + + String yearGapStr = ""; + String monthGapStr = ""; + + String dayGapStr = ""; + if (dayGap != 0) { + dayGapStr = dayGap + splitter + Translator.get("i18n_day") + (isEnUs && dayGap != 1 ? "s" : ""); + } + String hourGapStr = ""; + if (hourGap != 0) { + hourGapStr = hourGap + splitter + Translator.get("i18n_hour") + (isEnUs && hourGap != 1 ? "s" : ""); + } + String minuteGapStr = ""; + if (minuteGap != 0) { + minuteGapStr = minuteGap + splitter + Translator.get("i18n_minute") + (isEnUs && minuteGap != 1 ? "s" : ""); + } + String secondGapStr = ""; + if (secondGap != 0) { + secondGapStr = secondGap + splitter + Translator.get("i18n_second") + (isEnUs && secondGap != 1 ? "s" : ""); + } + + List list = new ArrayList<>(); + + switch (dateStyle) { + case "y": + yearGap = toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR); + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + return yearGapStr; + case "y_M": + yearGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) / 12; + monthGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) % 12; + + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + monthGapStr = monthGap == 0 ? "" : (monthGap + splitter + Translator.get("i18n_month") + (isEnUs && monthGap != 1 ? "s" : "")); + + if (!yearGapStr.isEmpty()) { + list.add(yearGapStr); + } + if (!monthGapStr.isEmpty()) { + list.add(monthGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d": + case "M_d": + return dayGapStr; + case "y_M_d_H": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d_H_m": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + return StringUtils.join(list, splitter); + case "H_m_s": + case "y_M_d_H_m_s": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + if (!secondGapStr.isEmpty()) { + list.add(secondGapStr); + } + return StringUtils.join(list, splitter); + default: + return ""; + } + } + + public static Map transSymbolicMapNormalWithDetail(ChartViewDTO view, List xAxis, List yAxis, List extBubble, List data, List detailFields, List detailData) { + int detailIndex = xAxis.size(); + + List realDetailFields = detailFields.subList(detailIndex, detailFields.size()); + + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) + fields.addAll(xAxis); + if (ObjectUtils.isNotEmpty(extBubble)) + fields.addAll(extBubble); + if (ObjectUtils.isNotEmpty(yAxis)) + fields.addAll(yAxis); + Map map = transTableNormal(fields, view, data, new HashMap<>()); + List> tableRow = (List>) map.get("tableRow"); + final int xEndIndex = detailIndex; + Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> "(" + StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), ")-de-(") + ")")); + String extBubblegisbiName = ObjectUtils.isNotEmpty(extBubble) ? extBubble.get(0).getGisbiName() : ""; + tableRow.forEach(row -> { + BigDecimal rowValue = row.get(extBubblegisbiName) == null ? BigDecimal.ZERO : new BigDecimal(row.get(extBubblegisbiName).toString()); + String key = xAxis.stream().map(x -> String.format(format, row.get(x.getGisbiName()).toString())).collect(Collectors.joining("-de-")); + List detailFieldValueList = groupDataList.get(key); + List> detailValueMapList = Optional.ofNullable(detailFieldValueList).orElse(new ArrayList<>()).stream().map((detailArr -> { + Map temp = new HashMap<>(); + for (int i = 0; i < realDetailFields.size(); i++) { + ChartViewFieldDTO realDetailField = realDetailFields.get(i); + if (StringUtils.equalsIgnoreCase(extBubblegisbiName, realDetailField.getGisbiName())) { + temp.put(realDetailField.getGisbiName(), rowValue); + } else { + temp.put(realDetailField.getGisbiName(), detailArr[detailIndex + i]); + } + } + return temp; + })).collect(Collectors.toList()); + //详情只要一个 + row.put("details", !detailValueMapList.isEmpty() ? Collections.singletonList(detailValueMapList.getFirst()) : detailValueMapList); + }); + // 先过滤掉所有记录数字段 + List filterCountAxis = fields.stream() + .filter(item -> !StringUtils.equalsIgnoreCase(item.getGisbiName(), "*")) + .collect(Collectors.toList()); + // 如果气泡大小是记录数,添加到字段列表中 + if (ObjectUtils.isNotEmpty(extBubble) && "*".equals(extBubble.get(0).getGisbiName())) { + filterCountAxis.addAll(yAxis); + } + map.put("fields", filterCountAxis); + map.put("detailFields", realDetailFields); + map.put("tableRow", tableRow); + return map; + } + +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 16a72ff..3503913 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -54,7 +54,7 @@ export default defineConfig({ cors: true, proxy: { '/api': { - target: 'http://192.168.1.38:8083', + target: 'http://192.168.1.20:8083', changeOrigin: true, secure: false, rewrite: path => path.replace(/^\/api/, '')