結對第二次作業——某次疫情統計可視化的實現
這個作業屬於哪個課程 | https://edu.cnblogs.com/campus/fzu/2020SpringW/ |
---|---|
這個作業要求在哪里 | https://edu.cnblogs.com/campus/fzu/2020SpringW/homework/10456 |
這個作業的目標 | 某次疫情統計可視化的實現 |
結對學號 | 061700150、071703434 |
作業正文 | 作業正文 |
其他參考文獻 | ... |
1.Github倉庫地址
2.展示你的成品
功能1:實現通過地圖的形式來直觀顯示疫情的大致分布情況,還可以查看具體省份的疫情統計情況
-
可以選擇具體的日期
-
顯示對應的感染患者人數、疑似患者人數、治愈人數、死亡人數;
-
在全國地圖上使用不同的顏色代表大概確診人數區間,顏色的深淺表示疫情的嚴重程度,可以直觀了解高危區域;
-
鼠標移到每個省份會高亮顯示;
-
點擊鼠標會顯示該省具體疫情情況;
功能2:點擊某個省份顯示該省疫情的具體情況
-
顯示該省份對應的感染患者人數、疑似患者人數、治愈人數、死亡人數;
-
該省份到目前為止的新增確診趨勢、新增疑似趨勢、治愈趨勢和死亡趨勢
-
繪制該省份的趨勢變化曲線圖;
3.結對討論過程描述
-
初步討論分工
-
前端布局過程
-
開始拓展功能
-
發現遺漏需求,放棄擴展功能
-
數據清洗處理,首先找了GitHub上開源的數據,發現數據不可以直接拿來用,因為數據多且不是每天對應的每個省份的數據,因此數據處理和清洗太花了很多時間,還是放棄,然后又用了天行的數據接口,數據處理很簡化也還是花了很長的時間
4.描述設計實現過程
前端
- 概況:使用vue-cli,易上手的MVVM框架,由於組件較少沒有使用vuex和vue-router
- 頁面結構:index.html內掛載了statis.vue(其內又有bar.vue)、navi.vue、query.vue(胎死腹中)
- 頁面布局:都是現寫的,
后端
- 概況:使用node環境下的express,nginx負責代理及分發api
- 數據來源:首先是https://lab.isaaclin.cn/nCoV/api/area,但它提供的省份時間數據過於混亂和離譜,后期又在前人大佬的啟發下緊急換上了http://api.tianapi.com/txapi//ncovcity/
- 調用:
https://ncov.funx.pro/api/ncov/getAll POST請求無參數,返回全國最新數據
https://ncov.funx.pro/api/ncov/getAllTime POST請求,參數為time:時間,例如'2020-02-20',返回全國最新數據
https://ncov.funx.pro/api/ncov/getProv POST請求,參數為name:省份短寫,例如'黑龍江',返回全國最新數據

