结对作业二

这个作业属于哪个课程 2021春软件工程实践S班
这个作业要求在哪里 结对作业二
结对学号 221801218, 221801219
这个作业的目标 搭建一个平台爬取论文
其他参考文献 百度

1.git仓库链接,代码规范链接和部署链接

GitHub仓库 (ErrorPay/PairProject)
代码规范链接 (codestyle.md)

云服务器部署链接

2.PSP表格

221801218

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

221801219

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

3.成品展示

  • 登陆界面

  • 注册界面

  • 论文列表

  • 论文详情

  • 论文搜索

  • 论文数据统计

4.结对讨论过程描述

4.1 要求分析

最开始拿到JSON格式的数据时分析解析和存储需要的数据。用户需要在系统中能够登陆注册以使用论文列表功能,用户也能够查看历年顶会的热门关键词以及热门趋势,同时也需要论文的查询功能。其中查询功能又能够分为普通查询以及高级查询。

4.2 确定实现方法

4.2.1 前端

前端采用了react+antdesign,由于react的特性,html的内容主要写在js里,这样便于动态生成界面内容,并添加响应事件,利用state这个属性,再不用刷新界面的条件下,实时渲染界面,不仅效率提高了,用户也能够得到更好的视觉体验。
图表方面用了wordcloud与echarts,wordcloud支持以关键词图谱的形式展现数据,而echarts有丰富的图表,并且在数据表现方面有较强的支持。
在前后端交互方面,登陆注册实现的方法是前端接受由后端发来的set-cookie,里面记录了后端存储的seeion,这样可以实现用户的认证。
前段界面大多采用了ant design的组件,该组件不用设计的样式,只需要提供几个属性方法,就能实现各种各样的功能。
页面跳转用了route与history传参结合,使得代码简单且能传递各种各样的参数。

4.2.2 后端

后端采用Golang编写。使用高性能的Gin框架提供http服务,选择xorm作为本项目的ORM框架管理数据,登陆方面使用session进行验证,用Cors处理跨域问题。

4.2.3 结对讨论




5.设计实现过程

5.1 描述实现过程

5.1.1 前端

先设置路由,设定一个主组件,所有的页面都要经过该组件的渲染,在这个主组件里写页面的结构,结构分为页头,侧边栏,主体部分和页尾,主体部分发生变化时,url路径改变,并且渲染不同的组件。主页面包含logo图案和一个搜索框,该页面一共有三个搜索框,第一个是导航栏上的搜索框,第二个是侧边栏的高级搜索,第三个是主体部分的搜索框。搜索框的逻辑如下:点击搜索触发点击事件,路由发生改变,同时,附加上用户输入的搜索参数,包括标题,关键词,所属会议。最后由一个swith条件语句判断要跳转的路由渲染的对应组件,对应组件获取搜索参数,完成搜索功能。
前后端交互用了axios,在实现的时候遇到了一个问题,就是axios是异步执行的,在组件没有渲染的时候,axios异步发送请求,会导致渲染时请求还在处理的情况,解决方法就是设置state,先在组件渲染时设为false。等axios结束后再设为true,再次渲染界面,就可以正常显示。

5.1.2 后端

设定router来接受前端的特定请求,再使用api通过handler函数对前端的请求进行处理。api可以通过调用service服务来进行深入的操作,如将JSON字符串解析并绑定为service结构体,再由特定的service函数来处理。service处理完所有的任务由serializer来序列化为JSON返回给前端。通过model对数据库进行CRUD操作。

5.2 功能结构图

5.3 数据库设计

6.代码说明

6.1 前端部分

