結對第二次作業


這個作業屬於哪個課程 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
其他參考文獻




零、項目已部署服務器

點擊查看:http://www.zhengzhengzheng.club/front/index.html




一、Github 倉庫地址和代碼規范鏈接

二、展示成品

  • 即時爬取數據。可以選擇當天至前二十天的日期。顯示國家疫情數據。
    8mUGxe.gif

  • 選擇日期,可以看到每個省份的確診人數
    8mU82D.gif

  • 選擇日期,可以看到每個省份的累計確診人數
    8mUwIP.gif

  • 國家級別的趨勢圖
    8mUdat.gif

  • 點擊省份可以進入到省份的詳細信息
    8mdd9f.gif

  • 顯示特定省份具體日期的疫情信息,同上
    8mwA8f.gif

  • 省份級別的趨勢圖
    8mU6MQ.gif

三、結對討論過程

1.討論實現技術

我們一開始寫作業的時候,首先討論了要用什么技術去實現這一次作業的功能。

image

2.決定作業牽頭人
在決定所采用的的技術后,我們交流了各自的技能點,最后決定這次作業誰來牽頭。

image

3.討論前后端接口
對於作業的前后端交互接口,我們討論后決定建立一個在線文檔來交流。

image

4.設計細節交流
前端有個 bug

image

后端有個 bug

image

服務器經費問題大討論

image

四、設計實現過程

前端

1.寫 html 和 css
前端開始寫作業時,首先實現了前台的靜態頁面

2.添加 echarts
通過閱讀文檔,將疫情地圖和疫情趨勢圖添加進頁面中

3.前后端交互
前后端交互通過接口,我們通過在線文檔討論了交互的細節

4.以地圖為例說明過程

我們前台顯示的地圖是用 echarts 來實現的。我們的實現過程如下:

① 在 echarts 官網實例中,學習如何使用熱力地圖

② 在網上找中國熱力地圖的樣例並學習

③ 將地圖用到的 js 包導入到項目中

④ 發起 POST 請求,從后台獲取數據,將數據添加到代碼中

5.功能結構圖

image

后端

1.確定項目基本結構
使用 springboot 作為基本框架,maven 做為包管理器,fastjson 用來封裝 json 數據以及篩選 json 數據。

2.爬取數據
從網絡上找到可爬取的接口進行爬取數據

3.前后端交互
前后端交互通過接口,我們通過在線文檔討論了交互的細節

4.功能結構圖
8ne98P.png

五、代碼說明

后端代碼描述(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 封裝數據后進行傳送。


前端代碼描述(221701414)

前端用到的框架都是現學的,寫起來挺吃力。

下面以設置全國數字疫情為例,進行代碼說明。

1、將數字疫情界面划分為一塊,方便界面管理

2、因為這個界面涉及到很多重復的界面,所以用表格來進行展示

3、在原型階段,我們對這個版塊的字體大小、字體顏色有要求。其中,標題的字體大小偏大、但是顏色一致,內容的字體大小偏小、但是顏色不一致。所以,我們設計 class 屬性來設置字體的大小,id 屬性來單獨設置字體的顏色。

4、在 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;
}

六、《構建之法閱讀心得》、心路歷程和收獲及對隊友的評價

閱讀心得

1、對於構建之法第四章里面所要求的兩人合作的要求,很遺憾我們並沒有真正意義上的做到。雖然這一次作業是兩人合作,但是礙於現實,我們是通過前后端分離實現功能的,兩人的代碼聯系只有幾個調用接口,代碼並沒有互通。也因為時間實在有限,代碼復審、結對編程這種合作方法沒有深刻的體驗,這是一種遺憾。

2、在第五章提到的團隊合作和流程這個對於我們接下來的團隊項目將很有幫助。作為一個團隊,要有一致的目標、明確的分工。首先這一點是最為關鍵的,在團隊中要時刻注意和保持。

心路歷程及收獲

221701414

這次作業有一點體會非常深,就是不同語言的代碼思維是共通的。雖然學習過 web 開發,但是一直都沒有用 web 技術開發過項目,並且沒用過 bootstrap、ajax、jQuery 等框架。在使用這些技術的過程中,卻又一種行雲流水的感覺。比方說,js 發起 GET 請求,雖然寫法不同,但是請求的類型設置、url 設置、同步異步設置、訪問成功回調,這些東西又額外的熟悉。我的體會就是,需要花時間去精通一門編程語言,而不是去了解更多的語言。

另外一個體會是,原來我沒有學會 git 操作!沒想到團隊合作的代碼會這么難搞,並且可能是網絡的問題,GitHub 操作非常的慢。有時間,git 的知識需要馬上補上。


221701431

這次的后端代碼可以說難度並不是很大。主要難度在於數據的獲取能力。剛剛開始我去到丁香醫生和百度那邊找尋數據,發現只能爬取到當天的數據,讓我很苦惱(爬取到的東西可以見寒假作業 2里面拓展的 present 功能)。后面在 git 上發現了有人用 Python 爬取的歷史數據,但因為數據不全也放棄。最后發現了一個天行的數據接口。利用爬蟲可以爬取近三十天的數據。后面的開發也就一帆風順。這次的開發讓我感受到了數據的重要性,也讓我增強了篩選信息的能力。


對隊友的評價

221701414

我的隊友是一個合格的后端選手,能快速的在網上爬取所需要的數據,並封裝好交給前端。希望在團隊項目中能進行更深入的合作。

image

221701431
我的隊友是一個學習能力很強,細心優秀的人。值得信賴。能夠找到我后端接口的錯誤並准確反饋。希望還能再次合作。
8Zohwt.jpg


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM