结对作业二

这个作业属于哪个课程 2021春软工实践W班 (福州大学)
这个作业的要求在哪里 结对作业二
结对学号 221801221、131802125
这个作业的目标 采用web技术实现原型功能
其他参考文献 CSDN、知乎、博客园

PSP表格

PSP Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 25
• Estimate • 估计这个任务需要多少时间 20 25
Development 开发 960 1290
• Analysis • 需求分析 (包括学习新技术) 30 30
• Design Spec • 生成设计文档 20 20
• Design Review • 设计复审 10 10
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 20 20
• Design • 具体设计 20 30
• Coding • 具体编码 720 930
• Code Review • 代码复审 30 30
• Test • 测试(自我测试,修改代码,提交修改) 90 120
Reporting 报告 70 85
• Test Repor • 测试报告 45 55
• Size Measurement • 计算工作量 10 10
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 15 20
合计 1030 1400

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的队友,开发经验丰富的他在作业过程中教会我很多前后端交互的知识,同时能在完成自己任务之余主动为我分担一部分工作量,耐心的教我一些我认为的难点如何去实现,给我推荐了几个靠谱的博主和视频。总之海旭给我的自学之旅带来很多帮助!也给了我非常好的结对作业体验!希望以后还有机会与他进行合作~
  • 海旭:和梓洛合作很愉快,交流很舒适,赞👍
posted @ 2021-03-31 22:43  淡水蓝鲸  阅读(48)  评论(0编辑  收藏  举报