688
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2023年福大-软件工程-实践-W班 |
|---|---|
| 这个作业要求在哪里 | 结对第二次作业--编程实现 |
| 结对学号 | 222000317_222000318 |
| 这个作业的目标 | 编程实现结对作业,撰写博客 |
| 其他参考文献 | 《构建之法》 |
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 20 | 30 |
| • Estimate | • 估计这个任务需要多少时间 | 10 | 20 |
| Development | 开发 | 1180 | 1362 |
| • Analysis | • 需求分析 (包括学习新技术) | 240 | 300 |
| •get data | •获取数据 | 45 | 50 |
| • Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 15 | 22 |
| • Design | • 具体设计 | 20 | 30 |
| • Coding | • 具体编码 | 720 | 800 |
| • Code Review | • 代码复审 | 60 | 60 |
| • Test | • 测试(自我测试,修改代码,提交修改) | 80 | 100 |
| Reporting | 报告 | 80 | 85 |
| • Test Repor | • 测试报告 | 30 | 30 |
| • Size Measurement | • 计算工作量 | 20 | 20 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 35 |
| 合计 | 1280 | 1477 |
首页为默认入口,图片轮播展示。

从第四轮开始,设计两张轮播图,每张轮播图展示三个轮次,从而达到查看每个选手的晋级路线。

通过点击切换按钮,可以切换展示男女子排名。鼠标移入某一行有高亮效果。

通过标签栏可以选择日期展示不同日期下的赛程结果。通过下拉菜单可以配合选择显示某天某地的比赛结果。


移入则显示,移出则隐藏。用来跳转到各个页面。






