单击以下链接,可跳转到相应的子任务实现部分。
最终实现的效果如下:
请注意:本示例为了在一个项目中演示多种不同图表的实现,实现了一个单页面应用程序,通过路由来在不同的图表之间切换。在比赛时,并没有此要求,因此大家也可以每个子任务单独创建一个项目,请求一个接口数据并显示一张图表,从而避免使用单页面应用程序和路由组件导航,这样可以减少复杂度和可能出错的机率。只要最终实现任务需求即可。
任务分析
相对来说,这部分在整个竞赛的各模块中相对比较容易,也是确保得分的模块。该模块主要涉及以下知识点:
-
(1)Vue前端框架。
-
(2)在Vue中实现Ajax请求。
-
(3)前端JavaScript编程(数据处理)。
-
(4)Apache ECharts图表库使用。
前置学习
前端框架vue.js系列教程:
注意:请务必先学习上面的vue.js系列教程,再继续接下来的任务实现。
创建Vue3工程
请按以下步骤实现任务要求。
(1) 创建一个项目存放的专用文件夹,比如,myvue,然后在命令使用cd命令切换到该目录下。
(2) 使用NPM包管理器安装本任务中项目的依赖包。在命令行执行如下安装命令:
在正式比赛中应该不需要自己安装这些依赖包,因为环境不连网,所以需要的模块和包应该已经安装在本地了。比赛时赛方应该已经在环境中创建好了项目的基本框架,大家在此基础上继续
#安装vue
$ npm install vue@next
#安装vue-route依赖包
$ npm install vue-router
#安装echarts依赖包
$ npm install echarts
(3) 创建Vue项目。在myvue目录下,执行如下项目创建命令:
在正式比赛中应该不需要自己从零创建项目。比赛时赛方应该已经在环境中创建好了项目的基本框架,大家在此基础上继续创建页面、编写代码请求和处理数据并显示数据即可。
$ vue create myvue-app
(4) 启动VS Code,打开myvue-app项目文件夹,加载项目文件,然后在项目的src目录下,创建一个views子目录。
(5) 检查项目中是否有echarts.min.js文件(比赛环境中没有安装echarts组件,需要手工导入echarts.min.js文件)。如果没有,将赛方提供的echarts.min.js拷贝到项目的src/assets/目录下。
(6) 打开项目中的vue.config.js文件,增加一项配置(如果没有的话):lintOnSave:false,如下所示:
......
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false
})
接口说明
在以下可视化任务中,涉及到对两个接口的请求。
接口1:获取指定时间范围内的订单数据
http请求方法:POST
请求地址:http://192.168.23.*(地址为可视化接口虚拟机的直连IP):8999/dataVisualization/selectOrderInfo
请求参数:
字段 | 说明 | 类型 | 是否必填 |
---|---|---|---|
startTime | 开始时间 | String | 是 |
endTime | 结束时间 | String | 是 |
请求格式:json。示例如下:
{
"startTime":"2020-01-01 00:00:00",
"endTime":"2020-12-30 00:00:00"
}
返回参数说明:
参数 | 说明 |
---|---|
id | 主键 |
finalTotalAmount | 总金额 |
outTradeNo | 订单交易编号(第三方支付用) |
provinceName | 省市名称。例如,北京、天津市、河北省等。 |
regionName | 地区名称。例如,华北、华中等。 |
userName | 用户名 |
请求成功返回JSON数据包:
{
"msg": "操作成功",
"code": 200,
"data": [
{
"id": 78506,
"finalTotalAmount": 305062.00,
"outTradeNo": "756847726439369",
"provinceName": "北京",
"regionName": "华北",
"userName": "华馥"
},
{
"id": 78559,
"finalTotalAmount": 6111.00,
"outTradeNo": "341957455961748",
"provinceName": "北京",
"regionName": "华北",
"userName": "罗菊兰"
},
{
"id": 78568,
"finalTotalAmount": 84610.00,
"outTradeNo": "489992944636772",
"provinceName": "北京",
"regionName": "华北",
"userName": "毛岚"
},
…
]
}
接口2:查询上架的商品信息
http请求方法:POST
请求地址:http://192.168.23.*(地址为可视化接口虚拟机的直连IP):8999/dataVisualization/selectGoodsInfo
请求参数:无具体参数
请求格式:json,{}。
返回参数说明:
参数 | 说明 |
---|---|
id | 编号 |
price | 总金额 |
skuName | 商品名称 |
year | 年份 |
请求成功返回JSON数据包:
{
"msg": "操作成功",
"code": 200,
"data": [
{
"id": ,
"price": 2220,
"skuName": "荣耀10青春版 幻彩渐变 2400万AI自拍 全网通版4GB+64GB 渐变蓝 移动联通电信4G全面屏手机 双卡双待",
"year": "2019"
},
{
"id": 2,
"price": 3321,
"skuName": "TCL 55A950C 55英寸32核人工智能 HDR曲面超薄4K电视金属机身(枪色)",
"year": "2019"
},
{
"id": 3,
"price": 3100,
"skuName": "小米(MI)电视 55英寸曲面4K智能WiFi网络液晶电视机4S L55M5-AQ 小米电视4S 55英寸 曲面",
"year": "2019"
},
...
]
}
可以看出,接口返回的数据是一个JSON对象。
子任务一:用柱状图展示消费额最高的省份
任务描述
-
编写Vue 工程代码,根据接口,用柱状图展示2020 年消费额最高的5 个省份(不用考虑数据是否合规,直接聚合省份消费额),同时将用于图表展示的数据结构在浏览器的console 中进行打印输出,将图表可视化结果和浏览器console 打印结果分别截图并粘贴至客户端桌面【Release\模块E 提交结果.docx】中对应的任务序号下。
请按以下步骤操作。
(1) 在项目的src/views/目录下,新建一个名为Task01View.vue的文件,编辑代码如下:
<template>
<h2>柱状图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:600px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
// 导入echarts组件
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请将IP替换为相应的接口实际地址)
var url = "http://IP:8999/dataVisualization/selectOrderInfo"
var params = '{"startTime":"2020-01-01 00:00:00", "endTime":"2020-12-31 23:59:59"}'
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用柱状图展示2020年消费额最高的5个省份',
subtext: '2020年',
left: 'center'
},
tooltip: {},
legend: {
data: ['销售额'], // 要和series.name一致
x:'right',
y:'top'
},
xAxis: {
type: 'category',
data: [] // **** ajax请求回来的数据要填充到这里
},
yAxis: {
type: 'value'
},
series: [
{
name: '销售额',
type: 'bar',
data: [] // **** ajax请求回来的数据要填充到这里
}
]
});
// fetch请求
fetch(url, {
method: "post", // POST请求
headers: {'content-type': 'application/json;charset=UTF-8'},
body: params // 参数
}
)
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取x轴值列表和y轴值列表
var jsObj = getXY(data.data);
// 将用于图表展示的数据结构在浏览器的console 中进行打印输出
console.log(jsObj)
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 刷新echarts数据
var option = myChart.getOption();
option.xAxis[0].data = jsObj.x;
option.series[0].data = jsObj.y;
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 分别抽取x轴数据和y轴数据
function getXY(jsArray){
// 准备存储数据的结构
var dataMap = new Map();
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象
var provinceName = jsObj.provinceName; // 订单所属省份
var finalTotalAmount = jsObj.finalTotalAmount; // 订单金额
// 如果有该省份,则累加金额
if(dataMap.has(provinceName)){
dataMap.set(provinceName, dataMap.get(provinceName) + finalTotalAmount)
}
// 如果没有,则说明是该省第一个订单
else{
dataMap.set(provinceName, finalTotalAmount)
}
}
// 先转为数组,再按金额排序,然后取前5个
var top5Arr = Array.from(dataMap).sort((a,b) => b[1] - a[1]).slice(0,5)
// 遍历top5Arr,取x轴值(省份名称)和y轴值(该省总金额)
var xs = []; // 存储x轴数据
var ys = []; // 存储y轴数据
for (var [key, value] of top5Arr) {
xs.push(key); // 省份值,放入x轴
ys.push(value);// 金额值,放入y轴
}
// 以json对象形式返回
return {"x":xs,"y":ys};
}
</script>
(2) 修改主组件App.vue,添加导航链接和渲染组件,代码如下:
<template>
<div class="menu">
<h3>请选择分析结果</h3>
<ul>
<!--使用 router-link 组件进行导航 -->
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/task01">任务1:用柱状图展示消费额最高的省份</router-link></li>
</ul>
</div>
<div class="graph">
<!-- 渲染在这里 -->
<router-view></router-view>
</div>
</template>
(3) 修改入口文件main.js,导入路由组件文件并指定路由映射,主要修改部分如下:
// 程序入口文件
...
// 1. 定义路由组件.
import Home from "./views/HomeView.vue"
import Task01 from "./views/Task01View.vue"
// 2. 定义一些路由映射
const routes = [
{ path: '/', component: Home },
{ path: '/task01', component: Task01 },
]
...
(4) 执行Vue应用程序。
在VS Code编辑器下方的“终端”窗口中,执行如下命令,启动开发服务器:
$ npm run serve
打开浏览器,访问http://localhost:8080/,点击左侧的链接,就可以看到在右侧显示相应的柱状图。
子任务二:用饼状图展示各地区消费能力
任务描述
-
编写Vue 工程代码,根据接口,用饼状图展示2020 年各地区的消费总额占比(不用考虑数据是否合规,直接聚合地区消费额),同时将用于图表展示的数据结构在浏览器的console 中进行打印输出,将图表可视化结果和浏览器console 打印结果分别截图并粘贴至客户端桌面【Release\模块E 提交结果.docx】中对应的任务序号下。
请按以下步骤操作。
(1) 在项目的src/views/目录下,新建一个名为Task02View.vue的文件,编辑代码如下:
<template>
<h2>柱状图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:600px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
// 导入echarts组件
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请将IP替换为你接口实际地址)
var url = "http://IP:8999/dataVisualization/selectOrderInfo"
var params = '{"startTime":"2020-01-01 00:00:00", "endTime":"2020-12-31 23:59:59"}'
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用饼状图展示各地区消费能力',
subtext: '2020年',
left: 'center'
},
tooltip: {trigger: 'item'},
legend: {
orient: 'vertical',
data: ['消费金额'], // 要和series.name一致
x:'left',
y:'top'
},
series: [
{
name: '消费金额',
type: 'pie',
radius: '60%',
data: [], // **** ajax请求回来的数据要填充到这里
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
// fetch请求
fetch(url, {
method: "post",
headers: {'content-type': 'application/json'},
body: params
}
)
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取x轴值列表和y轴值列表
var jsObj = getXY(data.data);
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 将用于图表展示的数据结构在浏览器的console 中进行打印输出
console.log(jsObj)
// 刷新echarts数据
var option = myChart.getOption();
option.series[0].data = jsObj;
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 分别抽取x轴数据和y轴数据
function getXY(jsArray){
var dataMap = new Map();
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象 {id: 78506, finalTotalAmount: 305062, outTradeNo: '756847726439369', provinceName: '北京', regionName: '华北', userName:'华馥'}
var regionName = jsObj.regionName; // 订单所属地区
var finalTotalAmount = jsObj.finalTotalAmount; // 订单金额
// 如果有该地区,则累加金额
if(dataMap.has(regionName)){
dataMap.set(regionName, dataMap.get(regionName) + finalTotalAmount)
}
// 如果没有,则说明是该地区第一个订单
else{
dataMap.set(regionName, finalTotalAmount)
}
}
// 遍历Map,取x轴值(地区名称)和y轴值(该地区总金额)
var data = []
for (var [key, value] of dataMap) {
var obj = new Object(); // js对象
obj.value = value;
obj.name = key;
data.push(obj);
}
// 以json对象形式返回
return data; // [{name:"华北",value:123123},...]
}
</script>
(2) 修改主组件App.vue,添加导航链接和渲染组件,代码如下:
<template>
<div class="menu">
<h3>请选择分析结果</h3>
<ul>
<!--使用 router-link 组件进行导航 -->
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/task01">任务1:用柱状图展示消费额最高的省份</router-link></li>
<li><router-link to="/task02">任务2:用饼状图展示各地区消费能力</router-link></li>
</ul>
</div>
<div class="graph">
<!-- 渲染在这里 -->
<router-view></router-view>
</div>
</template>
(3) 修改入口文件main.js,导入路由组件文件并指定路由映射,主要修改部分如下:
// 程序入口文件
...
// 1. 定义路由组件.
import Home from "./views/HomeView.vue"
import Task01 from "./views/Task01View.vue"
import Task02 from "./views/Task02View.vue"
// 2. 定义一些路由映射
const routes = [
{ path: '/', component: Home },
{ path: '/task01', component: Task01 },
{ path: '/task02', component: Task02 },
]
...
(4) 执行Vue应用程序。
在VS Code编辑器下方的“终端”窗口中,执行如下命令,启动开发服务器:
$ npm run serve
打开浏览器,访问http://localhost:8080/,点击左侧的链接,就可以看到在右侧显示相应的饼状图。
子任务三:用玫瑰图展示各地区消费能力
任务描述
-
编写Vue 工程代码,根据接口,用基础南丁格尔玫瑰图展示2020 年各地区的消费总额占比,同时将用于图表展示的数据结构在浏览器的console 中进行打印输出,将图表可视化结果和浏览器console 打印结果分别截图并粘贴至客户端桌面【Release\模块E 提交结果.docx】中对应的任务序号下。
实现与子任务二的饼状图完全一致,仅修改echarts图表外观即可。如下:
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用饼状图展示各地区消费能力',
subtext: '2020年',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a}
{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
data: ['消费金额'], // 要和series.name一致
x:'left',
y:'top'
},
series: [
{
name: '消费金额',
type: 'pie',
radius: [20, 200],
center: ['50%', '50%'],
roseType: 'area',
itemStyle: {
borderRadius: 8
},
data: [], // **** ajax请求回来的数据要填充到这里
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
子任务四:用折线图展示每年上架商品数量变化
任务描述
-
编写Vue 工程代码,根据接口,用折线图展示每年上架商品数量的变化情况(商品出现一次即累加1,不用考虑商品重复出现),同时将用于图表展示的数据结构在浏览器的console 中进行打印输出,将图表可视化结果和浏览器console打印结果分别截图并粘贴至客户端桌面【Release\模块E 提交结果.docx】中对应的任务序号下。
请按以下步骤操作。
(1) 在项目的src/views/目录下,新建一个名为Task04View.vue的文件,编辑代码如下:
<template>
<h2>折线图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:600px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请将IP替换为实际接口地址)
var url = "http://IP:8999/dataVisualization/selectGoodsInfo"
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用折线图展示每年上架商品数量的变化',
left: 'center'
},
tooltip: {},
legend: {
data: ['上架商品数量'], // 要和series.name一致
x:'right',
y:'top'
},
xAxis: {
type: 'category',
data: []
},
yAxis: {
type: 'value',
// scale: true
},
series: [
{
name: '上架商品数量',
symbolSize: 15,
type: 'line',
data: [], // **** ajax请求回来的数据要填充到这里
// symbolSize: function(value) {
// return value[1]/1000;
// },
itemStyle: {
color: 'green'
}
}
]
});
// fetch请求
fetch(url, {method: "post",headers: {'content-type': 'application/json'}})
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取x轴值列表和y轴值列表
var jsObj = getXY(data.data);
// 将用于图表展示的数据结构在浏览器的console中进行打印输出
console.log(jsObj)
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 刷新echarts数据
var option = myChart.getOption();
option.xAxis[0].data = jsObj.x; // 设置option中x轴的数据
option.series[0].data = jsObj.y; // 设置option中y轴的数据
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 分别抽取x轴数据和y轴数据
function getXY(jsArray){
var dataMap = new Map(); // 定义map,存储{年份,数量}
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象 {id: 1, price: 2220, skuName: '荣耀10青春版...', year: 2019}
var year = jsObj.year; // 上架商品年份
// 如果有该年份,则累加数量
if(dataMap.has(year)){
dataMap.set(year, dataMap.get(year) + 1); // 一条数据,一个商品
}
// 如果没有,则说明是该年第一个商品
else{
dataMap.set(year, 1); // 一条数据,一个商品
}
}
// 先转为数组,再按年排序
var dataArr = Array.from(dataMap).sort((a,b) => a[0] - b[0])
// 遍历dataArr,取x轴值(年份)和y轴值(上架商品数量)
var xs = []; // 存储x轴数据
var ys = []; // 存储y轴数据
for (var [key, value] of dataArr) {
xs.push(key); // 年份值,放入x轴
ys.push(value);// 上架商品数量值,放入y轴
}
// 以json对象形式返回
return {"x":xs,"y":ys};
}
</script>
(2) 修改主组件App.vue,添加导航链接和渲染组件,代码如下:
<template>
<div class="menu">
<h3>请选择分析结果</h3>
<ul>
<!--使用 router-link 组件进行导航 -->
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/task01">任务1:用柱状图展示消费额最高的省份</router-link></li>
<li><router-link to="/task02">任务2:用饼状图展示各地区消费能力</router-link></li>
<li><router-link to="/task04">任务4:用折线图展示每年上架商品数量的变化</router-link></li>
</ul>
</div>
<div class="graph">
<!-- 渲染在这里 -->
<router-view></router-view>
</div>
</template>
(3) 修改入口文件main.js,导入路由组件文件并指定路由映射,主要修改部分如下:
// 程序入口文件
...
// 1. 定义路由组件.
import Home from "./views/HomeView.vue"
import Task01 from "./views/Task01View.vue"
import Task02 from "./views/Task02View.vue"
import Task04 from "./views/Task04View.vue"
// 2. 定义一些路由映射
const routes = [
{ path: '/', component: Home },
{ path: '/task01', component: Task01 },
{ path: '/task02', component: Task02 },
{ path: '/task04', component: Task04 },
]
...
(4) 执行Vue应用程序。
在VS Code编辑器下方的“终端”窗口中,执行如下命令,启动开发服务器:
$ npm run serve
打开浏览器,访问http://localhost:8080/,点击左侧的链接,就可以看到在右侧显示相应的折线图。
子任务五:用散点图展示每年上架商品数量的变化
任务描述
-
编写Vue 工程代码,根据接口,用基础散点图展示每年上架商品数量的变化情况,同时将用于图表展示的数据结构在浏览器的console 中进行打印输出,将图表可视化结果和浏览器console 打印结果分别截图并粘贴至客户端桌面【Release\模块E 提交结果.docx】中对应的任务序号下。
实现与子任务四类似,仅需修改echarts图表的类型和统计结果数据类型即可。
<template>
<h2>折线图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:600px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请将IP替换为实际接口地址)
var url = "http://IP:8999/dataVisualization/selectGoodsInfo"
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用折线图展示每年上架商品数量的变化',
left: 'center'
},
tooltip: {},
legend: {
data: ['上架商品数量'], // 要和series.name一致
x:'right',
y:'top'
},
xAxis: {
type: 'value',
scale: true
},
yAxis: {
type: 'value',
// scale: true
},
series: [
{
name: '上架商品数量',
symbolSize: 15,
type: 'scatter',
data: [], // **** ajax请求回来的数据要填充到这里
// symbolSize: function(value) {
// return value[1]/1000;
// },
itemStyle: {
color: 'green'
}
}
]
});
// fetch请求
fetch(url, {method: "post",headers: {'content-type': 'application/json'}})
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取x轴值列表和y轴值列表
var jsObj = getXY(data.data);
// 将用于图表展示的数据结构在浏览器的console中进行打印输出
console.log(jsObj)
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 刷新echarts数据
var option = myChart.getOption();
option.series[0].data = jsObj.y; // 设置option中的数据
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 分别抽取x轴数据和y轴数据
function getXY(jsArray){
var dataMap = new Map(); // 定义map,存储{年份,数量}
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象 {id: 1, price: 2220, skuName: '荣耀10青春版...', year: 2019}
var year = jsObj.year; // 上架商品年份
// 如果有该年份,则累加数量
if(dataMap.has(year)){
dataMap.set(year, dataMap.get(year) + 1); // 一条数据,一个商品
}
// 如果没有,则说明是该年第一个商品
else{
dataMap.set(year, 1); // 一条数据,一个商品
}
}
// 先转为数组,再按年排序
var dataArr = Array.from(dataMap).sort((a,b) => a[0] - b[0])
// 遍历dataArr,取x轴值(年份)和y轴值(上架商品数量)
var axisData = []; // 存储数据
for (var [key, value] of dataArr) {
var itemArr = [key, value]; // 组织数据
axisData.push(itemArr); // 放入数组
}
// 返回
return axisData;
}
</script>
子任务六:用条形图展示平均消费额最高的省份
任务描述
-
编写Vue工程代码,根据接口,用条形图展示2020年平均消费额(四舍五入保留两位小数)最高的5个省份,同时将用于图表展示的数据结构在浏览器的console中进行打印输出,将图表可视化结果和浏览器console打印结果分别截图并粘贴至客户端桌面【Release\任务E提交结果.docx】中对应的任务序号下。
请按以下步骤操作。
(1) 在项目的src/views/目录下,新建一个名为Task06View.vue的文件,编辑代码如下:
<template>
<h2>条形图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:600px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请替换为你自己的IP)
var url = "http://IP:8999/dataVisualization/selectOrderInfo"
var params = '{"startTime":"2020-01-01 00:00:00", "endTime":"2020-12-31 23:59:59"}'
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用条形图展示平均消费额最高的省份',
subtext: '2020年',
left: 'center'
},
tooltip: {trigger: 'axis'},
legend: {
data: ['平均消费额'], // 要和series.name一致
x:'right',
y:'top'
},
xAxis: {
type: 'value'
},
yAxis: {
type: 'category',
data: [] // **** ajax请求回来的数据要填充到这里
},
series: [
{
name: '平均消费额',
type: 'bar',
data: [] // **** ajax请求回来的数据要填充到这里
}
]
});
// fetch请求
fetch(url, {
method: "post",
headers: {'content-type': 'application/json'},
body: params
}
)
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取x轴值列表和y轴值列表
var jsObj = getXY(data.data);
// 将用于图表展示的数据结构在浏览器的console中进行打印输出
console.log(jsObj)
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 刷新echarts数据
var option = myChart.getOption();
option.yAxis[0].data = jsObj.x;
option.series[0].data = jsObj.y;
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 分别抽取x轴数据和y轴数据
function getXY(jsArray){
// 存储每个省及其总金额、总订单数
var dataMap = new Map();
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象
var provinceName = jsObj.provinceName; // 订单所属省份
var finalTotalAmount = jsObj.finalTotalAmount; // 订单金额
// 构造一个对象,存储某省份的累加金额和累加订单数(以便计算平均金额)
var obj = new Object();
// 如果有该省份,则累加金额和数量
if(dataMap.has(provinceName)){
var accOjb = dataMap.get(provinceName); // 获得原来累加的对象
obj.totalAmount = accOjb.totalAmount + finalTotalAmount; // 累加金额
obj.totalNum = accOjb.totalNum + 1; // 总订单数。一条订单计数1
}
// 如果没有,则说明是该省第一个订单
else{
obj.totalAmount = finalTotalAmount; // 累加金额
obj.totalNum = 1; // 总订单数。一条订单计数1
}
dataMap.set(provinceName, obj); // 将更新后的obj存入map
}
// 计算每个省的平均消费额
var avgMap = new Map();
for (var [province, accObj] of dataMap) {
var avgConsumAmount = Math.round((accObj.totalAmount / accObj.totalNum) * 100) / 100; // 保留两位小数
avgMap.set(province, avgConsumAmount); // {省份,平均消费金额}
}
// 先转为数组,再按金额排序,然后取前5个
var top5Arr = Array.from(avgMap).sort((a,b) => b[1] - a[1]).slice(0,5)
// 遍历top5Arr,取x轴值(省份名称)和y轴值(该省总金额)
var xs = []; // 存储x轴数据
var ys = []; // 存储y轴数据
for (var [key, value] of top5Arr) {
xs.unshift(key); // 省份值,放入x轴
ys.unshift(value);// 平均消费金额,放入y轴
}
// 以json对象形式返回
return {"x":xs,"y":ys};
}
</script>
(2) 修改主组件App.vue,添加导航链接和渲染组件,代码如下:
<template>
<div class="menu">
<h3>请选择分析结果</h3>
<ul>
<!--使用 router-link 组件进行导航 -->
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/task01">任务1:用柱状图展示消费额最高的省份</router-link></li>
<li><router-link to="/task02">任务2:用饼状图展示各地区消费能力</router-link></li>
<li><router-link to="/task04">任务4:用散点图展示每年上架商品数量的变化</router-link></li>
<li><router-link to="/task06">任务6:用条形图展示平均消费额最高的省份</router-link></li>
</ul>
</div>
<div class="graph">
<!-- 渲染在这里 -->
<router-view></router-view>
</div>
</template>
(3) 修改入口文件main.js,导入路由组件文件并指定路由映射,主要修改部分如下:
// 程序入口文件
...
// 1. 定义路由组件.
import Home from "./views/HomeView.vue"
import Task01 from "./views/Task01View.vue"
import Task02 from "./views/Task02View.vue"
import Task04 from "./views/Task04View.vue"
import Task06 from "./views/Task06View.vue"
// 2. 定义一些路由映射
const routes = [
{ path: '/', component: Home },
{ path: '/task01', component: Task01 },
{ path: '/task02', component: Task02 },
{ path: '/task04', component: Task04 },
{ path: '/task06', component: Task06 },
]
...
(4) 执行Vue应用程序。
在VS Code编辑器下方的“终端”窗口中,执行如下命令,启动开发服务器:
$ npm run serve
打开浏览器,访问http://localhost:8080/,点击左侧的链接,就可以看到在右侧显示相应的条形图。
子任务七:用折柱混合图展示省份平均消费额和地区平均消费额
任务描述
-
编写Vue工程代码,根据接口,用折柱混合图展示2020年各省份平均消费额(四舍五入保留两位小数)和地区平均消费额(四舍五入保留两位小数)的对比情况,柱状图展示平均消费额最高的5个省份,折线图展示这5个省所在的地区的平均消费额变化,同时将用于图表展示的数据结构在浏览器的console中进行打印输出,将图表可视化结果和浏览器console打印结果分别截图并粘贴至客户端桌面【Release\任务E提交结果.docx】中对应的任务序号下。
请按以下步骤操作。
(1) 在项目的src/views/目录下,新建一个名为Task07View.vue的文件,编辑代码如下:
<template>
<h2>折柱混合图</h2>
<div class="left">
<!-- echarts图表绘制在这里 -->
<div id="canvas" style="width: 580px;height:500px;"></div>
</div>
<div class="right">
<p><pre>{{ items }}</pre></p>
</div>
</template>
<script>
import * as echarts from '../assets/echarts.min.js'
// 请求的RESTful API 接口中(请替换为你自己的IP)
var url = "http://IP:8999/dataVisualization/selectOrderInfo"
var params = '{"startTime":"2020-01-01 00:00:00", "endTime":"2020-12-31 23:59:59"}'
export default {
name: 'TaskTop',
data () {
return {
items: ''
}
},
mounted () {
// 根据准备好的dom初始化echarts实例
var myChart = echarts.init(document.getElementById('canvas'));
// 使用刚才指定的配置项和数据显示图表
myChart.setOption({
title: {
text: '用折柱混合图展示省份平均消费额和地区平均消费额',
subtext: '2020年',
left: 'center'
},
tooltip: {
trigger:'axis',
formatter: '{b0}<br />{a0}: {c0}<br />{a1}: {c1}'
},
legend: {
data: ['省平均消费额','地区平均消费额'], // 要和series.name一致
x:'center',
y:'bottom'
},
xAxis: {
type: 'category',
data: [] // **** ajax请求回来的数据要填充到这里
},
yAxis: [
{
type: 'value',
name: '省平均消费额',
},
{
type: 'value',
name: '地区平均消费额',
}],
series: [
{
name: '省平均消费额',
type: 'bar',
barWidth : '50%',
data: [] // **** ajax请求回来的数据要填充到这里
},{
name: '地区平均消费额',
type: 'line',
smooth:true,
data: [] // **** ajax请求回来的数据要填充到这里
}
]
});
// fetch请求
fetch(url, {
method: "post",
headers: {'content-type': 'application/json'},
body: params
}
)
.then((response) => {
// 取出响应中的json数据 *
return response.json();
})
.then((data) => {
// 从返回的json数据中,抽取数据
var jsObj = getAvgConsumption(data.data);
// 将用于图表展示的数据结构在浏览器的console中进行打印输出
console.log(jsObj)
// 设置响应数据显示在右侧,便于观察
// this.items = JSON.stringify(data,null,"\t\t\t");
this.items = jsObj
// 刷新echarts数据
var option = myChart.getOption();
option.xAxis[0].data = jsObj.a; // 省份名称
option.series[0].data = jsObj.b; // 省份平均消费top5
option.series[1].data = jsObj.c; // 所属地区的平均消费额
myChart.setOption(option);
})
.catch(error => { // 请求失败处理
console.log(error);
})
.then(() => {
this.loading = false;
});
}
}
// 汇总统计各省和地区的平均消费金额,并构造在echarts中显示的数据
function getAvgConsumption(jsArray){
// 各个省的平均消费金额
var mapByProvince = getAvgConsumptionByProvince(jsArray);
// 各个地区的平均消费金额
var mapByRegion = getAvgConsumptionByArea(jsArray);
// top 5
// 先转为数组,再按金额排序,然后取前5个
var top5Arr = Array.from(mapByProvince).sort((a,b) => b[1].avgConsumAmount - a[1].avgConsumAmount).slice(0,5)
// 遍历top5Arr,需要返回 省份名称数组,各省份平均消费额数组,各地区平均消费额数组
var provinces = []; // 存储省份名称
var avgByPorvinces = []; // 存储各省份平均消费额
var avgByRegions = []; // 存储各地区平均消费额
for (var [key, value] of top5Arr) {
provinces.push(key); // 放入省份名称
avgByPorvinces.push(value.avgConsumAmount); // 放入各省份平均消费额
// 该省所属地区的平均消费额
avgByRegions.push(mapByRegion.get(value.regionName)); // 根据地区名,获取该地区的平均消费额
}
// 以对象形式返回
return {a:provinces, b:avgByPorvinces, c:avgByRegions};
}
// 统计各个省的平均消费金额
function getAvgConsumptionByProvince(jsArray){
// 存储每个省及其总金额、总订单数
var dataMap = new Map();
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象
var provinceName = jsObj.provinceName; // 订单所属省份
var finalTotalAmount = jsObj.finalTotalAmount; // 订单金额
var regionName = jsObj.regionName; // 订单所属地区
// 构造一个对象,存储某省份的累加金额和累加订单数(以便计算平均金额)
var obj = new Object();
// 如果有该省份,则累加金额和数量
if(dataMap.has(provinceName)){
var accOjb = dataMap.get(provinceName); // 获得原来累加的对象
obj.totalAmount = accOjb.totalAmount + finalTotalAmount; // 累加金额
obj.totalNum = accOjb.totalNum + 1; // 总订单数。一条订单计数1
obj.regionName = regionName; // 所在地区
}
// 如果没有,则说明是该省第一个订单
else{
obj.totalAmount = finalTotalAmount; // 累加金额
obj.totalNum = 1; // 总订单数。一条订单计数1
obj.regionName = regionName; // 所在地区
}
dataMap.set(provinceName, obj); // 将更新后的obj存入map
}
// 计算每个省的平均消费额
var avgMap = new Map();
for (var [province, accObj] of dataMap) {
var avgConsumAmount = Math.round((accObj.totalAmount / accObj.totalNum) * 100) / 100; // 保留两位小数
avgMap.set(province, {avgConsumAmount: avgConsumAmount, regionName: accObj.regionName}); // {省份,{平均消费金额,所属省份}}
}
return avgMap;
}
// 统计各个地区的平均消费金额
function getAvgConsumptionByArea(jsArray){
// 存储每个省及其总金额、总订单数
var dataMap = new Map();
for (var index in jsArray){ // 这里遍历的是索引
var jsObj = jsArray[index] // 根据索引获得对象
var regionName = jsObj.regionName; // 订单所属地区
var finalTotalAmount = jsObj.finalTotalAmount; // 订单金额
// 构造一个对象,存储某地区的累加金额和累加订单数(以便计算平均金额)
var obj = new Object();
// 如果有该省份,则累加金额和数量
if(dataMap.has(regionName)){
var accOjb = dataMap.get(regionName); // 获得原来累加的对象
obj.totalAmount = accOjb.totalAmount + finalTotalAmount; // 累加金额
obj.totalNum = accOjb.totalNum + 1; // 总订单数。一条订单计数1
}
// 如果没有,则说明是该地区第一个订单
else{
obj.totalAmount = finalTotalAmount; // 累加金额
obj.totalNum = 1; // 总订单数。一条订单计数1
}
dataMap.set(regionName, obj); // 将更新后的obj存入map
}
// 计算每个地区的平均消费额
var avgMap = new Map();
for (var [region, accObj] of dataMap) {
var avgConsumAmount = Math.round((accObj.totalAmount / accObj.totalNum) * 100) / 100; // 保留两位小数
avgMap.set(region, avgConsumAmount); // {省份,平均消费金额}
}
return avgMap;
}
</script>
(2) 修改主组件App.vue,添加导航链接和渲染组件,代码如下:
<template>
<div class="menu">
<h3>请选择分析结果</h3>
<ul>
<!--使用 router-link 组件进行导航 -->
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/task01">任务1:用柱状图展示消费额最高的省份</router-link></li>
<li><router-link to="/task02">任务2:用饼状图展示各地区消费能力</router-link></li>
<li><router-link to="/task04">任务4:用折线图展示每年上架商品数量的变化</router-link></li>
<li><router-link to="/task06">任务6:用条形图展示平均消费额最高的省份</router-link></li>
<li><router-link to="/task07">任务7:用折柱混合图展示省份平均消费额和地区平均消费额</router-link></li>
</ul>
</div>
<div class="graph">
<!-- 渲染在这里 -->
<router-view></router-view>
</div>
</template>
(3) 修改入口文件main.js,导入路由组件文件并指定路由映射,主要修改部分如下:
// 程序入口文件
...
// 1. 定义路由组件.
import Home from "./views/HomeView.vue"
import Task01 from "./views/Task01View.vue"
import Task02 from "./views/Task02View.vue"
import Task04 from "./views/Task04View.vue"
import Task06 from "./views/Task06View.vue"
import Task07 from "./views/Task07View.vue"
// 2. 定义一些路由映射
const routes = [
{ path: '/', component: Home },
{ path: '/task01', component: Task01 },
{ path: '/task02', component: Task02 },
{ path: '/task04', component: Task04 },
{ path: '/task06', component: Task06 },
{ path: '/task07', component: Task07 },
]
...
(4) 执行Vue应用程序。
在VS Code编辑器下方的“终端”窗口中,执行如下命令,启动开发服务器:
$ npm run serve
打开浏览器,访问http://localhost:8080/
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
暂无评论内容