結對作業二


結對作業二

結對作業二

目錄


1.作業信息

這個作業屬於哪個課程 2021春軟件工程實踐|W班 (福州大學)
這個作業要求在哪里 結對作業二
結對學號 221801307 & 221801327
這個作業的目標  1.fork倉庫,和伙伴商討如何通過github協作/代碼規范等
 2.使用Web知識實現原型設計的部分功能
 3.將項目部署到雲服務器上,並發布release版本
 4.根據作業要求撰寫第一個博客
 5.在deadline之前提交博客
其他參考文獻  CSDN、簡書博客、github

2.github倉庫地址和代碼規范

github倉庫地址

代碼規范


3.PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鍾) 實際耗時(分鍾)
Planning 計划 15 15
·Estimate 估計這個任務需要多少時間 15 15
Development 開發 1480 1922
·Analysis ·需求分析(包括學習新技術) 90 120
·Design Spec ·生成設計文檔 30 40
·Design Review ·設計復審 10 20
·Coding Standard ·代碼規范(為目前的開發指定合適的規范) 30 40
·Design ·具體設計 30 40
·Coding ·具體編碼 1200 1564
·Code Review ·代碼復審 30 24
·Test ·測試(自我測試,修改代碼,提交修改) 60 74
Reporting 報告 115 100
·Test Repor ·測試報告 40 30
·Size Measurement ·計算工作量 45 40
·Postmortem & Process Improvement Plan ·事后總結,並提出過程改進計划 30 30
合計 1610 2037

4.雲服務器鏈接

爬論文雲服務器鏈接


5.作品展示

登錄界面->請輸入正確的用戶名和密碼哦

  • 入口采用輪播圖播放,不要被迷住了!!!(user:cs1 pwd:123456)

論文頁面

  • 論文展示->使用表格的形式向用戶展示數據,簡潔明了

論文平台支持模糊查找

新增一篇論文信息

編輯一篇論文信息,並進行查看

刪除一篇論文信息

關鍵詞圖譜->移到關鍵詞條上可以看到部分數據,點擊也有跳轉喲

熱詞走勢

點擊關鍵詞,熱詞跳轉->你想跳的,這里都有

表格分頁->10條太多看不過來,那就換成5條吧

平台信息->我編的,你別信


6.結對過程討論

折線圖和柱狀圖的制作討論

學習使用springboot過程中的討論

 剛開始拿到題目的時候,我們還是很慶幸助教們降低了難度,暫時不需要我們通過學習爬蟲技術進行資料收集。但是,處理數據,將數據整理成我們可以使用的數據庫表也是一個鍛煉我們分析的過程
 隨后,我們大致分配了一下兩個人學習的方向,互相學習,查找資料,通過運行一些小項目和觀看視頻,逐漸幫助我們熟悉springboot框架,layui,mybatis,druid,maven這些新朋友
 以下是我們討論過程中的一些具體截圖,希望我們以后能和"新技術"hxd們相處的其樂融融

 第一次使用這樣的"新"框架,不得不說依賴的配置也是一門"藝術"活,在這個過程中我們查閱了很多框架上的資料,然后才將項目過程中的依賴一點點的導入進去,然后成功的運行了小小的項目。另外我們也學習了通過配置maven來幫助我們協調沖突

圖片 圖片

 一些數據在調用的過程中出現問題,不顯現。最終還是在"反復調試"后出來了成品

圖片

實現編輯文章的功能

 這是在一次測試過程中,發現有部分數據沒有顯示,盡管"艱難"的debug,經過和隊友的討論,我們發現問題出在我們增加了一個新的類型,卻忘記了對部分方法進行修改

圖片

ui界面設計的討論

 我們討論設計了一個輪播圖界面跳轉登錄界面,最后再進入論文平台的界面,雖然可能比較復雜。因為想學習用一下輪播圖框,然后把界面弄得好看一點

圖片

7.設計實現過程

數據庫表

 數據庫中有四張表,分別是authors, admin, academics, keyword。 我們將論文數據整理成四張表,主要依賴academics這張包含論文信息的表,在這張主表上面進行增刪改查功能的實現。

項目框架

 本次項目開發過程采用了springboot框架 + mybatis + druid + layui的技術,項目的框架結構如下

