688
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2023年福大-软件工程实践-W班 |
|---|---|
| 这个作业要求在哪里 | 结对第二次作业——编码实现 |
| 结对学号 | 222000334 222000331 |
| 这个作业的目标 | 1.fork仓库,使用Git合作完成项目 2.制定代码规范 3.编码实现原型,完成指定功能 4.将项目部署到云服务器 5.撰写博客 |
| 其他参考文献 | VUE官网, Nodejs官网, 基于 Vue 2.x 的 Element UI, 百度前端代码规范 |
@
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| • Planning | • 计划 | 30 | 20 |
| • Estimate | • 估计这个任务需要多少时间 | 10 | 10 |
| • Analysis | • 需求分析 | 300 | 450 |
| • Development | • 开发 | 1800 | 1920 |
| •Discussion | • 讨论交流 | 60 | 60 |
| • Design Spec | • 生成设计文档 | 60 | 90 |
| • Design Review | • 设计复审 | 60 | 60 |
| • Coding Standard | • 制定代码规范 | 30 | 60 |
| • Coding | • 具体编码 | 1200 | 1320 |
| • Test | • 测试 | 120 | 90 |
| Reporting | • 报告 | 120 | 180 |
| • Size Measurement | • 计算工作量 | 5 | 5 |
| • Postmortem & Process Improvement Plan | • 事后总结,, 并提出过程改进计划 | 30 | 30 |
| 合计 | 2025 | 2375 |
展示男女Singles Aces leaders排名,排名展示选择斑马纹表格,添加鼠标悬浮变色,方便聚焦浏览信息

滑动按钮组选择具体某一天,鼠标悬浮不同颜色凸显,鼠标点击变色




Day14的第一个赛程的详细赛况





描述设计实现过程,给出功能结构图。

数据获取部分
本次作业的Json数据较复杂,各种对象之间存在映射关系不能直接拿到需要的信息。于是根据需要的信息设计新的Json文件格式,通过代码将原Json文件处理成新的数据,直接配置在web项目中,方便前端数据渲染。

前端渲染页面
负责后端的同学将原本复杂的json数据处理成简单的格式,方便前端渲染。
页面布局、数据渲染两部分实现。原型设计实现,通过开发者工具测量元素的大小样式,并编写css代码调整样式。其中,表格、轮播图、卡片、选择器、菜单栏、导航栏等内容通过ElementUi实现。通过查阅官网的官方文档编写并修改相应代码。模板字符串实现,可以动态生成满足要求的HTML代码,并利用innerHTML渲染到dom元素中。

dev分支用于合并其他分支的代码,我们二人分别在各自的331,334分支进行开发工作,需要合并项目时先切换到dev分支,使用git merge 3331/334来合并项目。最后所有代码完成时切换到master分支,使用git merge dev来获取整个项目。但是由于对Git协同开发不熟悉,导致了一些操作上的不规范,比如没有在约定好的自己的分支上开发;不知道当前是什么分支以至于找不到代码(很慌);push后远程仓库没有变化(vscode自带的Git管理器同步不及时,需要手动刷新);修改代码时没有先同步dev分支,导致合并时报错;编写的文件和已经上传到远程仓库中的代码冲突导致合并冲突等等等等(心累),解决办法就是发生错误时去查看相关技术博客,照着操作,学习了很多git的操作,比如强制推送git push --force,撤销前一次提交git reset --hard HEAD^等等。所以团队开发时一定要规范操作,避免分支管理上的错误造成代码混乱,甚至代码丢失。开发分支设计图

