310
社区成员




这个作业属于哪个课程 | 软件工程实践-2023学年-W班 |
---|---|
这个作业要求在哪里 | 结对第二次作业——编程实现 |
结对学号 | 222100417,222100420 |
这个作业的目标 | <将上一次结对作业所做的模型进行具体实现> |
其他参考文献 | … |
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 1700 | 1900 |
• Analysis | • 需求分析(包括学习新技术) | 600 | 800 |
• Design Spec | • 生成设计文档 | 20 | 30 |
• Design Review | • 设计复审 | 20 | 25 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30 | 35 |
• Design | • 具体设计 | 70 | 80 |
• Coding | • 具体编码 | 700 | 750 |
• Code Review | • 代码复审 | 60 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 40 | 55 |
• Test Repor | • 测试报告 | 20 | 15 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 1900 | 2015 |
我们设计了主页,详细界面,每日赛程,排名,奖牌榜这些主要界面,并对每个页面都设置了页眉导航栏。主页存在去往其他主要界面的连接;运动员界面提供了所有选手的信息;每日赛程中含有比赛日期、比赛项目等信息,可以切换日期查看不同赛程,并可通过点击某一赛程前往该赛程的信息界面;详细赛程界面中含有选手信息以及比赛结果;排名界面我们提供了不同的比赛项目,点击比赛项目会展开该赛程的比赛结果;更多界面展示了该赛事的一些介绍等等。
- 主页
主页导航栏HOME字标变色,以图片的形式显示去往其他界面的连接。- 选手信息
该页面展示参赛的各个选手的信息,如国籍(Country)、运动员姓名(Athlete)、性别(Gender)、出生日期(DOB)等。- 选手排名
选手排名主界面,主页导航栏RESULT字标变色,展示有结果的一些赛程,点击某一赛程框,展开改赛程的排名情况。点击其中某一个赛程便可看到排名情况,初始数据为最早的一次比赛数据,点击不同的赛次显示不同的比赛结果。- 每日赛程
每日赛程主界面,按日期对各赛程进行分类,可以在中间的下拉列表内选择所需的日期进行查看当天的赛程,也可以选择ALL显示近期的所有赛程,点击某一个赛程可以进入该赛程的详细界面。- 详细赛况
点击SHEDULES界面的某一赛程显示出详细赛况。其中显示本场比赛参赛选手(Athlete)、选手排名(Overall Rank)、比赛积分(Ponits)、落后积分(Pts Behind)等信息。- 奖牌榜
该页面展示参赛的各个国家的获奖情况,显示各个国家分别获得的金牌数量,银牌数量,铜牌数量以及总的奖牌数,并按照一定的规则进行排名。- 更多
主页导航栏MORE字标变色,展示该赛事的介绍等等。
刚拿到题目后,简单和队友讨论了一下我们要用的前端后端框架和开发工具,因为222100420同学学过后端Spring Boot开发,所以就由其负责后端开发以及云服务器的部署,222100417负责前端开发以及博客的书写。
我们遇到过前后端接口问题,为此我们专门去向一些有经验的前辈请教,并查看了一些相关文档,统一了接口问题,并且因为使用了接口,整个开发过程前后端联调的时候异常顺利。
前端采用Vue框架,搭载路由router,并在results界面使用element库进行折叠面板的编写。因为项目中主要框架基本类似,故在components专门设置pages包存放主框架,后在views设置各个界面的视图(如HomeView.vue),并设置不同界面的Main组件,通过props传参以及条件渲染来进行不同界面的展示功能。后将访问后端的接口路由放置到main.js,以便于修改。
后端采用Spring Boot框架,并使用maven构建项目并管理依赖。因为项目中用到大量实体类,常量,因此将其分为三个模块。分别是server模块,用来处理请求返回请求,pojo模块,用来存实体类,common模块,用来存json文件路径。server模块分为controller包,service包和config包。controller包负责接收请求并使用@ResponseBody封装并返回数据。service包主要负责业务逻辑实现,从文件中读取数据。并返回给controller。config包负责一些配置
一、axios
用axios来想后端发送GET请求,backendRouter是作为声明在main.js里的全局变量,用于设置访问后端的URL
const backendRouter = inject('backendRouter');
onMounted(() => {
// 发送GET请求
axios.get(backendRouter.url + '/daily/list?date=all')
.then(response => {
// response.data 就是上面的JSON数组
datas.value = response.data.data;
dates.value = datas.value.map(function(obj) {
return obj.date;
});
dates.value.unshift("ALL")
})
});
二、el-collapse折叠面板
用element库中的el-collapse组件来设置折叠面板,当点击某个比赛面板时展开与比赛面板标题相对应的内容,并显示有几个按钮,点击按钮可以切换该比赛的不同赛段。
<el-collapse v-model="activeNames" accordion>
<el-collapse-item v-for="match in matches" :key="match.eventName" :title="match.eventName" :name="match.eventName" >
<div>
<div class="buttons">
<button v-for="pName in types" :key="pName" @click="changeDetial(pName)"
:style="{backgroundColor: pName === phaseName ? 'gray' : 'white' , width: '20%', height: '40px',
border: '1px solid grey', borderRadius: '3px'
}">
{{ pName }}
</button>
</div>
<div >
<div class="title">
<span style="width: 15%; text-align: center;">Overall Rank</span>
<span style="width: 30%; text-align: center;">Country</span>
<span style="width: 35%; text-align: left;">Athlete</span>
<span style="width: 10%; text-align: center;">Age</span>
<span style="width: 10%; text-align: center;">Points</span>
</div>
<hr class="hrr" style="height: 3px;"/>
<div v-for="detial in detials" :key="detial.overallRank"
:style="{ backgroundColor: detial.overallRank % 2 === 0 ? 'white' : 'rgba(128, 128, 128, 0.2)' }" class="item">
<span style="width: 15%; text-align: center;">{{ detial.overallRank }}</span>
<span style="width: 15%; text-align: right; padding-right: 8px">
<img :src="'/images/img-flag/' + detial.country + '.png'" style="width: 30px;" />
</span>
<span style="width: 15%; text-align: left;">{{ detial.country }}</span>
<span style="width: 35%; text-align: left; color: black; ">
<div v-for="athlete in detial.athletes" :key="athlete.athleteName">{{ athlete.athleteName }}</div>
</span>
<span style="width: 10%; text-align: center;">
<div v-for="athlete in detial.athletes" :key="athlete.athleteName">{{ athlete.age }}</div>
</span>
<span style="width: 10%; text-align: center;">{{ detial.totalPoints }}</span>
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
watch(activeNames, () => {
/* console.log(activeNames.value) */
if(activeNames.value !== "" ){
/* console.log(activeNames.value) */
// 发送GET请求
axios.get(backendRouter.url +'/rank/detail?eventName=' + activeNames.value )
.then(response => {
// response.data 就是上面的JSON数组Message: {{ msg }}
datas.value = response.data.data;
types.value = types.value.filter((t) => t === '')
datas.value.forEach(element => {
types.value.push(element.phaseName);
});
phaseName.value = types.value[types.value.length - 1];
datas.value.forEach(element => {
if(element.phaseName === phaseName.value){
detials.value = element.eventRanks;
}
});
})
}
})
三、下拉列表显示,选择不同选项进行切换日期
设有一个下拉列表,选择不同选项可以进行切换日期,下面的内容改变为当天的比赛日程。使用router-link标签使其可以点击某个比赛日程,可以通过路由跳转到相应的detials界面
<div class="title">
<select v-model="selectedDate" class="select" style="margin-right: 20px;">
<option v-for="date in dates" :value="date" class="select">{{ date }}</option>
</select>
</div>
<hr class="hrr" style="height: 3px;"/>
<div v-for="data in showDatas" :key="data.date" style="width: 95%; margin: 0 auto;">
<p class="date">{{ data.date }}</p>
<router-link v-for="match in data.events" :key="match.eventTime" :to="{ name:'details', params: { name: match.eventName, type: match.eventPhase } }" class="routerlinktext">
<div class="routerlink">
<div class="vertical-line" style="background-color: #0D4FAD;height: 30px; width: 3px;"></div>
<span style="width: 15%; text-align: center;">{{ match.eventTime }}</span>
<div class="vertical-line"></div>
<span style="width: 40%; text-align: right; font-size: 20px;">{{ match.eventName }}</span>
<span style="width: 3%;"></span>
<span style="width: 20%; text-align: left; color: gray; font-size: 20px;">{{ match.eventPhase }}</span>
<span style="width: 20%; text-align: right; color: #BEBEBE;">{{ "ENTER DETAIL →" }}</span>
</div>
</router-link>
</div>
watch(selectedDate, () => {
if (selectedDate.value === "ALL") {
showDatas.value = props.datas;
} else {
showDatas.value = props.datas.filter(item => selectedDate.value === item.date);
}
})
一、Swagger
因为前后端同时进行开发时,不能使用前端来发送请求,而每次想检验请求是否能正确返回参数就得在网站输入,非常的麻烦与不便,使用Swagger他就会自动根据接口来生成请求,还会保存请求参数,非常方便快捷
二、统一返回结果代码
因为每个界面要求的数据不一样,如果直接返回的话,结果会非常杂乱,不利于前端的使用和维护,统一封装到Result对象中返回,其中code表示成功与否,1为成功,其他数字为失败,msg表示失败的原因,data是返回给前端的数据。
三、跨域
前后端联调时发现前端请求后端数据返回的状态是200,但并未接收到数据,去查询了许多人,发现是前端运行的端口号与后端运行端口号不一致导致的,但是修改端口号以后也会遇到很多问题,故此在后端写了跨域的代码,以此允许前端获得数据
- 问题:第一次使用组合式vue,对很多属性不熟悉
解决:使用原web知识,再配合vue的官方文档进行学习- 问题:不同路由之间不知如何传输多个参数
解决:在router/index.js文件中对每个路由设置name属性,使其能够通过name属性转接,再通过params将所需要传输的多个数据进行封装,最后通过:to="{ name:'details', params: { name: match.eventName, type: match.eventPhase } }"语句将参数通过props传输给另外一个路由- 问题:el-collapse的标题格式无法改变
解决:由于el-collapse对其class进行的绑定,以至于无法在使用时,之间通过其class属性修改标题格式,我查阅资料,最终使用:deep(.el-collapse-item__header)来进行对header格式的修改。
- 问题:在服务器运行后端程序时,一直运行不起来
解决:通过查看java版本,发现服务器java环境没有配置,配置Java环境,运行,发现端口冲突,修改运行端口,运行成功- 问题:后端程序在运行无法处理请求
解决:通过nphup.out,查看报错原因,未检测到json文件,查看代码,后端设计时把路径写死,无法访问到打包在jar包里的json数据,修改读取路径,成功读取并返回
在完成本次作业前,对使用git合作,拉代码还是一知半解,经过本次合作后,不仅对git命令的使用,还是项目的管理,分模块,都有了更深刻的理解。对已经学习的技术进行进一步的实践加深了对知识的理解。
在本次作业前,对vue框架几乎不会,所有前端界面代码的编写都是先学的。经过本次项目后对vue框架的结构有了较深的了解,对大组件分化为小组件,以及各种组件的组合,访问和管理有了更加深刻的理解,进一步理解前端页面的布置。
余承烨是一个非常善于发现自身不足并改进,同时也善于发挥自身优势来推动工作进展的好搭档,在本次结对作业的过程中多次发现问题,并和我积极讨论解决方案,和他合作让我感觉很有动力,因为我们总是在不断改善,不断进步。
陈佳伟展现了高水平的专业知识和技能,并且善于沟通,有效传达清晰的想法和解决问题,愿意分享知识和技能,为设计的成功贡献了强大的力量,他展现出来高度的可靠性和责任感,是一位优秀的合作伙伴。
前端的目录链接进行了设计,赞!布局上考虑了手机端的用户,值得肯定。但是没有实现页面的自适应。参赛选手的头像没有渲染上去。
前端页面布局不够美观,网页宽度不够,观感差,可以考虑做一下自适应布局,还有网页可以做成中文的,这样也方便国内的用户使用。
日期选择实现的不错,赞!
设计过程的前后端文字描述结合设计图会更直观;
主页面内容和导航栏完全重复了,改善的话可以添加一些统计信息的部分或者资讯,起到统领或介绍的效果