前端

  • 采用layui框架,使用layui組件進行布局,js動態生成數據,和連接頁面的跳轉
  • 登錄界面采用輪播圖播放一些圖片
  • 在用戶輸入用戶名,密碼,驗證碼時,會對輸入是否為空,驗證碼是否正確進行判斷
  • 主界面采用layui框架的側邊欄 + 分頁面形式
  • 論文的數據通過表格進行展示,實現增刪改查的按鈕與事件響應綁定,並彈出對應的對話框與用戶進行響應交互
  • 關鍵詞圖譜和熱詞趨勢采用echarts插件對數據庫中檢索到的數據進行展示,並在點擊時實現響應和部分數據顯示
  • 平台詳情顯示一些關於平台的具體信息,供用戶和平台進行聯系

后端

  • 采用springboot框架,數據庫使用mybatis進行連接和關閉
  • pojo : 封裝了Academics, Admin, Keywords, author, ResultBean類,前四個對應數據庫建立的四張表,最后一個類封裝前后端交互的數據
  • dao : 定義了AdminDao, KeywordDao, MyDao實現了數據庫各種類型增刪該查的Mapper數據接口
  • security : 定義了網站的權限訪問,禁止用戶在未登錄的情況下進入該系統
  • service : 實現了每種接口的具體類Service和ServiceImpI
  • config : 協同security管理權限
  • controller : 通過調用service層來負責具體業務,供前端進行調用,並將結果返回給前端

功能模塊


8.關鍵代碼描述

1.熱詞統計

 該代碼實現在熱詞趨勢過程中,統計ICCV論文中前10關鍵詞的功能,並將關鍵詞的數據以Map的形式進行返回

從數據庫中提取數據,獲取每篇文章出現的關鍵詞並進行統計
        List<Keywords> list = keywordsService.findAllKeywordsICCV();
        Map<String, List> map = new HashMap<>();
        Map<String, Integer> ma = new HashMap<>();
        int num = 10;//輸出前十的關鍵詞

        for (int i = 0; i < list.size(); i++) {
            Keywords keywords = list.get(i);
            if (ma.get(keywords.getKeyword()) != null) {
                int value = ma.get(keywords.getKeyword());
                value++;  //該關鍵詞如果出現過就+1存入ma
                ma.put(keywords.getKeyword(), value);
            } else {
                ma.put(keywords.getKeyword(), 1);
            }

        }
將HashMap中的包含映射關系的視圖entrySet轉換為List,然后重寫比較器
        List<Map.Entry<String, Integer>> list3 = new ArrayList<>(ma.entrySet());
        List<Integer> list4 = new ArrayList<>();
        List<String> list5 = new ArrayList<>();
        //idea自動轉化成lambda表達式
        list3.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        //輸出
        //同詞頻單詞表
        List<String> sameFrequency = new ArrayList<>();
        //輸出統計
        int outputCount = 0;
        if (list3.size() < num) {
            num = list3.size();
        }
        if (list3.size() == 1) {//如果只有一個關鍵詞,直接存入map,返回給前端
            list4.add(list3.get(0).getValue());
            list5.add(list3.get(0).getKey());
            map.put("x", list5);
            map.put("y", list4);
            return map;
        }
如果當前字符詞頻與下一個不一樣,則對當前所有同詞頻單詞排序
for (int i = 0; i < list.size() && outputCount < num; i++) {
            if ((i == list.size() - 1) || !list3.get(i).getValue().equals(list3.get(i + 1).getValue())) {
                //將當前單詞加入同詞頻單詞表
                sameFrequency.add(list3.get(i).getKey());
                //對同詞頻單詞表排序
                sameFrequency.sort(String::compareTo);
                //按字典順序記錄同詞頻單詞
                for (String s : sameFrequency) {
                    list4.add(list3.get(i).getValue());
                    list5.add(s);
                    outputCount++;
                }
                sameFrequency.clear();
            } else sameFrequency.add(list3.get(i).getKey());
        }

 下面貼出完整代碼

