结对作业(二):某次疫情统计的可视化实现

这个作业属于哪个课程 2020软件工程W班
这个作业要求在哪里 结对作业(二)要求
结对学号 <221701436><181700141>
这个作业的目标 使用Echarts等框架和技术做出像模像样的疫情统计页面
作业正文 本文链接在这里!
其他参考文献 bilibili的教学视频


1.成品展示

光标移动到地图上方显示高亮和数据

点击某省份跳转至趋势图页面

点击滚动新闻的“查看详情”进入详情页

2、结对讨论及设计思路

延续上次结对作业的思路,我们打算用Echarts来显示地图和趋势图,关于数据来源,我们用爬虫爬取了丁香园网站的数据

基本思路:利用fetch来获取data.json文件内容,然后将数据填入echarts图中。设置点击事件,当点击某一省份的时候跳转页面到province.html来显示该省份具体情况(趋势图等)

  • 讨论截图


虽然讨论思路之路曲曲折折,我们最终形成了上述设计思路

3、代码说明

+功能结构模式图

  • spider.js
const superagent = require('superagent');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');

const url = `https://ncov.dxy.cn/ncovh5/view/pneumonia`;
superagent
    .get(url)
    .then(res => {
        //console.log(res.text); //响应的内容,浏览器可以解析html 但是node端不行
        const $ = cheerio.load(res.text);
        //获取全国疫情数据
        var $getListByCountryTypeService1 = $('#getListByCountryTypeService1').html();
        //获取统计数据
        var $getStatisticsService = $('#getStatisticsService').html();
        //console.log($getListByCountryTypeService1);
        //使用eval
        var dataObj = {};
        eval($getListByCountryTypeService1.replace(/window/g, 'dataObj'));
        eval($getStatisticsService.replace(/window/g, 'dataObj'));
        //console.log(dataObj);
        //将获取到的数据写入本地
        fs.writeFile(path.join(__dirname, './data.json'), JSON.stringify(dataObj), err => {
            if (err) throw err;
            console.log("数据写入成功");
        })

    })