重装。通过远程工具下载宝塔面板后建立站点,一开始用新买的域名建站,可以成功访问,过一会访问就显示域名没有备案(被发现了)。后来发现可以在建站后进行域名管理,添加服务器IP 作为新域名,然后删除之前的域名,这样就可以通过云服务器的IP地址访问项目了。如果默认的端口80被其他程序占用可以在设置域名时设置端口,同时在服务器上开放该端口。还有一点,访问项目时需要使用http协议,通过https协议访问要求网站配置ssl证书(好贵),否则会显示该连接不安全无法访问到项目。HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。前端问题:
日期切换按钮组
日期切换按钮组在elementui、bootstrap等一系列组件库中找不到相似组件,不知道如何实现。两个组件层来实现,上一层为显示层,下面一层为滑动层。滑动层中放置14个日前按钮,其长度要比显示层长,然后用overflow:hidden将超出显示层的部分隐藏,即可实现效果。但是学习和实现花了好长的时间。winner样式加粗
winner要加粗显示,但是我的html是通过js生成的,不知道该如何添加类。if-else判断是否是赢家,然后为是赢家的元素添加winner类。在winner类中编写加粗样式。渲染每日赛程
// 每日赛程
getResults (e) {
// 获取results元素
const results = document.querySelector('.results')
//获取选择的日期
this.date = e.currentTarget.firstElementChild.innerHTML
for (let cout = 0; cout < 18; cout++) {
if (e.currentTarget.parentNode.parentNode.children[cout].children[0].classList.contains('selected')) {
e.currentTarget.parentNode.parentNode.children[cout].children[0].classList.remove('selected')
}
}
e.currentTarget.classList.add('selected')
console.log(e.currentTarget.parentNode.parentNode.children[0].children[0])
const jsonStr = require(`../../../public/data/${this.date}.json`)
let htmlStr = ``
jsonStr.matches.forEach(item => {
let resultStr = ''
let firstStr = ''
let secondStr = ''
let flag = 0
遍历teams数组
item.teams.forEach(item_teams => {
let playerStr = ``
let scoreStr = ``
//如果选手人数为1,则调整名字到中间位置
if(item_teams.players.length === 1){
// 遍历players数组
item_teams.players.forEach(item_players => {
playerStr += `<div class="player" style="margin-top:12px;">${item_players.short_name}<span>${item_players.nationality}</span></div>`
})
} else {
// eslint-disable-next-line
item_teams.players.forEach(item_players => {
playerStr += `<div class="player">${item_players.short_name}<span>${item_players.nationality}</span></div>`
})
}
// 遍历score数组
item_teams.score.forEach(item_score => {
scoreStr += `
<span>${item_score.game}</span>
`
})
//处理winner样式加粗
if (flag === 0) {
if (item_teams.is_winner === true) {
firstStr = '<div class="first winner"><div class="left">' + playerStr + '</div><div class="right">' + scoreStr + '</div></div>'
} else {
firstStr = '<div class="first"><div class="left">' + playerStr + '</div><div class="right">' + scoreStr + '</div></div>'
}
console.log(firstStr)
} else {
if (item_teams.is_winner === true) {
secondStr = '<div class="second winner"><div class="left">' + playerStr + '</div><div class="right">' + scoreStr + '</div></div>'
} else {
secondStr = '<div class="second"><div class="left">' + playerStr + '</div><div class="right">' + scoreStr + '</div></div>'
}
console.log(secondStr)
}
flag = 1
})
// eslint-disable-next-line
resultStr = firstStr + secondStr + '</el-card>'
//拼接模板字符串
htmlStr += `
<el-card class="box-card is-always-shadow el-card">
<div class="event">
<div class="top">
<span class="title">${item.event_type}</span>
<span class="status">Complete</span>
</div>
<div class="bottom">
<span class="court"><span>${item.round_type} • </span>${item.court}</span>
<span class="time">${item.duration}</span>
</div>
</div>` + resultStr
// console.log(playerStr)
})
// eslint-disable-next-line
// console.log(htmlStr);
//插入模板字符串到dom元素中(results)
results.innerHTML = htmlStr
}
晋级图渲染
renderDraws (data) {
//根据data,得到相应的json文件
if (data === 'MS') {
jsonStr = require('../../../public/data/MS.json')
} else if (data === 'MD') {
jsonStr = require('../../../public/data/MD.json')
} else if (data === 'WS') {
jsonStr = require('../../../public/data/WS.json')
} else {
jsonStr = require('../../../public/data/WD.json')
}
//以Quarterfinals(四分之一决赛)为例,遍历数据
jsonStr.Quarterfinals.forEach(item => {
if (item_teams.players.length === 1) {
}
//遍历players数组
item_teams.players.forEach(item_players => {
if (item_teams.players.length === 1) {
//添加winner样式,加粗
if (item_teams.is_winner === true) {
playerStr += `
<div class="player" style="margin-bottom:0px !important;margin-top:13px !important;font-weight:900;">
<span class="name">${item_players.short_name}</span>
<span class="guoji">${item_players.nationality}</span>
</div>
`
} else {
playerStr += `
<div class="player" style="margin-bottom:0px !important;margin-top:13px !important;">
<span class="name">${item_players.short_name}</span>
<span class="guoji">${item_players.nationality}</span>
</div>
`
}
} else {
if (item_teams.is_winner === true) {
playerStr += `
<div class="player" style="font-weight:900;">
<span class="name">${item_players.short_name}</span>
<span class="guoji">${item_players.nationality}</span>
</div>
`
} else {
playerStr += `
<div class="player">
<span class="name">${item_players.short_name}</span>
<span class="guoji">${item_players.nationality}</span>
</div>
`
}
}
})
//遍历得分数组,渲染数据
item_teams.score.forEach(item_score => {
scoreStr += `<span>${item_score.game}</span>`
})
if (flag === 0) {
teamResult1 = '<div class="first"><div class="left">' + playerStr + '</div><div class="right"><span class="score">' + scoreStr + '</span></div></div>'
} else {
teamResult2 = '<div class="second"><div class="left">' + playerStr + '</div><div class="right"><span class="score">' + scoreStr + '</span></div></div>'
}
flag = 1
})
//拼接结果
quarStr += '<el-card class="box-card carousel-index-0 el-card" style="width:300px;">' + teamResult1 + teamResult2 + '</el-card>'
})
// console.log(quarStr)
//将结果添加到dom元素中
quar.innerHTML = quarStr
使用开发者工具在官网上爬取原数据(此数据爬取行为仅用于作业),再使用Gson序列化将写好的数据类自动映射成对应格式的Json对象,输出到文件中。
原数据类
package org.example;
import java.util.List;
public class OldMatches {
private List<match> matches;
private List<round> rounds;
private List<event> events;
private List<court> courts;
private List<teamOut> teams;
private List<player> players;
}
public class match{
private String event_uuid; //未转化的比赛类型
private String round_id;//未转化的回合id
private String court_id;//未转化的场地id
private String duration;//格式为"2:56"的比赛持续时间
private List<team> teams;
public class team{ //match里的team
private String team_id; //某一方的team_id,用于查找成员信息
private String status; //是否获胜,输的一方没有这个属性
private List<scoreResult> score ;
public class scoreResult{
private int set;
private String game;//单局分数
}
}
}
public class round{
private String uuid; //比赛回合的uuid
private String name;//比赛回合名字
}
public class event{
private String uuid;
private String name;//比赛类型名字
}
public class court{
private String uuid;
private String name;//比赛场地名字
}
public class teamOut{
private String uuid;
List<String> players; //存储运动员id的字符串数组
}
public class player{
private String uuid;
private String short_name;
private Nationality nationality;
public class Nationality{
String name;
}
}
}
新数据类
package org.example;
import java.util.List;
public class NewMatches {
private List<match> matches;
public class match{
private String event_type;
private String round_type;
private String court;
private String duration;
private List<team> teams;
public class team{
private List<player> players;
private List<aSingleScore> score;
private boolean is_winner; //是否是赢家
public class player{
private String short_name;
private String nationality;
}
public class aSingleScore{
private int set;
private String game;//单局分数
}
}
}
}
生成新的Json数据代码
package org.example;
import com.google.gson.Gson;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
//创建文件
// generateJsonFile("0129.json");
Gson gson = new Gson();
OldMatches oldMatches = getOldMatches();
List<OldMatches.player> playerList = oldMatches.getPlayers();
//获取Matches对象中的所有相关列表属性...
List<OldMatches.match> oldMatchList = oldMatches.getMatches();
List<OldMatches.court> courtList = oldMatches.getCourts();
List<OldMatches.event> eventList = oldMatches.getEvents();
List<OldMatches.round> roundList = oldMatches.getRounds();
List<OldMatches.teamOut> teamOutList = oldMatches.getTeams(); //与match数组并列的外部team列表
//遍历每一场match,将每一个oldMatch封装成对应的newMatch,存储在newMatch列表中
List<NewMatches.match> matches = new ArrayList<>();
for(OldMatches.match singleMatch: oldMatchList){
//获得match中的参数
String event_uuid = singleMatch.getEvent_uuid();
String round_id = singleMatch.getRound_id();
String court_id = singleMatch.getCourt_id();
String duration = singleMatch.getDuration();
//遍历其他List找到uuid对应的name属性
String event_type = getEventName(event_uuid, eventList);
String round_type = getRoundName(round_id, roundList);
String court = getCourtName(court_id,courtList);
//遍历 单个match中teams列表,将每个team封装成newTeam, 再得到newTeamList
List<OldMatches.match.team> oldTeams = singleMatch.getTeams();
List<NewMatches.match.team> teams = new ArrayList<>();
for(OldMatches.match.team oldTeam : oldTeams){
NewMatches.match.team singleNewTeam = getSingleNewTeam(oldTeam, teamOutList, playerList);
teams.add(singleNewTeam);
}
//将四个属性封装成新match
NewMatches.match newMatch = new NewMatches().new match();
newMatch.setEvent_type(event_type);
newMatch.setRound_type(round_type);
newMatch.setCourt(court);
newMatch.setDuration(duration);
newMatch.setTeams(teams);
matches.add(newMatch);
}
NewMatches newMatches = new NewMatches();
newMatches.setMatchList(matches);
String result = gson.toJson(newMatches);
// System.out.println(result);
generateJsonFile("Day14.json", result);
}
/**
* 功能:根据单个oldteam,封装单个新的team
*/
public static NewMatches.match.team getSingleNewTeam(OldMatches.match.team team, List<OldMatches.teamOut> teams,List<OldMatches.player> oldPlayers){
}
/**
* 对于每个oldMatch中的teams中的team获取 ,新的score列表
*/
public static List< NewMatches.match.team.aSingleScore> getNewScores(OldMatches.match.team team){
}
/**
* 功能:根据单个match中teams数组的单个team的team_id找到对应的新类球员列表
* @param team_id
* @param teams
* @param players
* @return
*/
public static List<NewMatches.match.team.player> getNewTeamsPlayers(String team_id, List<OldMatches.teamOut> teams, List<OldMatches.player> players){ }
/**
* 功能:根据给定的输出路径生成文件
* @param outputPath
* @throws IOException
*/
public static void generateJsonFile(String outputPath, String result) throws IOException { }
/**
* 功能:获取某一天比赛的集合
*/
public static OldMatches getOldMatches() throws FileNotFoundException, UnsupportedEncodingException { }
/**
* 功能:根据某场match的event_uuid得到对应的event_name
* @param event_uuid
* @return
*/
public static String getEventName( String event_uuid, List<OldMatches.event> eventList){ }
/**
* 功能:根据某场match的court_id得到对应的court_name
* @param court_id
* @param courtList
* @return
*/
public static String getCourtName(String court_id, List<OldMatches.court> courtList){
}
/**
* 功能:根据某场match的round_id得到对应的round_name
*
* @param round_id
* @param roundList
* @return
*/
public static String getRoundName(String round_id, List<OldMatches.round> roundList){
}
}
得到每日赛程部分需要的数据
{
"matches": [{
"event_type": "Women's Doubles",
"round_type": "Final",
"court": "Rod Laver Arena",
"duration": "1:29",
"teams": [{
"players": [{
"short_name": "B. Krejcikova",
"nationality": "Czech Republic"
}, {
"short_name": "K. Siniakova",
"nationality": "Czech Republic"
}],
"score": [{
"set": 1,
"game": "6"
}, {
"set": 2,
"game": "6"
}],
"is_winner": true
}, {
"players": [{
"short_name": "S. Aoyama",
"nationality": "Japan"
}, {
"short_name": "E. Shibahara",
"nationality": "Japan"
}],
"score": [{
"set": 1,
"game": "4"
}, {
"set": 2,
"game": "3"
}],
"is_winner": false
}]
}, {
"event_type": "Men's Singles",
"round_type": "Final",
"court": "Rod Laver Arena",
"duration": "2:56",
"teams": [{
"players": [{
"short_name": "S. Tsitsipas",
"nationality": "Greece"
}],
"score": [{
"set": 1,
"game": "3"
}, {
"set": 2,
"game": "6"
}, {
"set": 3,
"game": "6"
}],
"is_winner": false
}, {
"players": [{
"short_name": "N. Djokovic",
"nationality": "Serbia"
}],
"score": [{
"set": 1,
"game": "6"
}, {
"set": 2,
"game": "7"
}, {
"set": 3,
"game": "7"
}],
"is_winner": true
}]
}]
}