public Map<String, List> dataToPic32() {
        List<Keywords> list = keywordsService.findAllKeywordsICCV();
        Map<String, List> map = new HashMap<>();
        Map<String, Integer> ma = new HashMap<>();
        int num = 10;//輸出前十的關鍵詞

        for (int i = 0; i < list.size(); i++) {
            Keywords keywords = list.get(i);
            if (ma.get(keywords.getKeyword()) != null) {
                int value = ma.get(keywords.getKeyword());
                value++;  //該關鍵詞如果出現過就+1存入ma
                ma.put(keywords.getKeyword(), value);
            } else {
                ma.put(keywords.getKeyword(), 1);
            }

        }

        List<Map.Entry<String, Integer>> list3 = new ArrayList<>(ma.entrySet());
        List<Integer> list4 = new ArrayList<>();
        List<String> list5 = new ArrayList<>();
        //idea自動轉化成lambda表達式
        list3.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        //輸出
        //同詞頻單詞表
        List<String> sameFrequency = new ArrayList<>();
        //輸出統計
        int outputCount = 0;
        if (list3.size() < num) {
            num = list3.size();
        }
        if (list3.size() == 1) {//如果只有一個關鍵詞,直接存入map,返回給前端
            list4.add(list3.get(0).getValue());
            list5.add(list3.get(0).getKey());
            map.put("x", list5);
            map.put("y", list4);
            return map;
        }

        for (int i = 0; i < list.size() && outputCount < num; i++) {
            if ((i == list.size() - 1) || !list3.get(i).getValue().equals(list3.get(i + 1).getValue())) {
                //將當前單詞加入同詞頻單詞表
                sameFrequency.add(list3.get(i).getKey());
                //對同詞頻單詞表排序
                sameFrequency.sort(String::compareTo);
                //按字典順序記錄同詞頻單詞
                for (String s : sameFrequency) {
                    list4.add(list3.get(i).getValue());
                    list5.add(s);
                    outputCount++;
                }
                sameFrequency.clear();
            } else sameFrequency.add(list3.get(i).getKey());
        }
        map.put("x", list5);
        map.put("y", list4);
        return map;
    }

2.mybatis的sql語句

 使用mybatis定義執行的sql語句,並在dao內進行引用

分頁查詢,根據前端傳入每頁條數進行sql語句的訪問
<select id="getPage" resultType="Academics">
        select * from academics order by academicNum asc
            limit ${(start-1)*size}, ${size};
    </select>
