diff --git a/core/core-backend/src/main/java/io/dataease/chart/charts/impl/DefaultChartHandler.java b/core/core-backend/src/main/java/io/dataease/chart/charts/impl/DefaultChartHandler.java index 13101a8073..7b1af9fc95 100644 --- a/core/core-backend/src/main/java/io/dataease/chart/charts/impl/DefaultChartHandler.java +++ b/core/core-backend/src/main/java/io/dataease/chart/charts/impl/DefaultChartHandler.java @@ -43,6 +43,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @Component @@ -123,7 +124,9 @@ public class DefaultChartHandler extends AbstractChartPlugin { //自定义排序 data = ChartDataUtil.resultCustomSort(xAxis, yAxis, view.getSortPriority(), data); //快速计算 - quickCalc(xAxis, yAxis, data); + var extStack = formatResult.getAxisMap().get(ChartAxis.extStack); + var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt); + quickCalc(xAxis, yAxis, xAxisExt, extStack, view.getType(), data); //数据重组逻辑可重载 var result = this.buildResult(view, formatResult, filterResult, data); T calcResult = (T) new ChartCalcDataResult(); @@ -412,7 +415,19 @@ public class DefaultChartHandler extends AbstractChartPlugin { return "SELECT " + stringBuilder + " FROM (" + sql + ") tmp"; } - protected void quickCalc(List xAxis, List yAxis, List data) { + protected List mergeIds(List xAxisExt, List extStack) { + Set idSet = new HashSet<>(); + if (xAxisExt != null) { + xAxisExt.forEach(field -> idSet.add(String.valueOf(field.getId()))); + } + if (extStack != null) { + extStack.forEach(field -> idSet.add(String.valueOf(field.getId()))); + } + return new ArrayList<>(idSet); + } + + protected void quickCalc(List xAxis, List yAxis + , List xAxisExt, List extStack, String chartType, List data) { for (int i = 0; i < yAxis.size(); i++) { ChartViewFieldDTO chartViewFieldDTO = yAxis.get(i); ChartFieldCompareDTO compareCalc = chartViewFieldDTO.getCompareCalc(); @@ -505,6 +520,91 @@ public class DefaultChartHandler extends AbstractChartPlugin { .divide(sum, 8, RoundingMode.HALF_UP) .toString(); } + } else if (StringUtils.equalsIgnoreCase(compareCalc.getType(), "accumulate")) { + // 累加 + if (CollectionUtils.isEmpty(data)) { + break; + } + if (StringUtils.containsAny(chartType, "group", "stack")) { + if (CollectionUtils.isEmpty(xAxis)) { + break; + } + if (StringUtils.containsIgnoreCase(chartType, "stack") && extStack.isEmpty()) { + break; + } + if (StringUtils.containsIgnoreCase(chartType, "group") && xAxisExt.isEmpty()) { + break; + } + final Map mainIndexMap = new HashMap<>(); + final List> mainMatrix = new ArrayList<>(); + // 排除group和stack的字段 + List groupStackAxisIds = mergeIds(xAxisExt, extStack); + List finalXAxisBase = xAxis.stream().filter(ele->!groupStackAxisIds.contains(String.valueOf(ele.getId()))).toList(); + if (CollectionUtils.isEmpty(finalXAxisBase) && CollectionUtils.isNotEmpty(xAxis)) { + finalXAxisBase.add(xAxis.get(0)); + } + data.forEach(item -> { + String[] mainAxisArr = Arrays.copyOfRange(item, 0, finalXAxisBase.size()); + String mainAxis = StringUtils.join(mainAxisArr, '-'); + Integer index = mainIndexMap.get(mainAxis); + if (index == null) { + mainIndexMap.put(mainAxis, mainMatrix.size()); + List tmp = new ArrayList<>(); + tmp.add(item); + mainMatrix.add(tmp); + } else { + List tmp = mainMatrix.get(index); + tmp.add(item); + } + }); + int finalDataIndex = dataIndex; + int subEndIndex = finalXAxisBase.size(); + if (StringUtils.containsIgnoreCase(chartType, "group")) { + subEndIndex += xAxisExt.size(); + } + if (StringUtils.containsIgnoreCase(chartType, "stack")) { + subEndIndex += extStack.size(); + } + int finalSubEndIndex = subEndIndex; + //滑动累加 + for (int k = 1; k < mainMatrix.size(); k++) { + List preDataItems = mainMatrix.get(k - 1); + List curDataItems = mainMatrix.get(k); + Map preDataMap = new HashMap<>(); + preDataItems.forEach(preDataItem -> { + String[] groupStackAxisArr = Arrays.copyOfRange(preDataItem, finalXAxisBase.size(), finalSubEndIndex); + String groupStackAxis = StringUtils.join(groupStackAxisArr, '-'); + String preVal = preDataItem[finalDataIndex]; + if (StringUtils.isBlank(preVal)) { + preVal = "0"; + } + preDataMap.put(groupStackAxis, new BigDecimal(preVal)); + }); + curDataItems.forEach(curDataItem -> { + String[] groupStackAxisArr = Arrays.copyOfRange(curDataItem, finalXAxisBase.size(), finalSubEndIndex); + String groupStackAxis = StringUtils.join(groupStackAxisArr, '-'); + BigDecimal preValue = preDataMap.get(groupStackAxis); + if (preValue != null) { + curDataItem[finalDataIndex] = new BigDecimal(curDataItem[finalDataIndex]) + .add(preValue) + .toString(); + } + }); + } + } else { + final int index = dataIndex; + final AtomicReference accumValue = new AtomicReference<>(new BigDecimal(0)); + data.forEach(item -> { + String val = item[index]; + BigDecimal curAccumValue = accumValue.get(); + if (!StringUtils.isBlank(val)) { + BigDecimal curVal = new BigDecimal(val); + curAccumValue = curAccumValue.add(curVal); + accumValue.set(curAccumValue); + } + item[index] = curAccumValue.toString(); + }); + } } } } diff --git a/core/core-frontend/src/locales/en.ts b/core/core-frontend/src/locales/en.ts index 5d502077cd..d9c671657b 100644 --- a/core/core-frontend/src/locales/en.ts +++ b/core/core-frontend/src/locales/en.ts @@ -2008,7 +2008,8 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr circle_packing_padding: 'Circle padding', increase: 'Increase', decrease: 'Decrease', - total: 'Total' + total: 'Total', + accumulate: 'Accumulate' }, dataset: { field_value: 'Field Value', diff --git a/core/core-frontend/src/locales/tw.ts b/core/core-frontend/src/locales/tw.ts index 2bcce777a1..55d2941898 100644 --- a/core/core-frontend/src/locales/tw.ts +++ b/core/core-frontend/src/locales/tw.ts @@ -1958,7 +1958,8 @@ export default { circle_packing_padding: '圓形間距', increase: '增加', decrease: '減少', - total: '合計' + total: '合計', + accumulate: '累加' }, dataset: { field_value: '欄位值', diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts index e05f6e4adb..f0b224f968 100644 --- a/core/core-frontend/src/locales/zh-CN.ts +++ b/core/core-frontend/src/locales/zh-CN.ts @@ -1960,7 +1960,8 @@ export default { circle_packing_padding: '圆形间距', increase: '增加', decrease: '减少', - total: '合计' + total: '合计', + accumulate: '累加' }, dataset: { field_value: '字段值', diff --git a/core/core-frontend/src/views/chart/components/editor/drag-item/QuotaItem.vue b/core/core-frontend/src/views/chart/components/editor/drag-item/QuotaItem.vue index b3fb4bc843..52adaddbad 100644 --- a/core/core-frontend/src/views/chart/components/editor/drag-item/QuotaItem.vue +++ b/core/core-frontend/src/views/chart/components/editor/drag-item/QuotaItem.vue @@ -271,6 +271,10 @@ const quickCalc = param => { item.value.compareCalc.type = 'percent' emit('onQuotaItemChange', item.value) break + case 'accumulate': + item.value.compareCalc.type = 'accumulate' + emit('onQuotaItemChange', item.value) + break default: break } @@ -676,6 +680,25 @@ onMounted(() => { + + + {{ t('chart.accumulate') }} + + + + +