郑朋友的心路历程和收获
这次作业主要学习了前端技能,对前端工作有了更全面的认识,写前端代码不是简单的把组件添加到页面里,其中各种复杂的动画,交互事件,数据渲染和后端代码一样需要细致的逻辑(因为一直学习的都是后端技术,对前端技术不是很了解)。此外还学习了网站的部署,看到一个属于自己的可以访问的网站,心情很奇妙(虽然这不是什么高深的东西)。
终于了解前端的所谓的框架是什么了。前端框架,比如BootStrap, ElementUI,
Layui等自带了大量可复用的组件,这些组件封装了行为层结构层表现层的代码,可以非常方便地用于网页实现;此外还有vue这样的js框架,提供了一套开发规则,大大提高开发效率。真是前端工程师的好帮手。
因为时间精力有限,这次作业选择了纯前端方式完成,没有涉及到前后端交互。这一块知识会在今后的学习中补上。
林朋友的心路历程和收获
这次的作业工作量是巨大的,在短短的一周时间内要掌握的东西实在是太多了,主要是这些内容在之前的课程中几乎是没有涉及的。在我有一定前端基础的情况下,编写代码还是要花费很多时间。毕竟是一个完完整整网站的开发,在短时间内学会技能并且将其实现谈何容易。
这一周的学习可以说是“暴风吸入”,每天都在各种博客中试图搜索有用的信息。但是大多数博客都是水出来的,找起资料相当的麻烦,时常一个路由问题就要找半个多小时。所以几乎所有的课余时间都用在了搜集资料 、学习技术、代码实现上。
这是我第一次完全使用vue开发项目,也是对自己的一种挑战。因为前面有前端的基础,所以上手比较快。虽然说代码量减少,但是思考的时间是不会减少的,在思考拼接模板字符串的逻辑时,我花费了好多时间去设计该如何实现。
虽然工作量很大,实现起来很不容易,但是我从中学到了很多。我觉得最重要的应该就是抗压能力。在上课和这个作业中平衡,还要保证充足的睡眠。其次是和队友的合作能力,刚开始合作的时候会有些不适应,但后面慢慢磨合好了,效率也高了。还有就是技术方面,这次作业之后我也会进行整理反思,接下来的目标是深入学习vue,为后面的团队作业打好基础。