5.代碼說明
-
前端關鍵代碼說明
```
前端部分,使用Vue:
```
//部分代碼,完整部分位於開頭鏈接倉庫
updateDataList(info, date) {
var baseURL = "https://ncov.funx.pro" //后端base地址
var url = !date?"/api/ncov/getAll":'/api/ncov/getAllTime' //根據是否攜帶時間參數,調用不同的api
var param = !date?{}:{time:date} //根據是否有時間參數,判斷是否將其攜帶
return new Promise(resolve => { //異步Promise,返回一個拿到數據后的狀態
$ajax.post(baseURL + url, param).then(doc => { //Ajax
var arr = JSON.parse(doc.data.data); //string至object
arr.data.forEach(v => {
this.dataList.forEach((l, i) => { //遍歷拿到的省份數據,將其添加至響應式數據中
if (l.name == v.provinceShortName)
this.$set(this.dataList[i], "value", v[info]); //改變數組的值
});
});
resolve(arr); //返回狀態,以便下一步進行
});
});
},
initAll(info, date) {
this.showDialog = false; //顯示loading和過度用的,沒有使用echarts自帶loading
if (this.myChart) this.myChart.dispose(); //因為框架內遇到了一些無法解決的bug,只能在重載時銷毀ec實例
this.updateDataList(info, date).then(arr => {
if (this.allNum.inj[0] == 0 || date) { // 判斷 數據源未提供的標識 顯示為'--'
Object.keys(this.allNum).forEach(name => { // 六項基本疫情信息遍歷
if(!arr.statis[name] || (date&&name=='sus')){
this.allNum[name]=[-9999,-9999] // 數據源未提供的標識 顯示為'--'
return
}
var Time = 30, t = 0;
var base = this.allNum[name][0] // 加了一點很無聊的數字動畫....
var base2 = this.allNum[name][1] // 0是總項、1是變化項
var piece = ((arr.statis[name][0]-this.allNum[name][0]) / Time).toFixed(2); // 單次變化值
var piece2 = ((arr.statis[name][1]-this.allNum[name][1]) / Time).toFixed(2);// 單次變化值
//console.log(`目標${arr.statis[name][0]},當前${this.allNum[name][0]}`)
var timer = setInterval(() => {
this.$set(this.allNum[name], 0, base+ parseInt(piece * ++t));
this.$set(this.allNum[name], 1, base2+parseInt(piece2 * ++t));
if (t == Time) {
this.allNum[name][0] = arr.statis[name][0];
this.allNum[name][1] = arr.statis[name][1];
clearInterval(timer);
}
}, 16.6*2);
});
}
this.myChart = echarts.init(document.getElementById("main"));
-
后端關鍵代碼說明
```
后端部分,nodejs環境下獲得數據,再存入數據庫:
知名疫情網站的數據都是寫死的,所以,爬蟲是不存在的... ...
這是GitHub上某倉庫提供的(臟數據,浪費了很多很多時間)
```
//部分代碼,完整部分位於開頭鏈接倉庫
$ajax.get("https://lab.isaaclin.cn/nCoV/api/area").then(doc => {
// console.dir(doc.data)
var arr = [];
var obj = {
curInj: [0, 0],
inj: [0, 0],
sus: [0, 0],
cur: [0, 0],
dead: [0, 0],
bad: [0, 0]
};
doc.data.results.forEach(d => {
if (d.countryName == "中國") {
delete d.cities;
delete d.locationId;
delete d.continentEnglishName;
delete d.countryEnglishName;
delete d.continentName;
delete d.provinceEnglishName;
arr.push(d);
}
});
$ajax.get("https://lab.isaaclin.cn/nCoV/api/overall").then(doc2 => {
var doc2 = doc2.data.results[0];
obj.inj[0] = doc2.confirmedCount;
obj.curInj[0] = doc2.currentConfirmedCount;
obj.sus[0] = doc2.suspectedCount;
obj.cur[0] = doc2.curedCount;
obj.dead[0] = doc2.deadCount;
obj.bad[0] = doc2.seriousCount;
obj.inj[1] = doc2.confirmedIncr;
obj.curInj[1] = doc2.currentConfirmedIncr;
obj.sus[1] = doc2.suspectedIncr;
obj.cur[1] = doc2.curedIncr;
obj.dead[1] = doc2.deadIncr;
obj.bad[1] = doc2.seriousIncr;
var ncov = new Ncov({
name: "全國",
data: JSON.stringify({
data: arr,
statis: obj
})
});
ncov.save((err, data) => {
if (!err) console.log("ok");
});
});
});
-
數據處理關鍵代碼說明
```
上段小部分代碼整理出了很多臟數據,又花費了非常大量時間清理,但效果依舊不好。
所以最后,唉,還是用了前人大佬們發現的tianapi:
(國際后仰:什么是爬蟲啊 )
```
//部分代碼,完整部分位於開頭鏈接倉庫
const mongoose = require("mongoose");
// const $ajax = require('axios')
mongoose.connect(MONGOURL, {
useNewUrlParser: true,
useUnifiedTopology: true
});
const Ncov = mongoose.model("NCOV", new mongoose.Schema({
name: String,
data: String,
},
{ collection: "NCOV" }));
var MONTH = [-1, 31, 29, 10]
var m, d, i
var calen = []
for (m = 2; m <= 3; m++) {
for (m == 2 ? (d = 14) : (d = 1); d <= MONTH[m]; d++) {
var strd = d
if (strd <= 9) strd = '0' + strd
calen.push(`2020-0${m}-${strd}`)
}
}
var last = {}
function sleep(wait) {
return new Promise((res,rej) => {
setTimeout(() => {
res(wait);
},wait);
});
}
var last = {curInj: 0, inj: 0, dead: 0, sus: 0, cur: 0}
async function run(){
for (let i = 0; i < calen.length; i++) {
let calenItem = calen[i]
let doc = await $ajax.get(
`http://api.tianapi.com/txapi//ncovcity/index?key=${KEY}&date=${calenItem}`
)
console.log(calenItem)
var obj = {
data: [],
statis: {curInj: [0, 0], inj: [0, 0], dead: [0, 0], sus: [0, 0], cur: [0, 0]}
}
doc = doc.data.newslist
doc.forEach(v => {
delete v.provinceName
delete v.cities
delete v.comment
delete v.locationId
delete v.statisticsData
obj.data.push(v)
obj.statis.curInj[0] += v.currentConfirmedCount
obj.statis.inj[0] += v.confirmedCount
obj.statis.sus[0] += v.suspectedCount
obj.statis.cur[0] += v.curedCount
obj.statis.dead[0] += v.deadCount
})
obj.statis.curInj[1] = obj.statis.curInj[0] - last.curInj
obj.statis.inj[1] = obj.statis.inj[0] - last.inj
obj.statis.sus[1] = obj.statis.sus[0] - last.sus
obj.statis.cur[1] = obj.statis.cur[0] - last.cur
obj.statis.dead[1] = obj.statis.dead[0] - last.dead
last.curInj=obj.statis.curInj[0]
last.inj=obj.statis.inj[0]
last.sus=obj.statis.sus[0]
last.cur=obj.statis.cur[0]
last.dead=obj.statis.dead[0]
console.log(obj.statis)
var ncov = new Ncov({
name: calenItem,
data: JSON.stringify(obj)
});
ncov.save((err, data) => {
if (!err) console.log("ok");
});
await sleep(2000)
}
}
run()
```
6.心路歷程與收獲
061700150
單單從結果上來看,這次作業的完成應該是不怎么理想的... ...首先是自己比較缺乏協作經驗,不靠譜的數據源耽誤了大量時間。其次是分工不夠明確,有些任務兩人同時做,效率算是1+1 << 1,這也導致后續的新增功能,難以通過分工合作的方式進行下去。最后我依舊是要通過《構建之法》中的內容進行反思,自己對於多人依賴合作、完成任務的要求並不熟稔於心 —— 眾多原因與自身的理解不到位,導致,項目一步步滑入深淵。
071703434
這次作業可以完成幾乎都是隊友的功勞,我其實不是很明白這個作業整個的流程,因為在作業開始之前隊友就已經把一部分完成了,無論是功能還是數據
之后呢,我做的事情幾乎就像是在添亂一樣,本以為我們的基礎功能算是完成,於是我就開始給擴展功能頁面開始排版,排版的結果就是,反而加大隊友的工作量;之后,前端的某些小小功能效果沒有實現,我又花了一晚上和一早上快速入門VUE,僅僅完成了兩部分按鈕的效果;在接下來,隊友看到其他隊的成品,才意識到我們漏了一個功能需求,就放棄擴展功能,於是我開始重新撿起Python處理清洗數據,但是因為API不熟悉,還有要求沒有看清又花了一個晚上一個早上處理出一堆沒有用處的數據;由於程序功能幾乎都不是我實現的,所以博客內容我也無從下手.....
反正,就是蠻挫敗的,花了很多時間,做了很多無用功,沒有做出啥實質性的貢獻,收獲就是,更清醒的認識到自己的不足,明白自己在合作中能夠發揮的作用其實不大,自身的編程能力很不OK的,還有很大的進步空間。
還有就是關於《構建之法》里關於團隊合作說到,團隊成員要有各自的分工,互相依賴合作,共同完成任務,反思這次就是沒有很好地進行規划合作,希望多多吸取經驗,畢竟合作能力在軟件工程中是很重要的一部分
7.評價結對隊友
061700150
隊友很樂於學習新技術並願意為之付出,而且撰文思路清晰流暢,即便是遇到一些障礙和困難,也會想方設法加以解決
071703434
隊友還是很靠譜的,認真負責,技術很強,經過這次結對合作之后,在他的指導下也學到了不少東西
![]()