6.1.1 关键代码
  • 根据路由跳转界面

    const ChoosePage = ({ id }) => {
      switch (id) {
        case "SearchPaperDetail":
          return (<CreateSearchDetailPage />);
        case "MyPaperList":
          return (<CreateListPage />);
        case "SearchPaperList":
          return (<CreateSearchPageList />);
        case "StatisticPage":
          return (<StatisticPage />);
        default:
          return (<CreateSearchPage />);
      }
    }
    
    class Home extends React.Component {
      onSearchP = () => {
        let { history } = this.props
        console.log('!!!' + a + b + c)
        history.push({
          pathname: '/SearchPaperList',
          state: {
            paperNameSearch: a,
            paperMeetingSearch: b,
            paperWordsSearch: c
          }
        })
      }
    
  • 数据可视化跳转界面

         <h2>TOP10关键词</h2>
                  <ReactWordcloud style={{ width: 600, height: 400 }} words={words} />
                  <ReactECharts
                  style={{ width: 1200, height: 350 }}
                      option={this.getOption()}
                      notMerge={true}
                      lazyUpdate={true}
                      theme={"theme_name"}
                  />
    

6.2 后端部分

6.2.1 代码目录结构
.
├── api									//用于处理前端发送的请求
├── config							//服务器配置
├── deserializer				//反序列化JSON
├── go.mod							//Go Module包管理
├── go.sum
├── main.go							//主函数入口
├── middleware					//服务端中间件
├── model								//数据库模型
├── serializer					//序列化JSON
├── server							//服务器路由
├── service							//处理请求的服务
└── util								//一些工具
6.2.2关键代码
  • 用户登录功能。通过Session和cookie设置登陆状态。

    func (service *UserLoginService) Login(c *gin.Context) serializer.Response {
    	if has, _ := model.Engine.Where("uid = ?", service.Uid).Exist(&model.User{}); !has {
    		return serializer.ParamErr("账号或密码错误", nil)
    	}
    
    	user := new(model.User)
    	_, _ = model.Engine.Where("uid = ?", service.Uid).Get(user)
    	if user.CheckPassword(service.Password) == false {
    		return serializer.ParamErr("账号或密码错误", nil)
    	}
    
    	service.setSession(c, *user)
    
    	return serializer.BuildUserResponse(*user)
    }
    
  • model包使用结构体绑定数据库表。如:

    package model
    type User struct {
    	Id             int64
    	Uid            string `xorm:"varchar(200) unique notnull"`
    	PasswordDigest string `xorm:"varchar(200) notnull"`
    }
    
  • serializer序列化参数为JSON格式以便返回给前端。

    // 所有序列化器
    // Response 基础序列化器
    type Response struct {
    	Code  int         `json:"code"`
    	Data  interface{} `json:"data,omitempty"`
    	Msg   string      `json:"msg"`
    	Error string      `json:"error,omitempty"`
    }
    
  • api包作为前端请求的Handler函数,传递前端数据给Service。

    func UserRegister(c *gin.Context) {
    	var service service.UserRegisterService
    	if err := c.ShouldBind(&service); err == nil {
    		res := service.Register()
    		c.JSON(200, res)
    	} else {
    		c.JSON(200, ErrorResponse(err))
    	}
    }
    
  • util包存放一些工具函数,如Log格式化输出日志。

    func (ll *Logger) Error(format string, v ...interface{}) {
    	if LevelError > ll.level {
    		return
    	}
    	msg := fmt.Sprintf("[E] "+format, v...)
    	ll.Println(msg)
    }
    
    func (ll *Logger) Warning(format string, v ...interface{}) {
    	if LevelWarning > ll.level {
    		return
    	}
    	msg := fmt.Sprintf("[W] "+format, v...)
    	ll.Println(msg)
    }
    

7.心路历程和收获

221801218

一直以来我对于一个完整Web应用的设计经验是很少的,这一次一个人独立的完整开发一个Web后端给我带来了不小的收获。前期设计和数据库规划的时候,经验的缺乏给项目的推进带来了不小的麻烦,但也让我对设计一个合理系统以及数据库更加有经验。作为一个Golang的初学者,这一次的项目也给我带来的非常大的锻炼的机会。让我对Golang这门语言又了更深的理解。一个本不那么熟悉的东西在不断的实践中变得熟悉起来,这给了我很大的动力。

221801219

这次结对作业,我学会了使用成熟的框架做一个网页,之前一直是自己用纯html,css写,费时费力,而且很花时间,组件虽然可扩展性差,但是一般能够满足我们的需求还有学习了npm包管理,用node进行网络通讯,以及最最重要的前后端分离技术。我也发现前端前期会出现难以调试自己请求的情况,尤其是后端没有开启服务的情况,
所以前端前期进度缓慢。在路由跳转以及异步处理的问题上我花了大量时间,虽然最后都解决了,但是了解到自己掌握的不够透彻,今后会加强学习

8.评价结对队友

221801218

我的队友在结对作业的过程体现了非常大的积极性,做事也有着很高的效率。在设计和开发过程中也给我提了很多很有建设性的建议,给我很多的帮助。

221801219

郑麟轩同学工作效率很高,善于听取他人的意见,知识面也十分广,会站在对方的立场上看待问题,会理解我的观点和看法。所以我们交流起来非常顺利。

同时他的一些看似工作量庞大的任务他都能够在很短的时间内解决。在他的任务完成后,也会热心地帮我分担一些任务,我觉得他有责任心。

posted @ 2021-03-31 22:41  福贵的老牛  阅读(125)  评论(11编辑  收藏  举报