主页 > 软件开发  > 

vue前端案例教学:动态获取最新疫情数据展示(代码详解)

vue前端案例教学:动态获取最新疫情数据展示(代码详解)

【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步! 吾等采石之人,应怀大教堂之心,愿我们奔赴在各自的热爱里…

一、案例介绍

分享原因:最近看到这样的实时显示的系统觉得很有趣,分享给vue前端初学者实践学习 具体的效果如图所示

数据分析:数据来源于第三方官方提供的API接口,我们调用即可获取对应接口,拿到显示出来即实时展示

百度一下有很多可以直接调用的第三方接口

实时最新疫情数据接口

c.m.163 /ug/api/wuhan/app/data/list-total

实时播报:时间线的对应接口

ent.163 /special/00035080/virus_report_data.js


二、后端代码

后端使用HttpClient创建对象,执行对应的请求即可~

@Slf4j @RestController @RequestMapping("/demo") public class DemoController { @ApiOperation("/HttpClient使用代码案例") @GetMapping("/getData") public Result getJsonTypeData(@RequestParam(name = "url", required = true) String url) throws Exception { Result result = new Result(); //创建HttpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); //设置请求传输超时时间 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) .setConnectionRequestTimeout(5000) .setSocketTimeout(5000) .setRedirectsEnabled(true) .build(); //创建get请求 HttpGet httpGet = new HttpGet(url); //设置配置 httpGet.setConfig(requestConfig); // 执行请求 HttpResponse httpResponse = httpClient.execute(httpGet); //判断响应信息是否正确 if (httpResponse.getStatusLine().getStatusCode() == 200) { String jsonResult = EntityUtils.toString(httpResponse.getEntity()); JSONObject jsonObject = JSONObject.parseObject(jsonResult); result.setData(jsonObject); result.setCode(200); } return result; } @ApiOperation("/实时播报:时间线的对应接口:此处仅给右下角显示使用") @GetMapping("/getTimeLine") public Result getNoJsonType(@RequestParam(name = "url", required = true) String url) throws IOException { Result result = new Result(); //创建HttpClient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) .setConnectionRequestTimeout(5000) .setSocketTimeout(5000) .setRedirectsEnabled(true) .build(); HttpGet httpGet = new HttpGet(url); httpGet.setConfig(requestConfig); HttpResponse httpResponse = httpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() == 200) { String jsonResult = EntityUtils.toString(httpResponse.getEntity()); result.setData(jsonResult); result.setCode(200); } return result; } }
三、前端代码

主页面代码以及效果

<template> <div class="container"> <el-card class="box-card1"> <div slot="header" class="title">全国疫情数据(含港澳台)</div> <div class="list-total"> <div class="item cover_input"> <h4>境外输入</h4> <div class="number">{{ total.input }}</div> <p class="added"> 较昨日 <span>+{{ today.input }}</span> </p> </div> <div class="item cover_nosymptom"> <h4>无症状感染者</h4> <div class="number">{{ extData.noSymptom }}</div> <p class="added"> 较昨日 <span>+{{ extData.incrNoSymptom }}</span> </p> </div> <div class="item cover_today_confirm"> <h4>现有确诊</h4> <div class="number"> {{ total.confirm - total.dead - total.heal }} </div> <p class="added"> 较昨日 <span>+{{ today.storeConfirm }}</span> </p> </div> <div class="item cover_confirm"> <h4>累计确诊</h4> <div class="number">{{ total.confirm }}</div> <p class="added"> 较昨日 <span>+{{ today.confirm }}</span> </p> </div> <div class="item cover_dead"> <h4>累计死亡</h4> <div class="number">{{ total.dead }}</div> <p class="added"> 较昨日 <span>+{{ today.dead }}</span> </p> </div> <div class="item cover_heal"> <h4>累计治愈</h4> <div class="number">{{ total.heal }}</div> <p class="added"> 较昨日 <span>+{{ today.heal }}</span> </p> </div> </div> <div class="cover_time">截至{{ lastUpdateTime }}</div> </el-card> <china-map></china-map> <line-chart id="line-chart"></line-chart> <time-line id="time-line"></time-line> </div> </template> <script> import request from "@/utils/request"; import LineChart from './components/lineChart.vue' import ChinaMap from './components/map.vue' import TimeLine from './components/timeLine.vue' export default { name: 'Statistics', components: { LineChart, ChinaMap, TimeLine, }, data() { return { total: {}, today: {}, extData: {}, lastUpdateTime: '', } }, created() { this.getInfo() }, mounted() { }, methods: { getInfo() { request.get("/demo/getData", { params: { url: ' c.m.163 /ug/api/wuhan/app/data/list-total', } }).then(data => { this.today = data.data.data.chinaTotal.today this.total = data.data.data.chinaTotal.total this.extData = data.data.data.chinaTotal.extData this.lastUpdateTime = data.data.data.lastUpdateTime }) }, }, } </script> <style lang="scss" scoped> .box-card1 { width: 440px; float: left; margin-left: 20px; } .list-total { display: flex; flex-wrap: wrap; justify-content: space-around; } .title { color: #333; font-size: 24px; } .item { width: 120px; height: 100px; margin-bottom: 15px; border: 1px dashed #ccc; display: flex; flex-direction: column; justify-content: center; align-content: space-around; } h4 { text-align: center; color: #333; } .number { text-align: center; color: #ffa352; font-weight: 700; font-size: 26px; } .added { text-align: center; color: #999; } .added span { color: #ffa352; } .cover_nosymptom .added span { color: #791618; } .cover_nosymptom .number { color: #791618; } .cover_today_confirm .number { color: #e44a3d; } .cover_today_confirm .added span { color: #e44a3d; } .cover_confirm .number { color: #a31d13; } .cover_confirm .added span { color: #a31d13; } .cover_dead .number { color: #333; } .cover_dead .added span { color: #333; } .cover_heal .number { color: #34aa70; } .cover_heal .added span { color: #34aa70; } .cover_time { color: #a9a9a9; } </style>

疫情地图显示效果

对应前端代码

<template> <el-card class="box-card"> <div id="map"></div> </el-card> </template> <script> import * as echarts from 'echarts' import china from 'echarts/map/js/china' import request from "@/utils/request"; let option = { title: { text: '中国疫情图', }, series: [ { name: '现有确诊', //控制鼠标hover上去显示的固定文本 type: 'map', //告诉echarts需要渲染一个地图 mapType: 'china', //告诉echarts要渲染注册的china地图 label: { show: true, //控制是否显示省份的名称 color: '#333', // 设置显示每个省份的字体颜色 }, itemStyle: { borderColor: '#e8e8e8', //每个省份的边界的颜色 }, emphasis: { //控制鼠标移入的版块的颜色 color: '#fff', //移入该模块的字体颜色 itemStyle: { areaColor: '#83b5e7', //鼠标hover到模块上的背景色 }, }, data: [], //每个板块的数据 }, ], visualMap: [ { type: 'piecewise', //左下角的分段显示 show: true, pieces: [ { min: 10000, max: 1000000, label: '≥ 10000人', color: '#7f1100', }, { min: 1000, max: 9999, label: '1000 - 9999人', color: '#bd1316', }, { min: 500, max: 999, label: '500 - 999人', color: '#e64b45', }, { min: 100, max: 499, label: '100 - 499人', color: '#ff8c71', }, { min: 10, max: 99, label: '10 - 99人', color: '#fdd2a0', }, { min: 1, max: 9, label: '1 - 9人', color: '#fff2cf', }, { min: 0, max: 0, label: '0', color: '#ffffff', }, ], color: ['#fafafa', '#7f1100'], }, ], tooltip: { //控制鼠标hover上去显示信息 trigger: 'item', formatter: function (params) { //自定义悬浮窗的显示内容 return params.name + '<br/>' + params.seriesName + ':' + params.value }, }, } export default { // 组件名称 name: 'ChinaMap', // 组件参数 接收来自父组件的数据 props: {}, // 组件状态值 data() { return {} }, // 计算属性 computed: {}, // 侦听器 watch: {}, // 以下是生命周期钩子 /** * 组件实例创建完成,属性已绑定,但DOM还未生成,$ el属性还不存在 */ created() {}, /** * el 被新创建的 vm.$ el 替换,并挂载到实例上去之后调用该钩子。 * 如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$ el 也在文档内。 */ mounted() { this.getData() this.myEcharts = echarts.init(document.getElementById('map')) this.myEcharts.setOption(option) }, // 组件方法 methods: { getData() { request.get("/demo/getData", { params: { url: ' c.m.163 /ug/api/wuhan/app/data/list-total', } }).then(data => { let list = data.data.data.areaTree[2].children.map((item) => ({ name: item.name, value: item.total.confirm - item.total.heal - item.total.dead, })) option.series[0].data = list this.myEcharts.setOption(option) }) }, }, } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <!--使用了scoped属性之后,父组件的style样式将不会渗透到子组件中,--> <!--然而子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,--> <!--这么设计的目的是父组件可以对子组件根元素进行布局。--> <style scoped> #map { width: 100%; height: 400px; background-color: #f3f3f3; } .box-card { width: 750px; float: left; margin-left: 20px; } </style>

折线图显示效果

折线图对应代码

<template> <el-card class="card-linechart"> <div id="linechart"></div> </el-card> </template> <script> import * as echarts from 'echarts' import request from "@/utils/request"; var option = { title: { text: '全国疫情新增趋势', }, tooltip: { trigger: 'axis', }, legend: { right: '20px', data: ['确诊', '疑似'], }, xAxis: { type: 'category', boundaryGap: false, data: [], }, yAxis: { type: 'value', data: ['0', '20', '40', '60', '80', '100', '120', '140'], }, series: [ { name: '确诊', type: 'line', data: [], }, { name: '疑似', type: 'line', data: [], }, ], } export default { // 组件名称 name: 'LineChart', // 组件参数 接收来自父组件的数据 props: {}, // 组件状态值 data() { return { chinaDayList: [], } }, // 计算属性 computed: {}, // 侦听器 watch: {}, // 以下是生命周期钩子 /** * 组件实例创建完成,属性已绑定,但DOM还未生成,$ el属性还不存在 */ created() { }, /** * el 被新创建的 vm.$ el 替换,并挂载到实例上去之后调用该钩子。 * 如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$ el 也在文档内。 */ mounted() { this.getData() this.myChart = echarts.init(document.getElementById('linechart')) this.myChart.setOption(option) }, // 组件方法 methods: { getData() { request.get("/demo/getData", { params: { url: ' c.m.163 /ug/api/wuhan/app/data/list-total', } }).then(data => { this.chinaDayList = data.data.data.chinaDayList option.series[0].data = [] option.series[1].data = [] option.xAxis.data = [] this.chinaDayList.forEach((item, index) => { option.xAxis.data.push(item.date) option.series[0].data.push(item.today.confirm) option.series[1].data.push(item.today.suspect) }) this.myChart.setOption(option) }) }, }, } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <!--使用了scoped属性之后,父组件的style样式将不会渗透到子组件中,--> <!--然而子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,--> <!--这么设计的目的是父组件可以对子组件根元素进行布局。--> <style scoped> .card-linechart { float: left; width: 500px; } #linechart { width: 100%; height: 400px; } </style>

时间线实现效果

时间线实现前端代码

<template> <el-card class="box-timeline"> <div slot="header" class="bobao">实时播报</div> <el-timeline class="time-container"> <el-timeline-item v-for="(item, index) in timeLineList" :key="index" :timestamp="item.time" placement="top" > <el-card class="content"> <div class="tit">{{ item.title }}</div> <a :href="item.link" target="_blank" class="detail">查看详细报道</a> </el-card> </el-timeline-item> </el-timeline> </el-card> </template> <script> import request from "@/utils/request"; export default { // 组件名称 name: 'TimeLine', // 组件参数 接收来自父组件的数据 props: {}, // 组件状态值 data() { return { timeLineList: [], } }, // 计算属性 computed: {}, // 侦听器 watch: {}, // 以下是生命周期钩子 /** * 组件实例创建完成,属性已绑定,但DOM还未生成,$ el属性还不存在 */ created() { this.getData() }, /** * el 被新创建的 vm.$ el 替换,并挂载到实例上去之后调用该钩子。 * 如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$ el 也在文档内。 */ mounted() { }, // 组件方法 methods: { getData() { request.get("/demo/getTimeLine", { params: { url: ' ent.163 /special/00035080/virus_report_data.js', } }).then(data => { let str = data.data this.timeLineList = eval( '(' + str.slice(str.indexOf('(') + 1, -1) + ')' ).list.slice(0, 10) }) }, }, } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <!--使用了scoped属性之后,父组件的style样式将不会渗透到子组件中,--> <!--然而子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,--> <!--这么设计的目的是父组件可以对子组件根元素进行布局。--> <style scoped> .box-timeline { width: 500px; float: left; margin-left: 20px; } .bobao { height: 20px; font-weight: 700; font-size: 18px; } .time-container { /* width: 100%; */ height: 400px; overflow: auto; } .content { width: 340px; background-color: #f4f4f4; border-radius: 8px; } .tit { font-weight: 600; font-size: 18px; } .detail { color: #999; margin-top: 20px; display: block; position: relative; } .detail::before { position: absolute; content: ''; right: 200px; top: 3px; width: 12px; height: 12px; background: url('./../../images/arrow.png') no-repeat; background-size: 100% 100%; } </style>

本来很早就写好了,发的比较晚,当自己学习了

好了,未来争取输出更多干货视文章……


📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!

📚愿我们奔赴在各自的热爱里!我们未来见……

标签:

vue前端案例教学:动态获取最新疫情数据展示(代码详解)由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“vue前端案例教学:动态获取最新疫情数据展示(代码详解)