天天看點

結對作業二

這個作業屬于哪個課程 2021春軟工實踐W班 (福州大學)
這個作業的要求在哪裡 結對作業二
結對學号 221801221、131802125
這個作業的目标 采用web技術實作原型功能
其他參考文獻 CSDN、知乎、部落格園

PSP表格

PSP Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 20 25
• Estimate • 估計這個任務需要多少時間
Development 開發 960 1290
• Analysis • 需求分析 (包括學習新技術) 30
• Design Spec • 生成設計文檔
• Design Review • 設計複審 10
• Coding Standard • 代碼規範 (為目前的開發制定合适的規範)
• Design • 具體設計
• Coding • 具體編碼 720 930
• Code Review • 代碼複審
• Test • 測試(自我測試,修改代碼,送出修改) 90 120
Reporting 報告 70 85
• Test Repor • 測試報告 45 55
• Size Measurement • 計算工作量
• Postmortem & Process Improvement Plan • 事後總結, 并提出過程改進計劃 15
合計 1030 1400

Github倉庫位址及代碼規範

  • Github倉庫位址
  • 代碼規範

雲伺服器通路連結

成品展示

  • 登入頁面
如果使用者名或者密碼錯誤則提示
登入成功則跳轉至搜尋界面
  • 搜尋界面
  • 搜尋結果界面
點選論文标題,跳轉到論文位址
  • 統計結果界面
滑鼠懸浮在詞雲圖上,顯示對應關鍵詞相關的論文數量
滑鼠懸浮在折線圖上,顯示時間軸對應月份的論文數量
  • 總體效果:

成品設計說明

  • 使用者登入系統後進入搜尋界面,輸入關鍵詞後跳轉到結果界面(此處預設支援模糊搜尋);
  • 側邊欄有搜尋相關論文、統計結果(内含折線圖和詞雲)等功能供使用者選擇
  • 在相關論文欄中可以看到與關鍵詞相關的所有論文,同時在文章清單中增加了删除操作,使用者點選删除後,重新傳回文章清單。

結對讨論過程描述

  • 我們剛拿到題目的時候,首先先對項目進行了需求分析和各自分工,初步定下了由梓洛完成前端設計、海旭完成後端實作的任務分工,在實踐過程中再做靈活調整。
  • 在海旭将json檔案全部解析之後,海旭就開始具體的後端實作,而梓洛在學習vue架構的運用的同時也嘗試着對着原型進行前端頁面設計。我們在各自前後端實作的過程中偶爾也會客串對方的代碼實作。
  • 在代碼實作的時候,我們如果遇到問題,就會跟對方讨論,我們在課餘時間會在實驗室或者宿舍讨論功能的具體實作。
  • 而在遇到一些小細節的時候,我們通常借助QQ線上上讨論,偶爾還會使用qq電話和向日葵遠端協助軟體。
  • 最後我們各自進行了一次測試,測試了所有功能,確定沒有bug後,完成了這次的結對程式設計任務~

設計實作過程

  • 後端
    • 程式設計語言:python
    • web架構:flask
    • orm架構:sqlalchemy
  • 前端
    • 使用架構:vue
    • UI庫:ant design vue
    • 圖庫:antv
    • http請求工具:axios
  • 實作過程:後端分model、router、util包,分别提供資料庫映射模型、路由、工具的服務,前端分components、plugins、requests、routers包,分别實作頁面、插件、http請求、路由的功能
  • 功能結構圖

關鍵代碼說明

資料庫設計

  • 查詢接口:使用分頁查詢,一次查詢十頁的方式,避免一次加載過多資料浏覽器卡死
