在图表统计展示方面,笔者目前使用过的两种开源,分别是 Echats 和 G2Plot 组件,从个人使用上来讲前者应用更广、自定义开发更灵活,后者使用上更简单尤其是在数据绑的格式和方式上更友好,其中在我们使用 Element vue admin 集成分支项目中有关图表的例子基础就是Echats,比如其中的混合图表(柱形+折线) 对应源代码中代码位置依据可从 /views/chats 看到导入的是 echats 也就是说此组件的的使用方式同样通过添加依赖和导入即可使用。 结合提测平台的后台数据,接下来就实战下 Echarts 的图表的基础使用。微信搜索【大奇测试开】,关注这个坚持分享测试开发干货的家伙。
Apache Echarts
关于 Echarts 是一个基于 JavaScript 的开源可视化图表库,最早由百度开源出来,经过社区发展目前已经交给Apache开源组织进行管理,具有设计友好、图表丰富、活跃的社区支持特性。 [官方地址] https://echarts.apache.orgVUE项目使用步骤
步骤一: 项目进行依赖安装npm install echarts --save
执行完成后可以在 package.json 的 dependencies 配置有出现 "echarts": "^5.2.2"
步骤二:页面添加组件引用和定义一个容器<template> <div class="app-container"> <div ref="pieChartDemo" style="width: 600px;height:400px;"></div> </div> </template> <script> import * as echarts from 'echarts' ... </script>步骤三: 使用 echarts.init 方法初始化一个 echarts 实例并通过 setOption 方法生成一个简单饼图,余下配置代码如下(注意查看几处注解说明):
export default { name: 'EchartsDemo', // 使用mounted在页面控件加载在完成后mounted方法进行echart初始化非created mounted() { this.initPieChart() }, methods: { initPieChart() { // 采用的是vue ref的方式获取容器 var chartDom = this.$refs['pieChartDemo'] var myChart = echarts.init(chartDom) var option = { title: { text: '大奇测试开发', subtext: '文章类型分布', left: 'center' }, tooltip: { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series: [ { name: 'Access From', type: 'pie', radius: '50%', data: [ { value: 20, name: '提测平台' }, { value: 2, name: '性能测试' }, { value: 1, name: '流量回放' }, { value: 3, name: '好文分享' }, { value: 5, name: '杂谈' } ] } ] } option && myChart.setOption(option); } } }还可以定义div id 通过 getElementById 获取容器的方式替代this.$refs方式。
<div id="pieChartDemo" style="width: 600px;height:400px;"></div> ...略... var chartDom = document.getElementById('pieChartDemo')
最终添加项目演示菜单启动查看实现效果如图
Echarts的示例运用
经过简单的三步实现了一个饼状图,其他图表的使用只需要在官方的示例页中找到想要,经过一些参数调整把 option 部分拷贝过来就行,对于非数据统计需求的复杂需求,官方这么多图总能找到一款合适的。 选择一个示例如“堆叠面积图”进入,将会展示可以进行调整和编辑的基础代码器页面,此图表主要涉及三个数据区域分别是 (1) 数据区域代表解释 (2)底部X轴展示的标题 (3)实际填充数据,Y对应的数据 series 数组对象个数与legend对应,通过name匹配,每一条对象的data数据又与xAxis的data对应,这也是在开篇提到的 Echarts 个人使用来讲,新手做动态数据处理的不方便的地方,因为数据全部分割了,那么不管是后端给数据或前端数据用都需要按照分散的格式进行再处理。 配置选项是做更多样式处理和调整的,一般如果不需要改变样式或CSS能力不强的话建议不要动了,照葫芦画瓢就行,关于 option 中各项配置解释可以在两个地方得到详细解释- 文档说明中的概念和应用篇,有基础解释与演示;
- 文档选项下的“配置项手册” 可以进行搜索得到更多配置说明
- 文档下还有一个是API文档,是对一些方法的使用说明,相当于之前项目使用 element ui 组件的事件,比演示代码中的 init()、setOption()。
提测数据报表实战
通过上小节的理论和例子,结合提测平台的提测需求做一个数量趋势的统计,数据的维度X轴表示按照周时间线,Y轴展示叠加的各个应用的一个数量值,最终使用“堆叠面积图”展示每周不同应用的提测数量和总数量。表SQL查询
满足展示需求,数据结构稍微有些复杂,需要进行联合表和分组查询,最终SQL语句和结果参考如下。 此SQl中用到的分组如果你查询所有字段的话在Mysql8版本中其实是有个报错的,这个后边我将联同表多表连接,按时间段如何分组知识点做个专题和大家一起复习一下,这里就先不展开了。周提测接口
如果是直接使用上边SQL语句编写接口直接返回,显然还要在Web端用js做一些格式化处理,鉴于python的代码能力要更好一些,这里直接在后端进行数据处理然后直接返回,完整的方法代码如下# dashboard.py @test_dashboard.route("/api/dashboard/stacked", methods=['POST']) def get_request_stacked(): # body = json.loads(request.get_data()) connection = pool.connection() with connection.cursor() as cursor: sql_select = 'SELECT DATE_FORMAT(request.createDate,"%Y%u") weeks, apps.note, COUNT(apps.id) counts FROM request LEFT JOIN apps ON request.appId = apps.id GROUP BY weeks, apps.note;' cursor.execute(sql_select) table_data = cursor.fetchall() # 第一次循环过滤生成week和notes,并生成做临时关键词储备数据, # 用户第二次循环生成 series 需要数据 weeks = [] notes = [] key_value = {} for row in table_data: week = row['weeks'] note = row['note'] if not week in weeks: weeks.append(week) if not note in notes: notes.append(note) key_value[week+note] = row['counts'] # 做一个排序 小到大 weeks.sort() # 做对应日期下应用数据列表生成,没有数据的week用0填充,保证顺序长度一致 series = {} for note in notes: series[note] = [] for week in weeks: if week+note in key_value: series[note].append(key_value[week+note]) else: series[note].append(0) resp_data = { 'weeks': weeks, 'note': notes, 'series': series } resp = format.resp_format_success resp['data'] = resp_data return resp
用了两个for循环完成这个逻辑,其实也算是个小小算法题目,不知道你是否还有解法,欢迎留言探讨。 另外关于报告接口的实现是新增了一个dashboard.py类实现,所以不要忘记之前课程中反复做一些必要代码(完整代码参考github),启动运行后端服务,做个stacked接口请求测试。
堆叠面积图
在掌握了Echar表的渲染方法和接口数据格式化的充分准备之后,就可以直接上在 src/views/dashboard/index.vue 编写代码,注意实现里有个额外的 series 数据处理,已经标注在代码注解里了。<template> <div class="dashboard-container"> <div ref="LineChartBoard" style="width: 95%;height:500px;"></div> </div> </template> <script> import * as echarts from 'echarts' import { requestStacked } from '@/api/board' export default { name: 'Dashboard', mounted() { this.getApList() }, methods: { getApList() { requestStacked().then(resp => { this.initStackedChart(resp.data) }) }, initStackedChart(data) { const chartDom = this.$refs['LineChartBoard'] const myChart = echarts.init(chartDom) const series = [] // 唯一处理需要额外逻辑处理的地方,根据接口数据动态生成series数据 for (var key in data.series) { series.push( { name: key, type: 'line', stack: 'Total', areaStyle: {}, emphasis: { focus: 'series' }, data: data.series[key] } ) } var option = { title: { text: '周需求提测趋势' }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } } }, legend: { // 数据标题展示 data: data.note }, toolbox: { feature: { saveAsImage: {} } }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: [ { type: 'category', boundaryGap: false, data: data.weeks } ], yAxis: [ { type: 'value' } ], series: series } option && myChart.setOption(option) } } } </script>
来吧万事俱备 $ npm run dev 看下实现效果吧。 本篇内容就这些,来回顾下学习内容,主要是以下知识点:
- Vue 中如何使用Echart并根据项目需要找到合适图表应用
- SQL 分组和联合表的组合查询语句实现
- 趋势查询接口数据格式化返回的逻辑处理
关于后续更多进展和分享欢迎持续关注公众号或博客。