這個做業屬於哪一個課程 | https://edu.cnblogs.com/campus/fzu/2020SpringW |
---|---|
這個做業要求在哪裏 | https://edu.cnblogs.com/campus/fzu/2020SpringW/homework/10456 |
結對學號 | 221701414,221701431 |
這個做業的目標 | 某次疫情統計可視化的實現 |
做業正文 | https://www.cnblogs.com/aahorse/p/12483117.html |
其餘參考文獻 |
[TOC]css
<br />html
<br />前端
零、項目已部署服務器
點擊查看:http://www.zhengzhengzheng.club/front/index.htmlgit
<br />github
<br />web
1、Github 倉庫地址和代碼規範連接
- Github 倉庫地址:https://github.com/jokercan/InfectStatisticWeb
- 代碼規範連接:https://github.com/jokercan/InfectStatisticWeb/blob/master/codestyle.md
2、展現成品
-
即時爬取數據。能夠選擇當天至前二十天的日期。顯示國家疫情數據。
ajax
-
選擇日期,能夠看到每一個省份的確診人數
spring
-
選擇日期,能夠看到每一個省份的累計確診人數
編程
-
國家級別的趨勢圖
json
-
點擊省份能夠進入到省份的詳細信息
-
顯示特定省份具體日期的疫情信息,同上
-
省份級別的趨勢圖
3、結對討論過程
1.討論實現技術
咱們一開始寫做業的時候,首先討論了要用什麼技術去實現這一次做業的功能。
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233652%E8%AE%A8%E8%AE%BA%E6%8A%80%E6%9C%AF.png" alt="image" /> </div>
<br />
2.決定做業牽頭人 在決定所採用的的技術後,咱們交流了各自的技能點,最後決定此次做業誰來牽頭。
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233633牽頭.png" alt="image" /> </div>
<br />
3.討論先後端接口 對於做業的先後端交互接口,咱們討論後決定創建一個在線文檔來交流。
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233627%E5%BB%BA%E7%AB%8B%E5%9C%A8%E7%BA%BF%E6%96%87%E6%A1%A3.png" alt="image" /> </div>
<br />
4.設計細節交流 前端有個 bug
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233647%E5%89%8D%E7%AB%AF%E6%9C%89%E4%B8%AAbug.png" alt="image" /> </div>
後端有個 bug
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233621%E5%90%8E%E7%AB%AF%E6%9C%89%E4%B8%AAbug.png" alt="image" /> </div>
服務器經費問題大討論
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233417%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BB%AD%E8%B4%B9.png" alt="image" /> </div>
4、設計實現過程
前端
1.寫 html 和 css 前端開始寫做業時,首先實現了前臺的靜態頁面
2.添加 echarts 經過閱讀文檔,將疫情地圖和疫情趨勢圖添加進頁面中
3.先後端交互 先後端交互經過接口,咱們經過在線文檔討論了交互的細節
4.以地圖爲例說明過程
咱們前臺顯示的地圖是用 echarts 來實現的。咱們的實現過程以下:
① 在 echarts 官網實例中,學習如何使用熱力地圖
② 在網上找中國熱力地圖的樣例並學習
③ 將地圖用到的 js 包導入到項目中
④ 發起 POST 請求,從後臺獲取數據,將數據添加到代碼中
5.功能結構圖
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233641%E5%89%8D%E7%AB%AF%E5%8A%9F%E8%83%BD%E7%BB%93%E6%9E%84%E5%9B%BE.png" alt="image" /> </div>
後端
1.肯定項目基本結構 使用 springboot 做爲基本框架,maven 作爲包管理器,fastjson 用來封裝 json 數據以及篩選 json 數據。
2.爬取數據 從網絡上找到可爬取的接口進行爬取數據
3.先後端交互 先後端交互經過接口,咱們經過在線文檔討論了交互的細節<br />
4.功能結構圖
5、代碼說明
###後端代碼描述(221701431)
後端此次的代碼十分簡單,無非是爬取到想要的數據進行分析篩選再傳到前端
public static String request(String httpUrl, String httpArg) { BufferedReader reader = null; String result = null; StringBuffer sbf = new StringBuffer(); httpUrl = httpUrl + "?" + httpArg; try { URL url = new URL(httpUrl); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setRequestMethod("GET"); InputStream is = connection.getInputStream(); reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); String strRead = null; while ((strRead = reader.readLine()) != null) { sbf.append(strRead); sbf.append("\r\n"); } reader.close(); result = sbf.toString(); } catch (Exception e) { e.printStackTrace(); } return result; }
上述代碼爲取得某一網頁接口的連接,而後返回接口所提供的全部值。
@Service public class InfectServiceImpl implements InfectService { @Value("${key}") private String key; public static HashMap<String , String> countryHashMap = new HashMap<>(); public static HashMap<String , String> provincesHashMap = new HashMap<>(); public void setDb(){ String now = new DateGet().getNow(); if (countryHashMap.size() == 0 || provincesHashMap.size() == 0 || !countryHashMap.containsKey(now) || !provincesHashMap.containsKey(now) ) { countryHashMap.clear(); provincesHashMap.clear(); for (int j = 0; j < 20; j++) { String httpUrl = "http://api.tianapi.com/txapi/ncovcity/index"; String jsonResult = new Info().request(httpUrl, "key=" + key + "&date=" + now); provincesHashMap.put(now, jsonResult); String httpUrlC = "http://api.tianapi.com/txapi/ncov/index"; String jsonResultC = new Info().request(httpUrlC, "key=" + key + "&date=" + now); countryHashMap.put(now, jsonResultC); now = new DateGet().getDay(now, -1); } } System.out.println("set small DB success"); } }
原本開始想和之前用 MySQL 進行數據存儲,但這個數據實時更新,並且不多會用到很早的數據,因此就將時間限制在二十天以內,這樣列表找關係就太辛苦了。用 Redis 又有些大材小用沒用必要。由於這個數據不算很大,就直接在後臺之中進行存儲供查詢,這樣節省了數據存儲的時間,也更符合實時更新的要求。
public String getProvinceConfirmed(String date){ String jsonResult = provincesHashMap.get(date); JSONObject jsonObject = JSON.parseObject(jsonResult); Object o = jsonObject.get("newslist"); JSONArray jsonArray = JSON.parseArray(o + ""); List<ProvinceCut> provinceCuts = new LinkedList<ProvinceCut>(); for (int i = 0; i < jsonArray.size(); i++) { Object n1 = jsonArray.get(i); JSONObject jsonObject1 = JSON.parseObject(n1 + ""); ProvinceCut provinceCut = new ProvinceCut(); provinceCut.setName(String.valueOf(jsonObject1.get("provinceShortName"))); provinceCut.setCurrentConfirmedCount(Integer.parseInt(String.valueOf(jsonObject1.get("confirmedCount")))); provinceCuts.add(provinceCut); } String js = JSON.toJSONString(provinceCuts); return js; }
以上是對存儲在 provinceHashMap 的數據使用 fastjson 進行相應的解析得到想要的數據。並經過 fastjson 封裝數據後進行傳送。
<br />
###前端代碼描述(221701414)
前端用到的框架都是現學的,寫起來挺吃力。
下面以設置全國數字疫情爲例,進行代碼說明。
一、將數字疫情界面劃分爲一塊,方便界面管理
二、由於這個界面涉及到不少重複的界面,因此用表格來進行展現
三、在原型階段,咱們對這個版塊的字體大小、字體顏色有要求。其中,標題的字體大小偏大、可是顏色一致,內容的字體大小偏小、可是顏色不一致。因此,咱們設計 class 屬性來設置字體的大小,id 屬性來單獨設置字體的顏色。
四、在 js 中,咱們首先經過 ajax 發起異步 GET 請求,從後臺獲取信息,而後將獲取到的信息綁定到對應的標籤元素中
<!-- 數字疫情板塊 --> <div class="bg" style="margin-top: 15px"> <table class="table"> <tr> <td><p class="type-title">現有確診</p></td> <td><p class="type-title">現有疑似</p></td> <td><p class="type-title">現有重症</p></td> </tr> <tr> <td><p class="count-content" id="definite-count-content">123</p></td> <td><p class="count-content" id="suspected-count-content">123</p></td> <td><p class="count-content" id="severe-count-content">123</p></td> </tr> <tr> <td> <span class="count-change">昨日</span> <span class="count-change" id="definite-count-change">123</span> </td> <td> <span class="count-change">昨日</span> <span class="count-change" id="suspected-count-change">123</span> </td> <td> <span class="count-change">昨日</span> <span class="count-change" id="severe-count-change">123</span> </td> </tr> <!-- 此處代碼有省略 --> </table> </div>
/* * 設置全國數字疫情 * */ function initNationalDigital(){ $.ajax({ type:'get', url:'http://localhost:8080/current', data:{ date:$('#datetimepicker1').find("input").val() }, dataType:'json', success:function(result){ document.getElementById("definite-count-content").innerHTML=result["currentConfirmedCount"]; document.getElementById("suspected-count-content").innerHTML=result["suspectedCount"]; document.getElementById("severe-count-content").innerHTML=result["seriousCount"]; document.getElementById("sum-definite-count-content").innerHTML=result["confirmedCount"]; document.getElementById("sum-cure-count-content").innerHTML=result["curedCount"]; document.getElementById("sum-dead-count-content").innerHTML=result["deadCount"]; document.getElementById("definite-count-change").innerHTML=result["currentConfirmedIncr"]>0?"+"+result["currentConfirmedIncr"]:result["currentConfirmedIncr"]; document.getElementById("suspected-count-change").innerHTML=result["suspectedIncr"]>0?"+"+result["suspectedIncr"]:result["suspectedIncr"]; document.getElementById("severe-count-change").innerHTML=result["seriousIncr"]>0?"+"+result["seriousIncr"]:result["seriousIncr"]; document.getElementById("sum-definite-count-change").innerHTML=result["confirmedIncr"]>0?"+"+result["confirmedIncr"]:result["confirmedIncr"]; document.getElementById("sum-cure-count-change").innerHTML=result["curedIncr"]>0?"+"+result["curedIncr"]:result["curedIncr"]; document.getElementById("sum-dead-count-change").innerHTML=result["deadIncr"]>0?"+"+result["deadIncr"]:result["deadIncr"]; } }); }
.count-content{ font-size: 16px; } .count-change{ font-size: 10px; } #definite-count-content{ font-size: large; color: rgb(253, 107, 92); } #definite-count-change{ color: rgb(253, 107, 92); } #suspected-count-content{ font-size: large; color: rgb(234, 146, 45); } #suspected-count-change{ color: rgb(234, 146, 45); } #severe-count-content{ font-size: large; color: rgb(73, 110, 158); } #severe-count-change{ color: rgb(73, 110, 158); } #sum-definite-count-content{ font-size: large; color: rgb(230, 52, 57); } #sum-definite-count-change{ color: rgb(230, 52, 57); } #sum-cure-count-content{ font-size: large; color: rgb(34, 174, 180); } #sum-cure-count-change{ color: rgb(34, 174, 180); } #sum-dead-count-content{ font-size: large; color: rgb(122, 124, 128); } #sum-dead-count-change{ color: rgb(122, 124, 128); } .table{ margin: 0; padding: 0; } .table tr td{ text-align: center; }
6、《構建之法閱讀心得》、心路歷程和收穫及對隊友的評價
###閱讀心得
一、對於構建之法第四章裏面所要求的兩人合做的要求,很遺憾咱們並無真正意義上的作到。雖然這一次做業是兩人合做,可是礙於現實,咱們是經過先後端分離實現功能的,兩人的代碼聯繫只有幾個調用接口,代碼並無互通。也由於時間實在有限,代碼複審、結對編程這種合做方法沒有深入的體驗,這是一種遺憾。
二、在第五章提到的團隊合做和流程這個對於咱們接下來的團隊項目將頗有幫助。做爲一個團隊,要有一致的目標、明確的分工。首先這一點是最爲關鍵的,在團隊中要時刻注意和保持。
###心路歷程及收穫
221701414
此次做業有一點體會很是深,就是不一樣語言的代碼思惟是共通的。雖然學習過 web 開發,可是一直都沒有用 web 技術開發過項目,而且沒用過 bootstrap、ajax、jQuery 等框架。在使用這些技術的過程當中,卻又一種行雲流水的感受。比方說,js 發起 GET 請求,雖然寫法不一樣,可是請求的類型設置、url 設置、同步異步設置、訪問成功回調,這些東西又額外的熟悉。個人體會就是,須要花時間去精通一門編程語言,而不是去了解更多的語言。
另一個體會是,原來我沒有學會 git 操做!沒想到團隊合做的代碼會這麼難搞,而且多是網絡的問題,GitHub 操做很是的慢。有時間,git 的知識須要立刻補上。
<br />
221701431
此次的後端代碼能夠說難度並非很大。主要難度在於數據的獲取能力。剛剛開始我去到丁香醫生和百度那邊找尋數據,發現只能爬取到當天的數據,讓我很苦惱(爬取到的東西能夠見寒假做業 2裏面拓展的 present 功能)。後面在 git 上發現了有人用 Python 爬取的歷史數據,但由於數據不全也放棄。最後發現了一個天行的數據接口。利用爬蟲能夠爬取近三十天的數據。後面的開發也就一路順風。此次的開發讓我感覺到了數據的重要性,也讓我加強了篩選信息的能力。
<br />
###對隊友的評價
221701414
個人隊友是一個合格的後端選手,能快速的在網上爬取所須要的數據,並封裝好交給前端。但願在團隊項目中能進行更深刻的合做。
<div> <img class="imgB" src="https://images.cnblogs.com/cnblogs_com/aahorse/1668623/o_200312233658%E5%98%BB%E5%98%BB.jpg" alt="image" />
</div>
<br />
221701431 個人隊友是一個學習能力很強,細心優秀的人。值得信賴。可以找到我後端接口的錯誤並準確反饋。但願還能再次合做。