zoukankan      html  css  js  c++  java
  • 结对作业二——顶会热词统计的实现

    这个作业属于哪个课程 2021软件工程实践|W班 (福州大学)
    这个作业要求在哪里 结对第二次作业——顶会热词统计的实现
    结对学号 221801129、221801322
    这个作业的目标 实践Github协作开发、实现顶会热词统计
    其他参考文献 Gin框架学习GormGinVue

    Github仓库链接和代码规范链接

    PaperCrawler

    PairProject

    Go后端代码规范

    前端代码规范

    PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟 实际耗时(分钟)
    Planning 计划
    · Estimate · 估计这个任务需要多少时间 15 15
    Development 开发
    · Analysis · 需求分析(包括学习新技术) 480 600
    · Design Spec · 生成设计文档 30 60
    · Design Review · 设计复审 30 60
    · Coding Standard · 代码规范(为目前的开发指定合适的规范) 30 30
    · Design · 具体设计 60 60
    · Coding · 具体编码 1800 2100
    · Code Review · 代码复审 60 120
    · Test · 测试(自我测试,修改代码,提交修改) 480 600
    Reporting 报告
    · Test Report · 测试报告 30 60
    · Size Measurement · 计算工作量 10 10
    · Postmortem & Process Improvement Plan · 时候总结,并提出过程改进计划 30 60
    Total 合计 3055 3775

    成品展示

    1、进行登录并回到首页

    2、首页搜索后跳到结果页展示论文列表

    3、对论文列表进行分页展示

    4、点击top10关键字展示相关搜索列表

    5、三大顶会热词趋势展示

    6、按关键词搜索显示论文列表

    7、论文列表收藏

    8、论文列表删除

    9、在结果页按论文题目搜索显示论文列表

    10、按论文编号搜索显示论文列表

    结对讨论过程描述

    收到需求后,两人还是有点懵的,因为确实感觉会来不及完成。然后,因为在第一次作业的时候就有讨论一些了,所以一开始两人的实现思想就很接近了,后面进行打代码过程的时候交流就比较顺利了

    1.对于接口数据交互的讨论

    2.对于关键词TOP10接口的讨论

    3.结对使用局域网,进行代码测试

    设计实现过程

    前端实现过程

    前端使用html+css+js语言以及jquery+vue框架进行开发

    • 页面设计

      整体页面的样式和布局做到尽量还原原型设计。首页、搜索结果页、收藏夹页共用一个nav,论文列表、热词top10通过vue框架的v-for指令进行循环显示。刚进首页时隐藏显示登录框,登录成功或点击除登录框外其他地方时登录框淡出。三大顶会的趋势图通过标签页形式在一个空间内切换显示。

    • 前后端交互

      前后端交互主要用ajax技术实现,统一进行post请求,请求参数和返回参数均为json格式,在请求时加上请求头"Content-Type": "application/json"。在传入请求参数时通过JSON.stringify()将参数转成json格式,对不能在回调函数内处理的数据通过localStorage存储起来,然后其他地方取出数据并处理。在回调函数中将响应参数进行相应处理并转成json格式,便与后续其他地方对数据的处理和展示。

    后端实现过程

    后端使用go语言进行开发

    • 数据库设计

      根据用户的需求,建立了一个articlekeyword表。考虑到一篇文章有多个关键词,一个关键词又可以对应多篇文章,一开始想要设计一个多对多的关联表, 但是,一开始因为对gormAPI的不熟悉,存数据的过程中出现了很多问题无法解决。所以存论文数据的时候,将数据库的表修改成了一对多的模式,方便了存数据,不可避免造成了数据的冗余。(项目后期发现解决方法,受于代码结构,没能更改)

      因为设计了收藏夹功能,创建了userbookmark表,bookmark实现userarticle表的多对多关联

      • article表

      • keyword表

      • user表

      • bookmark表

    • 后端代码

      使用MVC模式进行开发,model层使用go的第三方库gorm进行数据库交互,controller层采用轻量级的gin框架,负责调用model层与前端进行数据交互

    代码说明

    前端代码

    1、论文列表展示

                <div class="list">
                    <div class="listContent" v-for="list in lists">
                        <div class="title lineBreak" :data-paper-uid="list.article_id">
                            <h2 :title="list.title">{{ list.title }}</h2>
                        </div>
                        <div class="abstract">
                            <span>摘要:</span>
                            <div>
                                <p class="wrapBreak" :title="list.abstract">
                                    {{ list.abstract }}
                                </p>
                            </div>
                        </div>
                        <div class="listBottom">
                            <span>关键词:</span>
                            <div class="keyword lineBreak" v-for="key in list.keyword" :title="key">{{ key }}</div>
                        </div>
                        <img src="../img/Result/delete.svg" class="deleteSvg" :id="delete(index)" alt="delete" title="删除">
                        <img src="../img/Result/mark.svg" class="markSvg" alt="mark" title="收藏">
                    </div>
                    <button id="btn" @click="getLists()" style="border- 0;"></button>
                </div>
    

    2、热词top10展示

                    <ul id="rank">
                        <li v-for="topRank in topRanks">
                            <div class="num-box">
                                <span :id="num(topRank.index)">{{ topRank.index }}</span> 
                            </div>
                            <div class="name-box lineBreak" :title="topRank.name">
                                <span :class="name(topRank.index)" @click="rankClick(topRank.name)">{{ topRank.name }}</span>
                            </div>
                            <div class="total-box lineBreak" :title="topRank.count">
                                <span>{{ topRank.count }}</span>
                            </div>
                        </li>
                    </ul>
    

    3、展示论文列表的js代码

    function showList(urlStr,searchVal){
        PostHandle(urlStr, JSON.stringify(searchVal), function(data){
            if(data.code == 200){
                //console.log(data.data.articlelist[0].article_id);
                var articlelist = data.data.articlelist;
                var len = articlelist.length;
                var lists = [];
                for(var i = 0 ; i < len ; i++){
                    var keywords = [];
                    var keylen = articlelist[i].Keywords.length;
                    if(keylen <= 3){
                        for(var j = 0 ; j < keylen ; j++){
                            keywords[j] = articlelist[j].Keywords[j].name;
                        }
                    } else {
                        for(var k = 0 ; k < 3 ; k++){
                            keywords[k] = articlelist[k].Keywords[k].name;
                        }
                    }
                    lists[i] = {
                        title: articlelist[i].title,
                        abstract: articlelist[i].abstract,
                        article_id: articlelist[i].article_id,
                        keyword: keywords
                    };
                };
                localStorage.setItem("lists",JSON.stringify(lists));
                localStorage.setItem("totalPage",data.data.pagetotal);
                $("#btn").trigger("click");
            } else {
                alert(data.code + " " + data.msg);
            }
        });
    }
    
    function getList(){
        return JSON.parse(localStorage.getItem("lists"));
    }
    
    var app1 = new Vue({
        el: '.list',
        data: {
            lists: getList()
        },
        methods:{
            getLists : function(){
                this.lists = getList();
            }
        }
    });
    

    4、分页点击展示论文列表

        methods: {
            btnClick: function(data){
                if(data != this.cur){
                    this.cur = data;
                }
                console.log(this.cur+'页');
                //var urlStr = "https://mock.mengxuegu.com/mock/60634842f2e38f3a2f6ba3ec/example_copy/list";
                var urlStr = "http://192.168.0.110:8000/list";
                var searchVal = {
                    pagenum: this.cur,
                    type: 1,
                    searchval: localStorage.getItem("searchVal")
                };
                showList(urlStr,searchVal);
    
            },
            pageClick: function(){
                console.log('现在在'+this.cur+'页');
                //var urlStr = "https://mock.mengxuegu.com/mock/60634842f2e38f3a2f6ba3ec/example_copy/list";
                var urlStr = "http://192.168.0.110:8000/list";
                var searchVal = {
                    pagenum: this.cur,
                    type: 1,
                    searchval: localStorage.getItem("searchVal")
                };
                showList(urlStr,searchVal);
            },
        },
    

    5、热词top10展示的js

        //var urlStr = "https://mock.mengxuegu.com/mock/60634842f2e38f3a2f6ba3ec/example_copy/rank";
        var urlStr = "http://192.168.0.110:8000/rank";
        var rankVal = {
            type:"rank"
        };
        PostHandle(urlStr, JSON.stringify(rankVal), function(data){
            if(data.code == 200){
                var topList = data.data.top_list;
                var topRanks = [];
                for(var i = 0 ; i < 10 ; i++){
                    topRanks[i] = {
                        name: topList[i].name,
                        count: topList[i].count,
                        index: i+1
                    };
                }
                var app = new Vue({
                    el: '#rank',
                    data: {
                        topRanks: topRanks,
                    },
                    methods: {
                        num: function(index){
                            return "num" + index;
                        },
                        name: function(index){
                            return "name" + index;
                        },
                        rankClick :function(data){
                            //var urlStr = "https://mock.mengxuegu.com/mock/60634842f2e38f3a2f6ba3ec/example_copy/list";
                            var urlStr = "http://192.168.0.110:8000/list";
                            var searchVal = {
                                pagenum: 1,
                                type: 2,
                                searchval: data
                            };
                            showList(urlStr,searchVal);
                        }
                    }
                });
            } else {
                alert(data.code + " " + data.message);
            }
        });
    

    后端代码

    1. 返回所有顶会的热词TOP10列表

      func GetTopKeywordList() (results []KeyNum) {
      	var tmp1, tmp2 interface{}
      	rows, _ := db.Raw("SELECT name, count(*) FROM papercrawler.crawler_keyword group by name order by count(*) desc").Limit(10).Rows()
      	defer rows.Close()
      	for rows.Next() {
      		rows.Scan(&tmp1, &tmp2)
      		count, _ := strconv.Atoi(string(tmp2.([]byte)))
      		name := string(tmp1.([]byte))
      		results = append(results, KeyNum{
      			Name:  name,
      			Count: count,
      		})
      	}
      	return
      }
      
    2. 返回数据用于渲染趋势图(两段代码结合使用)

      //相关结构体
      type Chart struct {
      	Forum     string     `json:"forum"`
      	Years     []string   `json:"years"`
      	KeyValues []KeyValue `json:"key_values"`
      }
      
      type KeyValue struct {
      	Name   string `json:"name"`
      	Counts []int  `json:"counts"`
      }
      
      type KeyYearCount struct {
      	Name  string `gorm:"column:name"`
      	Year  string `gorm:"column:year"`
      	Count int    `gorm:"column:count(*)"`
      }
      
      //获取某个顶会TOP关键词
      func GetTOPByForum(forum string, size int) (topkeys []TopKey) {
      	db.Raw("SELECT forum, name, count(*) FROM papercrawler.crawler_keyword where forum = '" +
      		forum + "' group by name order by count(*) desc").Limit(size).Find(&topkeys)
      	return
      }
      
      //获取图表所需数据
      func GetChart(forum string, topkeys []TopKey) (chart Chart) {
      
      	var keyyearcounts []KeyYearCount
      	for _, topkey := range topkeys {
      		db.Raw("SELECT name, year, count(*) FROM crawler_keyword WHERE forum = '" + topkey.Forum + "' " +
      			"and name = '" + topkey.Name + "'").Group("year").Find(&keyyearcounts)
      
      		var keyvalue KeyValue
      		keyvalue.Name = keyyearcounts[1].Name
      		if forum == "ECCV" {
      			for i := 0; i < 11; i++ {
      				keyvalue.Counts = append(keyvalue.Counts, 0)
      			}
      			for _, keyyearcount := range keyyearcounts {
      				index, _ := strconv.Atoi(keyyearcount.Year)          //获取对应的年份
      				keyvalue.Counts[(index-2000)/2] = keyyearcount.Count //给对应年份赋值
      			}
      		} else {
      			for i := 0; i < 21; i++ {
      				keyvalue.Counts = append(keyvalue.Counts, 0)
      			}
      			for _, keyyearcount := range keyyearcounts {
      				index, _ := strconv.Atoi(keyyearcount.Year)      //获取对应的年份
      				keyvalue.Counts[index-2000] = keyyearcount.Count //给对应年份赋值
      			}
      		}
      		chart.KeyValues = append(chart.KeyValues, keyvalue)
      	}
      
      	chart.Forum = forum
      	if forum == "ECCV" {
      		for i := 2000; i <= 2020; i = i + 2 {
      			chart.Years = append(chart.Years, strconv.Itoa(i))
      		}
      	} else {
      		for i := 2000; i < 2021; i++ {
      			chart.Years = append(chart.Years, strconv.Itoa(i))
      		}
      	}
      	return
      }
      

    心路历程和收获

    • 221801129
      • 之前虽然有过一次web开发经验,但是是使用JAVA原生的servlet作为后端的开发,重复的代码部分无法有效的复用,深刻地体会到原生的开发效率之低,所以这次便下定决心要使用框架进行一次前后端分离的开发
      • 在结对作业之前,先进行了组队,由于团队的后端开发采用go语言和gin框架,便趁此机会学习并应用,为后面的团队开发打下基础
      • 在学习和实践过程中,虽然老师延长了期限,但是因为先进行了框架和语言的学习,导致最后代码时间有点赶。所以感觉在有实践项目时,最好采用自己熟悉的框架和语言进行开发,然后在课余时间进行相关的学习,加强自己对框架的理解和运用
      • 两人结对,因为前后端分离,一开始两人都是在各做各的,缺少交流,有点串行的合作,导致效率不是很高,也进而导致了一些功能没有实现
      • 虽然又很多遗憾,但是还是学到了宝贵的后端知识
    • 221801322
      • 之前有过一些web项目经历,但由于自身web基础不够扎实,所以实现起来效果不是特别好,所以就趁这次结对巩固下web基础并学习一些新知识。
      • 结对的过程中经历了一次团队实践,所以发现了并纠正了自己前后对接中出现的问题。这也使得后面结对编程的前后端对接不会出现类似的bug,使结对进行得更加顺利。
      • 结对项目中使用了一些vue框架,虽然方便了代码编写,但也由于自身对vue的了解不深,使得相关的bug更容易出现并且更难修好。
      • 结对过程中比较少给对方催进度,虽然这样每个人编写代码的自由度大,但也容易使得每个人的进度变慢,影响到了最后的实现。

    评价结对队友

    • 221801129 to 221801322

      这次的结对整体而言还是挺ok的,队友在前端方面有能力照着原型图构造页面,在讨论接口的时候能给出一些合理的建议,交流沟通虽然有些分歧,但是最后总能达成共识。同时,队友能够在时间紧迫的情况下,还能比较冷静地debug。这次结对,虽有遗憾,两人都有一定责任,但是我对于整体还是持积极的态度(生活不易)。希望我俩在这次结对后,都有反思,都能有进步

    • 221801322 to 221801129

      这次结对总体还是比较满意的,沟通过程也较为顺利。队友的后端能力很可靠,所以自己能够更专注于前端工作。在构造接口时,队友能够结合前端的需求改进相应的api,为前端的页面编写提供了思路。队友进行后端开发很不容易,而且还得学新框架,所以也没有去特意催进度。希望在这次结对后,都能有所收获,并将结对经验应用到今后的学习生活中。

  • 相关阅读:
    IE 8无法使用R12的解决办法
    ERP系统里的BOM展开函数
    BOM递归查询小实例
    使用标准Package提交Workflow
    查询WIP离散工单的所有组件
    Oracle EBS 各模块中文名称及英文缩写
    ORACLE EBS CUX用户的创建(转)
    HR人员基本信息、分配信息和地址信息SQL
    在Oracle中计算Onhand Quantity
    来自于Mozilla Networks演示工作室的超酷CSS3/Javascript动画演示
  • 原文地址:https://www.cnblogs.com/caihan/p/14993468.html
Copyright © 2011-2022 走看看