一. 情景
- 在做项目时,有时候后会遇到后端使用了聚合函数,导致生成的对象的属性数量或数量不固定,因此无法建立一个与之对应的对象来向前端传递数据,
- 这时可以采用NameDataListVO向前端传递数据。
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class NameDataListVO {
private String name; //名称(可以是聚合函数的分组名)
private List<BigDecimal> data1; //数据
private List<BigDecimal> data2;
private List<String> desp; //与数据List的长度相等,用于描述每个数据的含义
}
二. 前端处理
1. 数据显示
要想显示如下的数据
(1) 前端接收的List< NameDataVOList>对象(其中每个对象的desp字段保持一致
)
this.rawData=[
{
"name": "2023",
"data1": [85.5, 92.3, 88.1, 91.4, 87.6, 89.8, 93.2, 90.0, 86.7, 88.9, 92.5, 91.1],
"data2": null,
"desp": ["张三", "李四", "王五", "赵六", "钱七", "周八", "吴九", "郑十", "王十一", "李十二", "赵十三", "孙十四"]
},
{
"name": "2022",
"data1": [82.4, 90.5, 85.3, 89.7, 84.2, 86.9, 88.4, 83.6, 87.8, 91.2, 90.1, 84.5],
"data2": null,
"desp": ["张三", "李四", "王五", "赵六", "钱七", "周八", "吴九", "郑十", "王十一", "李十二", "赵十三", "孙十四"]
},
]
要想在前端正确显示,必须将data由数组转为prop:value(注意:为了使得this.columnList中的列名(label)与属性(prop)一一对应,可以以data_${index}
来命名属性)
this.columnList=["张三", "李四", "王五", "赵六", "钱七", "周八", "吴九", "郑十", "王十一", "李十二", "赵十三", "孙十四"]
this.processedData=[
{
"name": "2023",
"data_0":85.5,
"data_1":92.3
"data_2":88.1
"data_3":91.4
},
{
"name": "2022",
"data_0":85.5,
"data_1":92.3
"data_2":88.1
"data_3":91.4
},
]
- 前端数据处理代码:
if (this.rawData.length > 0) {
this.columnList = this.rawData[0].dep;
this.processedData=processData(this.rawData)
}
processData(rawData) {
return rawData.map(item => {
const processedItem = {
name: item.name,
};
item.data1.forEach((data, index) => {
processedItem[`data_${index}`] = data;
});
return processedItem;
});
},
(2) 前端页面显示
<el-table :data="processedData" height="800" v-loading="loading" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="name" label="聚类名称" sortable width="60" align="center" />
<el-table-column v-for="(column, index) in columnList" :key="index" :label="column" :prop="`data_${index}`"
align="center" v-if="columns[index].visible">
<template slot-scope="scope">
<span>{{ scope.row[`data_${index}`] }}</span>
</template>
</el-table-column>
</el-table>
2. 显隐列
新建列配置列表this.columns,通过使用 v-if=“columns[index].visible” 来控制是该列是否显示
//构建columns配置列表
buildColumns(rawData) {
// 初始化一个空数组用于存储列配置
this.columns = [];
// 将列名称添加到列配置中,动态生成key
this.columnList.forEach((c, index) => {
let key = this.columns.length; // 使用 this.columns 数组的当前长度作为 key
this.columns.push({
key: key,
label: c,
visible: true
});
});
},
3. Echarts图表显示
- chartOptions 是一个计算属性,它返回一个对象,这个对象包含了图表的配置项。每当组件的数据发生变化时,chartOptions 会重新计算,并且图表会根据新的配置进行更新。
<template>
<div class="app-container">
<!-- ... 其他代码 ... -->
<!-- 生成图表按钮 -->
<el-button type="warning" plain icon="el-icon-s-data" size="mini" @click="handleGraph">生成图表</el-button>
<!-- ... 其他代码 ... -->
<!-- 图表对话框 -->
<el-dialog title="图表展示" :visible.sync="chartDialogVisible" width="80%">
<div ref="chart" style="width: 100%; height: 500px;"></div>
</el-dialog>
<!-- ... 其他代码 ... -->
</div>
</template>
<script>
// 引入echarts
import * as echarts from 'echarts';
export default {
// ... 其他选项 ...
data() {
return {
// ... 其他数据 ...
chartDialogVisible: false, // 控制图表对话框的显示
// 假设yearList是存储年份的数组
yearList: [],
};
},
computed: {
// ... 其他计算属性 ...
chartOptions() {
const xAxisData = this.columnList;
const seriesData = this.processedData.map(item => ({
name: item.name,
type: 'bar',
data: Object.keys(item)
.filter(key => key.startsWith('data_')) // 过滤出以 'data_' 开头的键
.map(key => item[key]) // 获取每个 'data_X' 属性的值
}));
return {
legend: {
data: this.nameList
},
tooltip: {},
xAxis: {
type: 'category',
data: xAxisData,
},
yAxis: {
// // 设置 y 轴的最大值为数据中的最大值加上 20%
// max: (value) => {
// return value.max + value.max * 0.2;
// }
},
dataZoom: [
{
type: 'slider',
show: true,
xAxisIndex: [0],
start: 1,
end: 35
},
{
type: 'inside',
xAxisIndex: [0],
start: 1,
end: 35
}
],
toolbox: {
show: true,
feature: {
mark: { show: true },
saveAsImage: { show: true },
}
},
series: seriesData
};
}
},
methods: {
// ... 其他方法 ...
// 处理图表显示
handleGraph() {
this.chartDialogVisible = true;
this.$nextTick(() => {
this.initChart();
});
},
// 初始化图表
initChart() {
const chart = echarts.init(this.$refs.chart);
const options = this.chartOptions;
chart.setOption(options);
},
// ... 其他方法 ...
}
};
</script>