结对作业二
这个作业属于哪个课程 | 2021春软件工程实践|W班(福州大学) |
---|---|
这个作业要求在哪里 | 结对作业二 |
结对学号 | 221801204 、 221801239 |
这个作业的目标 | 记录PSP表格 论文查询网站的编码实现 |
其他参考文献 | vue.js elementUI、Echarts |
目录:
1.Github项目地址
2.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 2850 | 3345 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 1200 | 1080 |
• Design Spec | • 生成设计文档 | 60 | 90 |
• Design Review | • 设计复审 | 60 | 45 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
• Design | • 具体设计 | 60 | 45 |
• Coding | • 具体编码 | 1200 | 1400 |
• Code Review | • 代码复审 | 120 | 180 |
• Test | • 测试(自我测试,修改代码,提交修改) | 240 | 300 |
Reporting | 报告 | ||
• Test Repor | • 测试报告 | 60 | 50 |
• Size Measurement | • 计算工作量 | 60 | 50 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 2850 | 3330 |
3. 云服务器地址
由于能力有限以及时间有限,我们没有将项目部署到服务器上
4. 成品展示
1.用户没用登录,无法进入其他页面。用户如果没有账号,就点击立即注册。用户输入信息后点击注册按钮,如果用户名没有重复就注册成功,页面跳转至登录界面。
2.论文列表界面
5. 结对讨论过程
1.对问题的讨论
在刚刚拿到题目之后,我们就马上讨论用什么语言、什么框架来完成这次作业。我们虽然在之前有一些Web基础,但是开发这样的Web项目要学习不少新技术。所以我们先确定了前端用Vue框架来实现,后端用Spring Boot来实现。确定了前后端的框架之后,我们就分工开始学习技术。
2.遇到的困难
1.虽然上学期学习过Web的一些框架,之前也学过java,但是这次决定使用的Vue+Spring boot这两个框架我们都基本上都不会用,所以都要学习新知识。
2.前端网页分为不同部分,不同部件之间的传值比较困难,比如论文列表中的查看论文,需要父组件将数据传给子组件然后进行渲染。在写到这部分时进度卡住了。
3.后端困难:之前对于后端其实只有一个很浅的理解,停留在简单的编写java程序之上,很少使用框架,而后端框架素有配置地狱一说,在配置springboot和mybatis的那些文件的时候花了我很多时间,并且因为配置不过关引发了很多bug,改了半天。
4.前后端接口写好了之后,怎么交互也是个问题,在测试交互的过程中我们遇到了跨域问题、找不到网页等一系列问题。
3.解决方案
1.通过在b站搜索教程、百度上查找知识、求助有经验的同学学会了vue和spring boot的使用
2.通过阅读百度上一些论坛的专业回答,找到了问题的根源并且解决了父子组件、兄弟组件之间的传值问题
3.反复跟着网上的视频敲配置代码,bug改到后面看到提示就知道是哪里出问题了...
4.多进行交流沟通,一起查询资料来解决交互出现的问题。
4.讨论照片
6. 设计实现过程
1.首页
用户可以在首页进行登录和注册,用户只有登录了之后才可以查看论文,登录之后可以点击右上角退出登录按钮退出。登录和注册需要将表单传到后端验证,然后后端查询数据库,用户存在就且密码正确就可以登录。
2.论文列表
用户可以在论文列表中查看全部论文,还可以通过论文题目、关键词、论文发表时间等进行模糊搜索。在进入论文列表界面时,前端请求后端,将所有论文读取到前端,然后前端实现论文分页以及将查询的论文结果展示给用户。
论文列表中的摘要只显示部分,点击查看按钮可以查看论文详细信息,点击相应论文的删除可以将论文删除(并不影响数据库)。论文列表的分页在前端通过过滤器filter来实现
3.关键词图谱
用户可以在这个界面查看Top10的关键词词云。词云的字体大小体现出了不同关键词之间数量关系。用户点击词云,可以在页面下方查看与关键词有关的论文。前端利用Echart的词云组件来实现,后端处理完的数据返回给前端。
4.热度走势图
用户可以在这个界面查看三大峰会的论文数量趋势对比。通过柱状图的形式展现出来。实现方式为:前端利用Echart来绘制柱状图,后端处理数据后传给前端进行页面渲染。
7. 关键代码
前端登录界面表单以及请求后端的代码:
//登录按钮对应的函数
doLogin() {
this.$axios.get('http://localhost:8083/login', {
params: {
username: this.username,
password: this.password
}
}, {headers: {'Content-Type': 'application/x-www-form-urlencoded format'}})
.then(res => {
if (res.data === 1) {
this.state.status = 1;
this.state.index = 1;
bus.$emit('sendStatus', this.state);
this.$router.replace('/Search');
} else if (res.data === -1) {
alert("用户未注册,请注册后再登录")
}
})
.catch(failResponse => {
})
},
前端请求后端的代码:
//注册按钮对应的函数
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios
.get('http://localhost:8083/register', {
params: {
username: this.ruleForm.user,
password: this.ruleForm.pass
}
}, {headers: {'Content-Type': 'application/x-www-form-urlencoded format'}})
.then(res => {
if (res.data === 1) {
this.$message.success("注册成功")
this.$router.replace({path: '/Login'})
} else {
this.$message.error("注册失败,用户名已被注册!")
}
}).catch(failResponse => {
})
} else {
this.$message.error("信息填写有误!请重新填写")
return false;
}
});
},
登录界面的点击滑动的页面。
<template>
<div class="out">
<button class="btn blt" @click="cLeft"></button>
<button class="btn mid" @click="cMid"></button>
<button class="btn rit" @click="cRi"></button>
<img class="pic" v-bind:src="picArr[num]" alt=""/>
</div>
</template>
<script>
export default {
data() {
return {
num: 0,
picArr: [
require("../assets/images/first.png"),
require("../assets/images/second.png"),
require("../assets/images/third.png"),
],
};
},
methods: {
cLeft() {
this.num = 0;
},
cRi() {
this.num = 2;
},
cMid() {
this.num = 1;
},
},
};
加载数据库的论文数据到前端
query() {
this.$axios
.get('http://localhost:8083/getPapers', {})
.then(res => {
this.listArray = res.data
this.searchArray = this.listArray
this.showArray = this.listArray
this.divideList()
})
.catch(failResponse => {
})
},
根据搜索框旁边的下拉框来决定按什么方式搜索:
getList() {
if (this.content !== "") {
if (this.value === "论文名") {
this.searchArray = this.listArray.filter((item, index) =>
item.title.includes(this.content));
} else if (this.value === "关键词") {
this.searchArray = this.listArray.filter((item, index) =>
item.keyword.indexOf(this.content) > -1);
} else if (this.value === "发布时间") {
this.searchArray = this.listArray.filter((item, index) =>
item.publication_year === this.content);
} else {
this.searchArray = this.listArray
}
}
},
对论文数据进行分页展示
divideList() {
this.showArray = this.searchArray.filter(
(item, index) =>
index < (this.pageNum + 1) * this.pageSize &&
index >= this.pageSize * this.pageNum
);
},
nextPage() {
if ((this.pageNum + 1) * this.pageSize > this.searchArray.length) {
alert("已经到最后一页了!");
} else {
this.pageNum++;
this.divideList();
}
},
formerPage() {
if (this.pageNum > 0) {
this.pageNum--;
this.divideList();
} else {
alert("已经在第一页了!");
}
}
},
用词云来直观展示关键词的数量多少:
initChart() {
let chart
if (chart != null) {
chart.dispose()
}
chart = echarts.init(document.getElementById("myWordCloud"));
chart.setOption({
title: {
text: "Top10热词词云图",
x: "center"
},
series: [
{
type: "wordCloud",
gridSize: 10,
sizeRange: [14, 50],
rotationRange: [0, 0],
textStyle: {
normal: {
color: function () {
return (
"rgb(" +
Math.round(Math.random() * 255) +
", " +
Math.round(Math.random() * 255) +
", " +
Math.round(Math.random() * 255) +
")"
);
}
}
},
left: "center",
top: "center",
right: null,
bottom: null,
width: "200%",
height: "200%",
//数据
data: this.wordData
}
]
})
chart.on('click', (params) => {
this.query()
});
用柱状图来体现趋势(未完全实现)
drawLine() {
// 基于准备好的dom,初始化echarts实例
const myChart = echarts.init(document.getElementById('myChart'))
// 绘制图表
myChart.setOption({
title: {
text: '',
//textAlign: 'center',
//padding: 0
},
xAxis: {
data: this.data1,
inverse: true,
animationDuration: 600,
animationDurationUpdate: 600,
},
yAxis: {max: 'dataMax'},
series: [
{
name: '',
type: 'bar',
data: this.data2,
realtimeSort: true,
label: {
show: true,
position: 'top',
valueAnimation: true
}
}
],
legend: {
show: true,
data: ['ECCV']
},
color: ['#1685ff'],
animationDuration: 0,
animationDurationUpdate: 3000,
animationEasing: 'linear',
animationEasingUpdate: 'linear'
})
},
后端登录部分mybatis xml代码
select * from xjbs.user where username = #{username};
</select>
<select id = "getPassword" parameterType = "string" resultType = "string">
select password from xjbs.user where username = #{username};
后端注册部分mybatis xml代码
<mapper namespace="com.mapper.RegisterMapper">
<select id = "getUserByName" parameterType = "string" resultType = "_int">
select count(*) from xjbs.user where username = #{username};
</select>
<insert id = "addUser" parameterType = "User">
insert into xjbs.user (username, password) VALUES (#{username},#{password});
</insert>
</mapper>
后端论文有关部分mybatis xml代码
<mapper namespace="com.mapper.PaperMapper">
<select id="getTopWords" resultType="Keyword">
select keyword,count from xjbs.keyword_count ORDER BY count DESC limit 0,10;
</select>
<select id="getPapers" resultType="Paper">
select * from xjbs.paper;
</select>
<select id="getMeetingInfo" resultType="meetinginfo">
select magazine,count(*) as number,publication_year from xjbs.paper group by magazine,publication_year ORDER BY publication_year;
</select>
</mapper>
8. 心路历程及收获
HWY的感受:
一个字,累!这次做了Springboot的后端,最大的感受就是,后端的编码、编写逻辑其实不是很难,只占据了编程总时间中较少的一部分,真正麻烦的是各种框架的配置,“配置地狱”不是开玩笑的,尽管框架有整合,但是Springboot和Mybatis的配置我还是弄了很久,然后最多的时间是改bug,从一开始爆个bug毫无头绪到后面能熟练根据异常定位出错位置,我的debug能力肉眼可见地提高了。第一次尝试前后端分离写项目也是一种很奇妙的体验。
LLX的感受和收获:
有了第一次的结对经历,并且第一次已经完成了原型设计,我心里对第二次结对作业的难度有了大致的认识。这次作业对于我本人来说难度不小,一开始我是觉得做趋势分析那块内容会比前面复杂的多,但是后来我发现Vue框架的功能可太完整了,各种组件库任你选择。
而且前端开发可以看到页面的样子。我从什么都不会到搭建出一个个页面,心中莫名有种自豪感。但是编写页面的布局让我有些时候让人头疼。做前端让我感受到了一种甲方的感觉,一直在向后端提出需求。这次作业我收获不少,首先是巩固了Web的知识;其次,我还
了解了一些springboot的语法,可以理解一些简单的语句。这对我以后的后端之路有一定帮助。
9.队友评价
HWY ==> LLX
龙星做事一如既往地认真了高效率,结对作业开始后那几天每次去他们宿舍他一定是在进行vue的学习,这令我也感到责任重大,不敢拖拉,尽早开始学习Springboot的知识,在接口的参数和返回值等方面上我们交流许多,这让我们双方编写代码都省去了很多不必要的麻烦,编程过程中出现了很多的bug,但我们大量讨论解决,这使我们双方的debug能力都有了很大的提升。
LLX ==> HWY
我自认为后端的工作是非常复杂的,但是伟源一开始就主动承担了后端的工作。他在我们讨论完分工后就开始学习相关知识。这次后端最复杂的就是论文数据的处理,伟源也花了好几天才解决,效率挺高的。在实现设计的过程中,我提出的需求他也基本都实现了,第二次结对作业也结束了,我从中学到了不少知识。