按條件查詢並分頁,使用標識符綁定傳遞的參數,在通過sql語句進行查找,這段代碼也是實現模糊查詢功能的sql部分代碼
<select id="queryByParamPage" resultType="Academics">
        select * from academics
        <where>
            <if test="author!=null and author!=''">
                author like concat('%',#{author},'%')
            </if>
            <if test="academicNum!=0">
                and academicNum = #{academicNum}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
            <if test="keyword!=null and keyword!=''">
                and keyword like concat('%',#{keyword},'%')
            </if>
        </where>
        order by academicNum asc
        limit ${(page-1)*limit},${limit};
    </select>

 其余的查詢語句也一同展示在下面

<select id="findAllArticleList" resultType="Academics">
        select * from academics
    </select>

    <select id="findAllArticles" resultType="int">
        select count(*) from academics
    </select>

    <select id="getPage" resultType="Academics">
        select * from academics order by academicNum asc
            limit ${(start-1)*size}, ${size};
    </select>

    <insert id="addAcademic" parameterType="Academics">
        insert into academics(title, link, abstra, magazine, author, keyword, academicNum)
        values (#{title}, #{link}, #{abstra}, #{magazine}, #{author}, #{keyword}, #{academicNum})
    </insert>
    <!--更新文章-->
    <update id="updateAcademic" parameterType="Academics">
        update academics
        set title    = #{title},
            link     = #{link},
            abstra   = #{abstra},
            magazine = #{magazine},
            author   = #{author},
            keyword  = #{keyword}
        where title = #{title}
    </update>

    <select id="findOneAcademic" parameterType="Academics" resultType="Academics">
        select *
        from academics
        where title = #{title}
    </select>

    <delete id="delAcademic" parameterType="int">
        delete
        from academics
        where academicNum = #{academicNum}
    </delete>
    <!--批量刪除文章-->
    <delete id="delAcademics" parameterType="int">
        delete
        from academics
        where academicNum = #{academicNum}
    </delete>

    <!--按條件查詢並分頁-->
    <select id="queryByParamPage" resultType="Academics">
        select * from academics
        <where>
            <if test="author!=null and author!=''">
                author like concat('%',#{author},'%')
            </if>
            <if test="academicNum!=0">
                and academicNum = #{academicNum}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
            <if test="keyword!=null and keyword!=''">
                and keyword like concat('%',#{keyword},'%')
            </if>
        </where>
        order by academicNum asc
        limit ${(page-1)*limit},${limit};
    </select>

    <!--按條件查詢-->
    <select id="queryByParam" resultType="Academics">
        select * from academics
        <where>
            <if test="author!=null and author!=''">
                author like concat('%',#{author},'%')
            </if>
            <if test="academicNum!=0">
                and academicNum = #{academicNum}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
            <if test="keyword!=null and keyword!=''">
                and keyword like concat('%',#{keyword},'%')
            </if>
        </where>
    </select>

3.餅圖的動態設置

通過綁定后端的dataTobin方法,獲得前10關鍵詞的排行數據,並進行動態初始化

 設置backgroundColor, title, tooltip, serious屬性
 這些屬性的設置分別體現在餅圖的背景顏色,餅圖的標題,餅圖的每個部分的彈窗,以及動態的餅圖占比,餅圖類型為data_pie
 異步加載的過程中還有其他的屬性值得 大家學習

 // 異步加載數據
    $.get('/keywords/dataTobin', function (data) {
        myChart3.setOption({
            backgroundColor: '#e6ffff',
            title: {
                textStyle: {
                    color: 'rgba(0,0,0,0.8)'
                },
                text: '關鍵詞百分比餅圖1',
                left: 'center'
            },
            tooltip: {
                trigger: 'item',
                formatter: '{a} <br/>{b} : {c} ({d}%)'
            },

            series: [
                {
                    name: '數據',
                    type: 'pie',    // 設置圖表類型為餅圖
                    radius: '55%',  // 餅圖的半徑
                    data: data.data_pie,
                    emphasis: {
                        itemStyle: {
                            shadowBlur: 10,
                            shadowOffsetX: 0,
                            shadowColor: 'rgba(0,0,0,0.5)'
                        }
                    }

                }
            ]
        });
餅圖的點擊跳轉事件

 如果你想實現點擊餅圖的部分區域進行跳轉,不妨試試這個代碼

 myChart3.on('click', function (param) {
        window.open("demo1.html?keyname="+param.name+"")//該處為定義你想要打開的網頁的url
        //喜歡在本頁面跳轉的朋友可以試試, window.location.href = "admin.html?" + $("#username").val() + "";
    })

9.心路歷程與收獲

 221801327黃明亮:
 本次的結對作業二讓我受益匪淺。加強了自己在github上的使用,也在遇到bug的時候意識到了版本復原的重要性,(這次真是在上面栽了個大跟頭),以后一定按時commit;這次結對作業自己主要是負責前端的部分,學習了使用layui的組件搭建了這樣一個平台,不得不說,有一個組件庫,確實方便自己的開發,不需要自己寫太多的樣式表,但我覺得如果自己寫也能達到那樣的組件樣式,那也是很強的。合作過程中自己也曾參加過后端代碼的開發,不過bug頻出,好在隊友力挽狂瀾,在隊友的幫助下,成功的完成了前后端的交互。通過這一次的結對過程,我認為自己在技術上還要繼續學習,編碼過程中要更加細心,希望下一次的實踐還可以有更多的收獲!!!


 221801307蔡瑞金
 結對作業二的開發過程可謂是一波三折。前期對github的使用,中期學習框架,編寫程序,后期搭載服務器,雖然流程在一步一步走着,但在過程中遇到了許多問題。例如github pull request錯誤,需要回退;編寫程序出現bug又不知道改了哪里,導致要回退過於多的版本進行重新編寫,體驗到了備份的重要性,同時要及時測試程序的穩定性和可靠性。后期搭載服務器算是比較順風順水的一次,但是在linux上安裝mysql的時候把密碼更新錯誤也重新設置了許久。當然,負責后端也不能只會后端,前端也需要看懂,這在編寫文檔時具有重大作用。


10.隊友評價

 To 221801307蔡瑞金
 瑞金hxd在這次的結對過程中可謂是技術擔當,學習能力一流,很快就能夠學習並應用新學習的技術,這個學習能力真是讓我非常佩服。在遇到bug的時候,他也不會慌亂,會更願意投入時間去攻克難題,大膽嘗試網上的方法,雖然過程非常煎熬,但可以看出他非常的努力。總之,想對這位hxd說,你是真滴強!


 To 221801327黃明亮
 明亮在這次結對過程中,能夠努力學習新的技能,交代的任務也能努力完成。就是在實現新功能的時候還一直想着其他功能,導致原本能按部就班地完成卻要拖到后面才能完成,這個在開發過程中需要改一下。其他時候,他都不失為一個好隊友。


免責聲明!

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



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