设计思路:利用superagent包(一个http方面的库,可以发起get和post请求)和cheerio包(为服务器特别定制的、快速、灵活、实施的jQuery)来爬取数据,使用eval函数来处理数据最后将数据保存到data.json文件中。

  • 新型冠状病毒全国分布.html
   <!--将图标配置应用到容器里-->
    <script>

        //存储获取到的数据
        var epidemicData = [];
        fetch('./server/data.json')
            .then(res => res.json())//把可读的数据流转为json格式
            .then(res => {
                //console.log(res);
                //获取各省数据
                var getListByCountryTypeService1 = res.getListByCountryTypeService1;
                //处理返回的数据,转为echarts可直接使用的数据
                getListByCountryTypeService1.forEach(element => {
                    epidemicData.push({
                        name: element.provinceShortName,
                        value: element.currentConfirmedCount,//当前确诊人数(显示)
                        confirmedCount: element.confirmedCount,//累计确诊人数
                        deadCount: element.deadCount,//死亡人数(显示)
                        curedCount: element.curedCount,//治愈人数(显示)
                        time: element.modifyTime//时间(不显示)

                    });
                    //获取全国数据,以及和昨日对比的数据
                    var getStatisticsService = res.getStatisticsService;
                    //console.log(getStatisticsService.confirmedIncr);
                    //更新网页上全国数据以及和昨日对比的数据
                    document.getElementById('currentConfirmedCount').innerHTML = "现有确诊" + getStatisticsService.currentConfirmedCount;
                    document.getElementById('confirmedCount').innerHTML = "累计确诊" + getStatisticsService.confirmedCount;
                    document.getElementById('suspectedCount').innerHTML = "疑似人数" + getStatisticsService.suspectedCount;
                    document.getElementById('curedCount').innerHTML = "治愈人数" + getStatisticsService.curedCount;
                    document.getElementById('deadCount').innerHTML = "死亡人数" + getStatisticsService.deadCount;
                    document.getElementById('seriousCount').innerHTML = "现存重症" +getStatisticsService.seriousCount;
                    document.getElementById('suspectedIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.suspectedIncr);
                    document.getElementById('currentConfirmedIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.currentConfirmedIncr);
                    document.getElementById('confirmedIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.confirmedIncr);
                    document.getElementById('curedIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.curedIncr);
                    document.getElementById('deadIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.deadIncr);
                    document.getElementById('seriousIncr').innerHTML = "较昨日" + signedNum(getStatisticsService.seriousIncr);
                    //更新网页上关于疫情的描述,如潜伏期、宿主等
                    document.getElementById('susceptiblePop').innerHTML = getStatisticsService.remark1;
                    document.getElementById('incubationPeriod').innerHTML = getStatisticsService.remark2;
                    document.getElementById('parasitifer').innerHTML = getStatisticsService.remark3;
                    document.getElementById('virus').innerHTML = getStatisticsService.note1;
                    document.getElementById('source').innerHTML = getStatisticsService.note2;
                    document.getElementById('route').innerHTML = getStatisticsService.note3;
                    //更新时间
                    var date = new Date(parseInt(getStatisticsService.modifyTime));
                    document.getElementById('time').innerHTML = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
                    //最新资讯
                     var breaknews =getStatisticsService.marquee;

利用fetch来获取data.json文件内容,然后将数据填入echarts图中。设置点击事件,当点击某一省份的时候跳转页面到province.html来显示该省份具体情况

 myChart.on('click', function (params) {
                    //南海诸岛不跳转
                    if (typeof (params.data) == typeof (undefined)) {
                        alert("暂无详细数据");
                        return;
                    }
                    if (params.data.name == "台湾" || params.data.name == "香港" || params.data.name == "澳门") {
                        alert("暂无详细数据");
                        return;
                    }
                    //console.log(params.data);
                    //跳转页面,同时对参数进行编码               
                    window.location.href = `./province.html?` +
                        window.btoa(window.encodeURIComponent(`name=${params.data.name}&currentConfirmedCount=${params.data.value}
                        &confirmedCount=${params.data.confirmedCount}&deadCount=${params.data.deadCount}&curedCount=${params.data.curedCount}
                        &time=${params.data.time}`));
                });

            })

设置点击事件,南海诸岛、港澳台不提供详细数据。利用window.location.href来实现页面跳转,利用window.bota对传递的参数进行编码使得参数值不可直接看出。传递的参数有:点击的省份名、该省的当前确诊人数、累计确诊人数、死亡和治愈人数以及这些数据最近更新的时间。

  • province.html
<script>
        //获得参数字符串
        var paramsString = window.location.search.substring(1);
        //解码
        paramsString = window.decodeURIComponent(window.atob(paramsString));
        //存储个参数及其值
        var params = {};
        //以&为边界将参数字符串拆分为数组
        var parameters = paramsString.split('&');
        for (var i = 0; i < parameters.length; i++) {
            var s = parameters[i];
            var l = s.length;
            var index = s.indexOf('=');
            var key = s.substring(0, index);
            var value = s.substring(index + 1);
            params[key] = value;

        }
        //省份
        var province = params.name;
        //存放该省份的确诊数据
        var confirmData = [];
        //存放该省份的治愈数据
        var cureData = [];
        //存放该省份的死亡数据
        var deathData = [];

        //更新页面上关于省份、现存确诊等的描述
        document.getElementById('province').innerHTML = province+"疫情趋势图";
        document.getElementById('currentConfirmedCount').innerHTML = "现存确诊\n" + params.currentConfirmedCount;
        document.getElementById('confirmedCount').innerHTML = "累计确诊\n" + params.confirmedCount;
        document.getElementById('deadCount').innerHTML = "死亡人数\n" + params.deadCount;
        document.getElementById('curedCount').innerHTML = "治愈人数\n" + params.curedCount;
        //更新时间
        var date = new Date(parseInt(params.time));
        //console.log(date);
        document.getElementById('time').innerHTML = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`

        //获得确诊数据并画出趋势图
        fetch(`./confirmData/${province}.txt`)
            .then(res => res.text())
            .then(res => {
                confirmData = JSON.parse(res);
                var myChart = echarts.init(document.getElementById("confirmData"));
                var option = {
                    title: {
                        text: `${province}确诊人数趋势图`,
                        left: 'center'
                    },
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {
                            type: 'shadow'
                        },
                    },
                    legend: {
                        data: ['确诊人数'],
                        left: 'right',
                        top: '5%'
                    },
                    xAxis: {
                        //设置x轴为时间轴
                        type: 'time'
                    },
                    yAxis: {
                        name: '人'
                    },
                    series: [{
                        name: '确诊人数',
                        type: 'line',
                        data: confirmData,
                        symbolSize: 8,   //拐点圆的大小
                        color: ['red'],//折线条的颜色
                        itemStyle: {
                            normal: {
                                lineStyle: {
                                    width: 3
                                }
                            }
                        },
                    }]
                };
                myChart.setOption(option);
            });//end of then

基本思路:通过传递过来的参数读取相应的数据文件然后显示。

通过fetch获取数据文件并处理后可直接将将数据赋予echarts图,txt文件内容为[[“XXXX-XX-XX”,Y],[“XXXX-XX-XX”,Y],…]其中XXXX-XX-XX为日期,Y为人数(如果是在confirmData文件夹里,就是确诊人数),文件名为省份名。

心路历程及队友评价

本次作业算是有一些挑战性的,因为我们一开始不知道实现这次作业需要什么技术,但是在经过讨论之后,加上有教学视频,通过对新知识的学习摸索,我们逐渐拓宽道路,分工合作。在这期间,我们碰到了一些印象比较深的困难:

  • 1、fetch获取本地数据

未安装LiveServer前,通过fetch读取本地文件报错:Fetch APT cannot load XXXX URL scheme must be "http" or "https" for CORS request.然后就去寻找解决方法,刚开始通过tomcat将data.json文件放到服务器上,然后在再去获取,还是报错;通过百度发现是因为浏览器安全限制不允许跨域访问,然后就百度修改了web.xml文件,ok可以运行。最后百度的时候看到可以安装LiveServer来实现fetch访问本地文件。

  • 2、跳转页面时隐藏参数

刚开始直接通过window.bota直接编码来实现隐藏参数,但是对于中文乱码。百度发现window.bota只能针对ANSI然后看到一篇博客说可以先采用window.encodeURIComponent编码再是利用window.bota就可对中文编码。

队友评价:

  • 221701436林晟:没想到队友在写代码的时候可以那么投入,而且思维还很敏捷,是我值得学习的对象;经过与队友的合作我认为我可以磨炼协商技巧,还应该克服拖延症。

  • 181700141吴鸿敬:本次合作最终还是在截止日期前完成,与队友的合作虽然有时在一些问题上看法不相同;但是在经过交流后还是可以取得一致。从本次与队友合作开发项目的过程中学到了:对项目的完成应该设置多个时间节点,同时要按时完成。

posted @ 2020-03-14 20:41  炽_风  阅读(341)  评论(4编辑  收藏  举报