@paper.route('/search', methods=['GET'])
def search():
    data = request.args
    token = data.get("token")
    pay, msg = validate_token(token)
    if msg is not None:
        res = ResponseData(2, "無效token", None)
        return json.dumps(res.__dict__)
    page = data.get("page")
    key = data.get("key")
    papers = Paper.query.filter(Paper.title.like("%" + key + "%")).order_by(
        Paper.paper_id).limit(10).offset((int(page) - 1) * 10).all()
    list = []
    for paper in papers:
        item = paper.__dict__
        del item["_sa_instance_state"]
        list.append(item)
    res = ResponseData(200, "success", list)
    return json.dumps(res.__dict__)
           
  • top10 接口通過 count 值排序傳回出現頻率最高的十個詞及出現次數
@keyword_count.route('/top10', methods=['GET'])
def top10():
    data = request.args
    token = data.get("token")
    pay, msg = validate_token(token)
    if msg is not None:
        res = ResponseData(2, "無效token", None)
        return json.dumps(res.__dict__)
    top10 = Keyword_count.query.order_by(Keyword_count.count.desc()).limit(10)
    list = []
    for item in top10:
        item = item.__dict__
        del item["_sa_instance_state"]
        list.append(item)
    res = ResponseData(200, "success", list)
    return json.dumps(res.__dict__)
           
  • 分頁查詢通過在localstorage存儲要查找的頁面及已查找的頁數實作,不過後來發現其實有現成的工具(((
fetchData(callback) {
      console.log(key);
      reqwest({
        url: dataUrl,
        type: 'json',
        method: 'get',
        contentType: 'application/json',
        success: res => {
          pageNum++;
          dataUrl = 'http://47.98.152.179:5000/xjbs/api/v1/paper/search?page=' + pageNum +'&key=' + key + '&token=' + token;
          callback(res.data);
        },
      });
    },
           
  • 圖表通過antv的繪圖工具,傳對應的參數繪制而成
fetchData() {
            fetch('http://47.98.152.179:5000/xjbs/api/v1/keyword/top10?token=' + localStorage.getItem("token"))
            .then((res) => res.json())
            .then((data) => {
                data = data.data
                const wordCloud = new WordCloud('container', {
                    data,
                    wordField: 'keyword',
                    weightField: 'count',
                    colorField: 'keyword',
                    wordStyle: {
                        fontFamily: 'Verdana',
                        fontSize: [12, 48],
                        rotation: 0,
                    },
                // 傳回值設定成一個 [0, 1) 區間内的值,
                // 可以讓每次渲染的位置相同(前提是每次的寬高一緻)。
                random: () => 0.5,
                });
                wordCloud.render();
                const plot = new Plot();
                plot.on('label:click',(...args) => {
                    window.location.href="www.baidu.com"
                });
            });
        },
           

心路曆程和收獲

  • 梓洛:在此次的結對程式設計中,對我這種開發小白來說實在是收獲頗豐。首先是在過程中入門了vue架構的運用,為今後的深入學習打下了基礎,同時又掌握一項新技能也讓我感到興奮;其次是在實際參與開發的過程中對code出一個完整的項目有了更深的了解,比如繪圖的時候通過調用一些現有的插件使得生産力和實作效果都比自己手打的不太成熟的繪圖代碼要美觀和高效;再有就是對結對程式設計有了更深的了解吧,在本次結對作業和上周六的團隊作業過程中我逐漸感受到結對程式設計的美妙和高效了,團隊成員之間知識共享能力互補的良性循環的确給整個項目開發過程帶來了相較一個人單打獨鬥更愉快的體驗!
  • 海旭:學了很多新知識,贊👍

隊友評價:

  • 梓洛:這是和海旭的第二次合作,海旭一個很有耐心很nice的隊友,開發經驗豐富的他在作業過程中教會我很多前後端互動的知識,同時能在完成自己任務之餘主動為我分擔一部分工作量,耐心的教我一些我認為的難點如何去實作,給我推薦了幾個靠譜的部落客和視訊。總之海旭給我的自學之旅帶來很多幫助!也給了我非常好的結對作業體驗!希望以後還有機會與他進行合作~
  • 海旭:和梓洛合作很愉快,交流很舒适,贊👍
下一篇: 結對作業一