mirror of
https://github.com/dataease/dataease.git
synced 2026-05-20 02:58:10 +08:00
feat(图表): 图表指标的快速计算支持累加 #8939
This commit is contained in:
committed by
jianneng-fit2cloud
parent
b3ba91c728
commit
5a3108d93e
@@ -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<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<String[]> data) {
|
||||
protected List<String> mergeIds(List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> extStack) {
|
||||
Set<String> 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<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis
|
||||
, List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> extStack, String chartType, List<String[]> 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<String, Integer> mainIndexMap = new HashMap<>();
|
||||
final List<List<String[]>> mainMatrix = new ArrayList<>();
|
||||
// 排除group和stack的字段
|
||||
List<String> groupStackAxisIds = mergeIds(xAxisExt, extStack);
|
||||
List<ChartViewFieldDTO> 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<String[]> tmp = new ArrayList<>();
|
||||
tmp.add(item);
|
||||
mainMatrix.add(tmp);
|
||||
} else {
|
||||
List<String[]> 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<String[]> preDataItems = mainMatrix.get(k - 1);
|
||||
List<String[]> curDataItems = mainMatrix.get(k);
|
||||
Map<String, BigDecimal> 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<BigDecimal> 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -1958,7 +1958,8 @@ export default {
|
||||
circle_packing_padding: '圓形間距',
|
||||
increase: '增加',
|
||||
decrease: '減少',
|
||||
total: '合計'
|
||||
total: '合計',
|
||||
accumulate: '累加'
|
||||
},
|
||||
dataset: {
|
||||
field_value: '欄位值',
|
||||
|
||||
@@ -1960,7 +1960,8 @@ export default {
|
||||
circle_packing_padding: '圆形间距',
|
||||
increase: '增加',
|
||||
decrease: '减少',
|
||||
total: '合计'
|
||||
total: '合计',
|
||||
accumulate: '累加'
|
||||
},
|
||||
dataset: {
|
||||
field_value: '字段值',
|
||||
|
||||
@@ -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(() => {
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
class="menu-item-padding"
|
||||
:disabled="state.quotaViews.indexOf(chart.type) > -1"
|
||||
:command="beforeQuickCalc('accumulate')"
|
||||
>
|
||||
<span
|
||||
class="sub-menu-content"
|
||||
:class="'accumulate' === item.compareCalc.type ? 'content-active' : ''"
|
||||
>
|
||||
{{ t('chart.accumulate') }}
|
||||
<el-icon class="sub-menu-content--icon">
|
||||
<Icon
|
||||
name="icon_done_outlined"
|
||||
v-if="'accumulate' === item.compareCalc.type"
|
||||
><icon_done_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
Reference in New Issue
Block a user