feat(视图): 视图 指标 增加sum min等常用汇总方式

This commit is contained in:
junjie 2021-03-11 14:33:24 +08:00
parent b1194fd843
commit d8c66325a9
6 changed files with 252 additions and 90 deletions

View File

@ -0,0 +1,30 @@
package io.dataease.dto.chart;
import lombok.Data;
/**
* @Author gin
* @Date 2021/3/11 1:18 下午
*/
@Data
public class ChartViewFieldDTO {
private String id;
private String tableId;
private String originName;
private String name;
private String type;
private Boolean checked;
private Integer columnIndex;
private Long lastSyncTime;
private Integer deType;
private String summary;
}

View File

@ -12,6 +12,7 @@ import io.dataease.datasource.provider.ProviderFactory;
import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.datasource.service.DatasourceService;
import io.dataease.dto.chart.ChartViewDTO;
import io.dataease.dto.chart.ChartViewFieldDTO;
import io.dataease.dto.chart.Series;
import io.dataease.dto.dataset.DataTableInfoDTO;
import io.dataease.service.dataset.DataSetTableFieldsService;
@ -76,9 +77,9 @@ public class ChartViewService {
public ChartViewDTO getData(String id) throws Exception {
ChartViewWithBLOBs view = chartViewMapper.selectByPrimaryKey(id);
List<DatasetTableField> xAxis = new Gson().fromJson(view.getXAxis(), new TypeToken<List<DatasetTableField>>() {
List<ChartViewFieldDTO> xAxis = new Gson().fromJson(view.getXAxis(), new TypeToken<List<ChartViewFieldDTO>>() {
}.getType());
List<DatasetTableField> yAxis = new Gson().fromJson(view.getYAxis(), new TypeToken<List<DatasetTableField>>() {
List<ChartViewFieldDTO> yAxis = new Gson().fromJson(view.getYAxis(), new TypeToken<List<ChartViewFieldDTO>>() {
}.getType());
List<String> x = new ArrayList<>();
@ -88,25 +89,25 @@ public class ChartViewService {
BeanUtils.copyBean(dto, view);
return dto;
}
List<String> xIds = xAxis.stream().map(DatasetTableField::getId).collect(Collectors.toList());
List<String> yIds = yAxis.stream().map(DatasetTableField::getId).collect(Collectors.toList());
List<DatasetTableField> xList = dataSetTableFieldsService.getListByIds(xIds);
List<DatasetTableField> yList = dataSetTableFieldsService.getListByIds(yIds);
// List<String> xIds = xAxis.stream().map(DatasetTableField::getId).collect(Collectors.toList());
// List<String> yIds = yAxis.stream().map(DatasetTableField::getId).collect(Collectors.toList());
// List<DatasetTableField> xList = dataSetTableFieldsService.getListByIds(xIds);
// List<DatasetTableField> yList = dataSetTableFieldsService.getListByIds(yIds);
// 获取数据
// 获取数据
DatasetTable table = dataSetTableService.get(view.getTableId());
// todo 判断连接方式直连或者定时抽取 table.mode
Datasource ds = datasourceService.get(table.getDataSourceId());
DatasourceProvider datasourceProvider = ProviderFactory.getProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(table.getInfo(), DataTableInfoDTO.class);
datasourceRequest.setTable(dataTableInfoDTO.getTable());
datasourceRequest.setQuery(getSQL(ds.getType(), dataTableInfoDTO.getTable(), xList, yList));
datasourceRequest.setQuery(getSQL(ds.getType(), dataTableInfoDTO.getTable(), xAxis, yAxis));
List<String[]> data = datasourceProvider.getData(datasourceRequest);
// todo 处理结果,目前做一个单系列图表后期图表组件再扩展
for (DatasetTableField y : yList) {
for (ChartViewFieldDTO y : yAxis) {
Series series1 = new Series();
series1.setName(y.getName());
series1.setType(view.getType());
@ -116,16 +117,16 @@ public class ChartViewService {
for (String[] d : data) {
StringBuilder a = new StringBuilder();
BigDecimal b = new BigDecimal("0");
for (int i = 0; i < xList.size(); i++) {
if (i == xList.size() - 1) {
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 = xList.size(); i < xList.size() + yList.size(); i++) {
int j = i - xList.size();
for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) {
int j = i - xAxis.size();
series.get(j).getData().add(new BigDecimal(d[i]));
}
}
@ -139,7 +140,7 @@ public class ChartViewService {
return dto;
}
public String getSQL(String type, String table, List<DatasetTableField> xAxis, List<DatasetTableField> yAxis) {
public String getSQL(String type, String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis) {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(type);
switch (datasourceType) {
case mysql:
@ -150,10 +151,10 @@ public class ChartViewService {
}
}
public String transMysqlSQL(String table, List<DatasetTableField> xAxis, List<DatasetTableField> yAxis) {
// TODO 此处sum后期由用户前端传入
String[] field = yAxis.stream().map(y -> "sum(" + y.getOriginName() + ")").toArray(String[]::new);
String[] group = xAxis.stream().map(DatasetTableField::getOriginName).toArray(String[]::new);
public String transMysqlSQL(String table, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis) {
// TODO 字段汇总 排序等
String[] field = yAxis.stream().map(y -> "CAST(" + y.getSummary() + "(" + y.getOriginName() + ") AS DECIMAL(10,2))").toArray(String[]::new);
String[] group = xAxis.stream().map(ChartViewFieldDTO::getOriginName).toArray(String[]::new);
return MessageFormat.format("SELECT {0},{1} FROM {2} GROUP BY {3}", StringUtils.join(group, ","), StringUtils.join(field, ","), table, StringUtils.join(group, ","));
}
}

View File

@ -592,7 +592,15 @@ export default {
x_axis: '横轴',
y_axis: '纵轴',
chart: '视图',
close: '关闭'
close: '关闭',
summary: '汇总方式',
fast_calc: '快速计算',
sum: '求和',
avg: '平均',
max: '最大值',
min: '最小值',
std: '标准差',
var_samp: '方差'
},
dataset: {
datalist: '数据集',

View File

@ -0,0 +1,66 @@
<template>
<span>
<el-dropdown trigger="click" size="small">
<span class="el-dropdown-link">
<span
class="item-axis"
>
{{ item.name }}<i class="el-icon-arrow-down el-icon--right" />
<span />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-edit-outline">
item1
</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete">
item2
</el-dropdown-item>
</el-dropdown-menu>
</span>
</span>
</el-dropdown>
</span>
</template>
<script>
export default {
name: 'DimensionItem',
props: {
item: {
type: Object,
required: true
}
},
data() {
return {}
},
mounted() {
},
methods: {}
}
</script>
<style scoped>
.item-axis {
padding: 1px 6px;
margin: 0 3px 2px 3px;
border: solid 1px #eee;
background-color: #f1f1f1;
text-align: left;
height: 24px;
line-height: 22px;
display: inline-block;
color: #1890ff;
border-radius: 4px;
box-sizing: border-box;
white-space: nowrap;
}
.item-axis:hover {
background-color: #fdfdfd;
cursor: pointer;
}
span {
font-size: 12px;
}
</style>

View File

@ -0,0 +1,95 @@
<template>
<span>
<el-dropdown trigger="click" size="small">
<span class="el-dropdown-link">
<span
class="item-axis"
>
{{ item.name }}<span class="summary-span">({{ $t('chart.'+item.summary) }})</span><i class="el-icon-arrow-down el-icon--right" />
<span />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-notebook-2">
<el-dropdown placement="right-start" size="small" @command="summary">
<span class="el-dropdown-link">
{{ $t('chart.summary') }}<span class="summary-span">({{ $t('chart.'+item.summary) }})</span><i class="el-icon-arrow-right el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="beforeSummary('sum')">{{ $t('chart.sum') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('avg')">{{ $t('chart.avg') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('max')">{{ $t('chart.max') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('min')">{{ $t('chart.min') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('std')">{{ $t('chart.std') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSummary('var_samp')">{{ $t('chart.var_samp') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete">
item4
</el-dropdown-item>
</el-dropdown-menu>
</span>
</span>
</el-dropdown>
</span>
</template>
<script>
export default {
name: 'QuotaItem',
props: {
item: {
type: Object,
required: true
}
},
data() {
return {}
},
mounted() {
},
methods: {
summary(param) {
console.log(param)
this.item.summary = param.type
this.$emit('onQuotaSummaryChange', this.item)
},
beforeSummary(type) {
return {
type: type
}
}
}
}
</script>
<style scoped>
.item-axis {
padding: 1px 6px;
margin: 0 3px 2px 3px;
border: solid 1px #eee;
background-color: #f1f1f1;
text-align: left;
height: 24px;
line-height: 22px;
display: inline-block;
color: #1890ff;
border-radius: 4px;
box-sizing: border-box;
white-space: nowrap;
}
.item-axis:hover {
background-color: #fdfdfd;
cursor: pointer;
}
span {
font-size: 12px;
}
.summary-span{
margin-left: 4px;
color: #878d9f;;
}
</style>

View File

@ -23,7 +23,7 @@
<span>{{ $t('chart.dimension') }}</span>
<draggable
v-model="dimension"
:options="{group:{name: 'itxst',pull:'clone'},sort: true}"
:options="{group:{name: 'dimension',pull:'clone'},sort: true}"
animation="300"
:move="onMove"
style="height: 90%;overflow:auto"
@ -39,7 +39,7 @@
<span>{{ $t('chart.quota') }}</span>
<draggable
v-model="quota"
:options="{group:{name: 'itxst',pull:'clone'},sort: true}"
:options="{group:{name: 'quota',pull:'clone'},sort: true}"
animation="300"
:move="onMove"
style="height: 90%;overflow:auto"
@ -100,73 +100,32 @@
<el-row style="width: 100%;height: 100%;" class="padding-lr">
<el-row style="margin-top: 10px;">
<el-row style="display:flex;height: 32px;">
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.x_axis') }}</span>
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.dimension') }}</span>
<draggable
v-model="view.xaxis"
group="itxst"
group="dimension"
animation="300"
:move="onMove"
style="width:100%;height: 100%;margin:0 10px;border-radius: 4px;border: 1px solid #DCDFE6;overflow-x: auto;display: flex;align-items: center;"
@end="end2"
>
<transition-group class="draggable-group">
<el-dropdown v-for="(item) in view.xaxis" :key="item.id" trigger="click" size="mini">
<span class="el-dropdown-link">
<span
class="item-axis"
>
{{ item.name }}<i class="el-icon-arrow-down el-icon--right" />
<span />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-edit-outline">
item1
</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete">
item2
</el-dropdown-item>
</el-dropdown-menu>
</span>
</span>
</el-dropdown>
<dimension-item v-for="(item) in view.xaxis" :key="item.id" :item="item" />
</transition-group>
</draggable>
</el-row>
<el-row style="display:flex;height: 32px;margin-top: 10px;">
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.y_axis') }}</span>
<span style="line-height: 32px;width: 60px;text-align: right;">{{ $t('chart.quota') }}</span>
<draggable
v-model="view.yaxis"
group="itxst"
group="quota"
animation="300"
:move="onMove"
style="width:100%;height: 100%;margin:0 10px;border-radius: 4px;border: 1px solid #DCDFE6;overflow-x: auto;display: flex;align-items: center;"
@end="end2"
>
<transition-group class="draggable-group">
<el-dropdown v-for="(item) in view.yaxis" :key="item.id" trigger="click" size="mini">
<span class="el-dropdown-link">
<span
class="item-axis"
>
{{ item.name }}<i class="el-icon-arrow-down el-icon--right" />
<span />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-edit-outline">
<el-dropdown placement="right-start" size="mini">
<span class="el-dropdown-link">
item3<i class="el-icon-arrow-right el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>sub1</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-delete">
item4
</el-dropdown-item>
</el-dropdown-menu>
</span>
</span>
</el-dropdown>
<quota-item v-for="(item) in view.yaxis" :key="item.id" :item="item" @onQuotaSummaryChange="quotaSummaryChange" />
</transition-group>
</draggable>
</el-row>
@ -185,10 +144,12 @@
import { post } from '@/api/dataset/dataset'
import draggable from 'vuedraggable'
import { BASE_BAR } from '../chart/chart'
import DimensionItem from '../components/DimensionItem'
import QuotaItem from '../components/QuotaItem'
export default {
name: 'ChartEdit',
components: { draggable },
components: { QuotaItem, DimensionItem, draggable },
data() {
return {
table: {},
@ -301,6 +262,16 @@ export default {
view.sceneId = this.sceneId
view.name = this.table.name
view.tableId = this.$store.state.chart.tableId
view.xaxis.forEach(function(ele) {
if (!ele.summary || ele.summary === '') {
ele.summary = 'sum'
}
})
view.yaxis.forEach(function(ele) {
if (!ele.summary || ele.summary === '') {
ele.summary = 'sum'
}
})
view.xaxis = JSON.stringify(view.xaxis)
view.yaxis = JSON.stringify(view.yaxis)
post('/chart/view/save', view).then(response => {
@ -419,6 +390,17 @@ export default {
return true
},
quotaSummaryChange(item) {
console.log(item)
// item
this.view.yaxis.forEach(function(ele) {
if (ele.id === item.id) {
ele.summary = item.summary
}
})
this.save()
},
myEcharts(option) {
// domecharts
var myChart = this.$echarts.init(document.getElementById('echart'))
@ -483,26 +465,6 @@ export default {
cursor: pointer;
}
.item-axis {
padding: 1px 8px;
margin: 0 3px 2px 3px;
border: solid 1px #eee;
background-color: #f1f1f1;
text-align: left;
height: 24px;
line-height: 22px;
display: inline-block;
color: #1890ff;
border-radius: 4px;
box-sizing: border-box;
white-space: nowrap;
}
.item-axis:hover {
background-color: #fdfdfd;
cursor: pointer;
}
.el-form-item {
margin-bottom: 0;
}