结对第二次作业-编程实现

222000317王侨文 学生 2023-03-24 20:28:35
这个作业属于哪个课程2023年福大-软件工程-实践-W班
这个作业要求在哪里结对第二次作业--编程实现
结对学号222000317_222000318
这个作业的目标编程实现结对作业,撰写博客
其他参考文献《构建之法》

目录

  • 1.仓库地址和代码规范链接
  • 2.PSP表格
  • 3.成品展示
  • 3.1.首页
  • 3.2晋级图
  • 3.3选手排名
  • 3.4每日赛程
  • 3.5导航栏
  • 4.结对过程
  • 5.设计实现过程
  • 5.1功能结构图
  • 5.2设计过程
  • 系统设计
  • 合理性
  • 6.关键代码
  • 6.1前端部分
  • 6.1.1导航栏
  • 6.1.2每日赛程
  • 6.1.3选手排名
  • 6.1.4首页
  • 6.1.5晋级图
  • 6.2后端部分
  • 7.结对感受和评价队友
  • 7.1结对感受
  • 7.2 评价队友

1.仓库地址和代码规范链接

仓库地址
代码规范

2.PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划2030
• Estimate• 估计这个任务需要多少时间1020
Development开发11801362
• Analysis• 需求分析 (包括学习新技术)240300
•get data•获取数据 4550
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)1522
• Design• 具体设计2030
• Coding• 具体编码720800
• Code Review• 代码复审6060
• Test• 测试(自我测试,修改代码,提交修改)80100
Reporting报告8085
• Test Repor• 测试报告3030
• Size Measurement• 计算工作量2020
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3035
合计12801477

3.成品展示

3.1.首页

首页为默认入口,图片轮播展示。

img

3.2晋级图

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

img

3.3选手排名

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

img

3.4每日赛程

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

img


(由于录屏的原因,下拉菜单没有显示出来,补充了截图)

img

3.5导航栏

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

4.结对过程

img

img

img

img

img

img

5.设计实现过程

5.1功能结构图

功能结构图

5.2设计过程

系统设计

  • 需求分析:
    1. 首页图片轮播。
    2. 展示选手排名。
    3. 展示每日赛程。
    4. 展示晋级图。
  • 架构设计:
    该项目采用前后端分离架构,前端使用vue3框架,后端使用springboot框架。使用MySQL作为数据库存储数据。
  • 技术选型:
    vue3、bootstrap、springboot、mybatis-plus
  • 代码结构设计:
    前端采用组件化开发,后端采用模块化开发,API采用RESTful风格设计。

合理性

根据结对作业一原型进行设计,仿照官网页面的基本功能来实现。实现导航栏的移入显示、移除隐藏效果,页面中包含了导航栏和页脚,充实页面主体部分。首页有常见的图片轮播,晋级图使用可点击左右侧实现切换,选手排名页面有放置高亮效果,每日赛程可通过选择地址和日期配合显示结果。

6.关键代码

6.1前端部分

前端采用vue3框架,向后端发送请求并接收处理后端发来的数据。

6.1.1导航栏

配置好路由,使导航栏能正常跳转。

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
              }
            ]

(导航栏的前端实现)

6.1.2每日赛程

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>

6.1.3选手排名

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>

6.1.4首页

直接使用了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>

6.1.5晋级图

根据原型里面的大致要求,使用了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>

6.2后端部分

后端采用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);
}
}

7.结对感受和评价队友

7.1结对感受

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的基本使用方法和团队协作的重要性。最后,我的协作配合能力也得到了增强。

7.2 评价队友

  • 对王同学的评价:

在新技术的学习方面,王同学展现了出色的学习能力和适应能力,快速掌握了新的技术和工具,并将其应用到项目中。在学习过程中,王同学表现出了极大的耐心和恒心,通过不断地探索和实践,逐渐熟悉了vue框架 bootstrap框架和git提交代码等技术的使用。除此之外,在项目的实现过程中王同学展现了很好的合作精神,积极地与我进行讨论和交流,共同探讨问题,共同解决问题,能够很好地理解和尊重我的想法,也非常愿意分享自己的看法和建议。王同学在项目中的工作也非常细心和认真,能够在开发过程中不断检查和修改代码,确保代码的质量和项目的进度。这些优点,都值得我学习。

  • 对吴同学的评价:

吴同学在此次作业中积极与我配合,沟通能力也非常不错,能够很好地表达出他的想法和意见,并在队伍内部保持良好的交流氛围。对于新技术的学习,吴同学也表现的非常积极,并不因为之前没有接触过相关方面的技术而感到气馁,这点让我非常欣赏。除此之外,通过此次和吴同学结对完成作业,我自己的协作能力以及对技术的熟悉和掌握程度也得到了一定程度的加强。总体来说,吴同学在这个项目中的表现很好。

...全文
300 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
助教-张思锐 助教 2023-04-07
  • 打赏
  • 举报
回复

功能结构图是否上传失败?

688

社区成员

发帖
与我相关
我的任务
社区描述
2023年福州大学软件工程实践课程W班的教学社区
软件工程团队开发软件构建 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • 张书旖
  • 郭渊伟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