根据结对作业一原型进行设计,仿照官网页面的基本功能来实现。实现导航栏的移入显示、移除隐藏效果,页面中包含了导航栏和页脚,充实页面主体部分。首页有常见的图片轮播,晋级图使用可点击左右侧实现切换,选手排名页面有放置高亮效果,每日赛程可通过选择地址和日期配合显示结果。
前端采用vue3框架,向后端发送请求并接收处理后端发来的数据。
配置好路由,使导航栏能正常跳转。
const routes = [
{
path: '/ranks',
name: 'ranks',
component: RanksView
},
{
path: '/results',
name: 'results',
component: ResultsView
},
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/draws',
name: 'DrawsView',
component: DrawsView
}
]
(导航栏的前端实现)
results页面创建时则执行getResults函数。通过axios向后端发送请求,将返回的数据存入contents数组。将所有地点去重后存入addresses数组。
changeDay函数用来修改与切换不同日期的比赛结果的相关的变量。
turnFirst和turnNotFirst函数用于辅助归类同一地址下的比赛结果。
监听selectItem变量,当该变量被下拉菜单修改时则切换展示被选中地址的比赛结果。
created() {
this.getResults()
},
methods:{
getResults:function (){
axios.get('http://localhost:8081/results').then((res)=>{
this.contents = res.data.data
//取第一天的所有地址就能覆盖到后面的地址了
this.addresses = this.contents[0].map(item => item.address)
this.addresses = Array.from(new Set(this.addresses))
})
},
changeDay:function (){
let id = event.currentTarget.id
this.date = id
this.checkList = this.clean.slice()
this.checkList[id] = true
},
turnFirst:function (){
this.isFirst = true;
return false;
},
turnNotFirst:function () {
if (this.isFirst === true){
this.isFirst = false
return true
}
else return false
}
},
watch: {
selectItem(newValue) {
if (newValue != "0")
this.addresses = this.addr1[newValue-1]
else
this.addresses = this.addr2
}
}
turnFirst用于重设当前地址为首次出现的状态,turnNotFirst使得重复地址不再输出。
<div class="tab-content">
<div v-for="(ad,j) in addresses" :key="j" class="">
<!--每次新地点的循环都更改一次状态-->
<span v-if="turnFirst()"></span>
<span v-for="(result,index) in contents[date]" :key="index" :class="{active:(checkList[index])}" id="content" >
<!--<h2 class="container to-line" v-if="result.address===ad&&turnNotFirst()">{{ad}}</h2>-->
<div class="container" v-if="result.address===ad&&turnNotFirst()">
<hr class="to-line">
<h2 class="to-line">{{ad}}</h2>
</div>
<!--从contents数组中拿去某一date的当日数据,当日数据由多个result组成-->
<span class="card to-row" v-if="result.address===ad">
<ul class="list-group list-group-flush to-row">
<li class="list-group-item">
<span>
<span class="winner to-line" style="float: left;display: block">{{result.type}}</span>
<span class="lessLight to-line" style="float: left;display: block">{{result.address}}</span>
</span>
<span class="lessLight" style="float: right">{{result.time}}</span>
</li>
<li :class="{'list-group-item':true,winner:result.winner === 1}">
<span style="float: left">{{result.player1}}</span>
<span style="float: right">{{result.score1}}</span>
</li>
<li :class="{'list-group-item':true,winner:result.winner === 2}">
<span style="float: left">{{result.player2}}</span>
<span style="float: right">{{result.score2}}</span>
</li>
</ul>
</span>
</span>
</div>
</div>
ranks页面创建时执行getRanks函数,通过axios向后端发送请求,将返回的结果存入到arr数组中。switch函数用于修改展示男子排名页面和女子排名页面的状态。
created() {
this.getRanks()
},
methods: {
getRanks:function (){
axios.get('http://localhost:8081/ranks').then((res)=>{
this.arr = res.data.data
})
},
switch:function () {
this.tableState = this.tableState === 1 ? 2 : 1;
}
tableState用于控制展示男子排名或女子排名,v-for遍历后端返回的数据并输出到表格内。
<div v-if="tableState === 1" class="col-12">
<h2>Men’s Singles Aces Leaders</h2>
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th>
<span>Rank</span>
</th>
<th>
<span>Matches</span>
</th>
<th>
<span>Aces</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in arr" :key="index" :class="{lightShadow:item.rank % 2 == 1}" >
<td v-if="item.id < 21">{{ item.name }}</td>
<td v-if="item.id < 21">{{ item.rank}}</td>
<td v-if="item.id < 21">{{ item.matches}}</td>
<td v-if="item.id < 21">{{ item.aces}}</td>
</tr>
</tbody>
</table>
</div>
直接使用了bootstrap框架里的样式,引入bootstrap后,从轮播图里面选择自己需要的样式,复制代码并更新图片即可
<div class="container">
<div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="../assets/home.jpg" class="d-block w-100" alt="">
<div class="carousel-caption d-none d-md-block">
<p>澳大利亚网球公开赛(英语:Australian Open,简称:澳网)是网球四大满贯赛事之一。</p>
</div>
</div>
<div class="carousel-item">
<img src="../assets/home2.png" class="d-block w-100" alt="">
<div class="carousel-caption d-none d-md-block">
<p>比赛通常于每年一月的最后两周在澳大利亚维多利亚州的墨尔本体育公园举行,是每年四大满贯中最先举行的一个赛事,也是最年轻的大满贯</p>
</div>
</div>
<div class="carousel-item">
<img src="../assets/home3.png" class="d-block w-100" alt="">
<div class="carousel-caption d-none d-md-block">
<p>澳大利亚网球公开赛创办于1905年,已经有100多年的历史。</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
根据原型里面的大致要求,使用了v-for 以及 v-show 来控制每轮比赛中的选手个数,并使用bootstrap中的卡片,用来作为每个选手信息和得分的容器,通过在卡片中使用分割线,将选手与选手分开。给中间的轮次和右边的轮次,分别设置类名:center,right,通过调整这两个类的margin,来实现居中效果
<div v-show="date[index-1] === '4th Round'" class="list-group list-group-flush" v-for="index1 in extensibleInfo" :key="index1">
<div class="list-group-item">
<span :class="{name:true,strong:index1.winner === 1}" >
{{ index1.player1 }}
</span>
<span :class="{score:true,strong:index1.winner === 1}">
{{ index1.score1 }}
</span>
</div>
<div class="list-group-item">
<span :class="{name:true,strong:index1.winner === 1}" >
{{ index1.player2 }}
</span>
<span :class="{score:true,strong:index1.winner === 1}">
{{ index1.score2 }}
</span>
</div>
</div>
<style>
.center {
margin-top: 120px;
}
.right {
margin-top: 280px;
}
</style>
后端采用springboot框架,将MySQL数据库中的数据提取出并发送给前端页面。
使用@CrossOrigin注解和修改配置文件来解决跨域问题。使用@GetMapping接收前端以get方式发来的请求。
LambdaQueryWrapper是MyBatis-Plus提供的一种基于Lambda表达式的查询构造器,可以通过Lambda表达式构造查询条件,避免手写字符串拼接的方式,使得代码更加直观、简洁、安全。R为自己写的通用结果返回类。
初步查询得到的数据存入results,将数据根据日期来划分后存入map,再将map中的数据转存到arr中,之后将结果返回。
//ResultController部分
@CrossOrigin(origins = "http://localhost:8082")
@RestController
@RequestMapping"/results")
public class ResultController {
@Autowired
private ResultService resultService;
@GetMapping
public R<List<List<Result>>> getResults(){
LambdaQueryWrapper<Result> queryWrapper = new LambdaQueryWrapper();
List<Result> results = resultService.list(queryWrapper);
Map<Integer,List<Result>> map = results.stream()
.collect(Collectors.groupingBy(Result::getDate));
List<List<Result>> arr = new ArrayList<>();
arr.add(map.get(0));
arr.add(map.get(1));
arr.add(map.get(2));
return R.success(arr);
}
}
//RankController部分
@CrossOrigin(origins = "http://localhost:8082")
@RestController
@RequestMapping("/ranks")
public class RankController {
@Autowired
private RankService rankService;
@GetMapping
public R<List<Rank>> getRanks(){
LambdaQueryWrapper<Rank> queryWrapper = new LambdaQueryWrapper();
List<Rank> ranks = rankService.list(queryWrapper);
return R.success(ranks);
}
}
222000317:
完成本次项目,是一段既痛苦又充实的历程。从需求分析、技术选型,到代码实现、查看效果,每个环节都不容易。
在本次作业中,我遇到了很多挑战。首先,我必须学会并熟练使用Vue框架和Bootstrap框架以及springboot宽假,这些框架在以前我没有使用过,需要学习不少内容。其次,我需要与队友密切合作,理解他的代码,并帮助解决他可能遇到的问题。在整个项目的过程中,我遇到了许多问题和挑战,但最终我们共同克服了它们,并成功地完成了项目。
在这个项目的过程中,我收获了很多。首先,我学会了如何在团队中协作。项目作业的完成离不开队友的贡献,我们必须共同合作,克服困难,才能达到我们的目标。其次,我学会了如何使用Vue框架和Bootstrap和springboot框架。这些框架不仅可以加快Web应用程序的开发速度,还可以提高程序的质量和易于维护性。最后,我学会了如何使用Git进行代码管理。Git是一个非常有用的版本控制系统,它可以帮助团队成员共同管理代码,协同开发项目。
总的来说,这个项目对我具有非常积极的意义。通过本次项目,我不仅接触到了新的技术,还学会了如何与队友协作开发,以及如何使用git来创建分支管理一个项目。
222000318:
在此次的项目中,我和我的队友共同完成了一个基于Vue框架和Bootstrap框架的Web网页。这是我第一次使用Vue和Bootstrap框架进行Web开发,对我来说是一个非常有意义的经历。
在项目的开始阶段,我首先了解了Vue框架的基本概念和语法,接触到了组件化开发的思想。我使用了Vue的官方脚手架 ,并和我的队友一起分析了项目的基本需求。在Vue框架的学习过程中,我深刻理解到组件化开发的优势和重要性,以及Vue框架如何将组件化开发落地实现。
接下来,我们开始使用Bootstrap框架进行界面设计和开发。Bootstrap框架是一个流行的前端框架,拥有丰富的样式库和组件,能够快速搭建出美观的Web界面。在使用Bootstrap框架的过程中,我学习了它的基本概念、CSS样式的应用和JS插件的使用方法。通过对Bootstrap框架的学习和私用,我们能够快速实现界面设计和开发,大大提高了我们的开发效率。
在项目的开发过程中,我们使用Git进行版本控制和队伍协作。在使用Git的过程中,我们学习了分支管理、合并冲突、提交和推送代码等基本操作,有效地提高了队伍的开发效率
通过本次项目,我获益良多,。首先,我对Vue和Bootstrap框架有了更深入的理解,能够更快速地进行Web应用程序的开发。其次,我学习到了Git的基本使用方法和团队协作的重要性。最后,我的协作配合能力也得到了增强。
在新技术的学习方面,王同学展现了出色的学习能力和适应能力,快速掌握了新的技术和工具,并将其应用到项目中。在学习过程中,王同学表现出了极大的耐心和恒心,通过不断地探索和实践,逐渐熟悉了vue框架 bootstrap框架和git提交代码等技术的使用。除此之外,在项目的实现过程中王同学展现了很好的合作精神,积极地与我进行讨论和交流,共同探讨问题,共同解决问题,能够很好地理解和尊重我的想法,也非常愿意分享自己的看法和建议。王同学在项目中的工作也非常细心和认真,能够在开发过程中不断检查和修改代码,确保代码的质量和项目的进度。这些优点,都值得我学习。
吴同学在此次作业中积极与我配合,沟通能力也非常不错,能够很好地表达出他的想法和意见,并在队伍内部保持良好的交流氛围。对于新技术的学习,吴同学也表现的非常积极,并不因为之前没有接触过相关方面的技术而感到气馁,这点让我非常欣赏。除此之外,通过此次和吴同学结对完成作业,我自己的协作能力以及对技术的熟悉和掌握程度也得到了一定程度的加强。总体来说,吴同学在这个项目中的表现很好。
功能结构图是否上传失败?