310
社区成员




这个作业属于哪个课程 | 软件工程实践-2023学年-W班 |
---|---|
这个作业要求在哪里 | 结对第二次作业——编程实现 |
结对学号 | <222100125,222100123> |
这个作业的目标 | ①编码实现原型设计 ②熟悉Git合作 |
其他参考文献 | 《Vue.js中文文档》 |
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 30 |
• Estimate | • 估计这个任务需要多少时间 | 40 | 30 |
Development | 开发 | 1640 | 1900 |
• Analysis | • 需求分析 (包括学习新技术) | 200 | 250 |
• Design Spec | • 生成设计文档 | 60 | 60 |
• Design Review | • 设计复审 | 30 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
• Design | • 具体设计 | 60 | 70 |
• Coding | • 具体编码 | 1080 | 1260 |
• Code Review | • 代码复审 | 60 | 70 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 50 | 45 |
• Size Measurement | • 计算工作量 | 10 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 1730 | 1975 |
主页提供路由跳转,显示比赛照片等内容
每日赛程使用折叠面板展示,根据接受到的响应数据数目动态生成组件,点击可展开显示参赛运动员信息,点击显示详情功能可跳转至详细赛况,点击上方按钮可切换时区
详细赛况使用折叠面板展示,根据接受到的响应数据数目动态生成组件,点击可展开显示比赛各阶段的结果,可以通过点击相应的按钮切换显示的比赛阶段,当前显示的比赛阶段的按钮会有不同的显示效果提示
比赛数据使用echarts图表库展示,包含各国运动员人数,各项目参赛人数,各国奖牌总数和各国金银铜奖牌数量
- 在本次项目设计过程中,我们针对用什么方式实现这次作业所提到的的功能,数据应该如何设计,前后端数据的传输过程等一系列问题的讨论使用了微信聊天的方式进行,以下是讨论过程中的部分截图:
- 将类分成存放处理数据的service类,存储数据的实体类和返回数据的Controller类。
- 把返回每日赛程和对应运动员信息的方法、返回比赛对应具体信息的方法、返回奖牌个数的方法、返回全体运动员信息的方法放在对应的Controller类中。
- 将处理数据比赛信息的方法放在对应的service类中
- 数据使用的是静态json文件,json文件存放在resources的目录下进行访问。
- 使用Vue3框架,并借助UI库ElementPlus进行页面搭建;
- 采用单页面,页面分为三个部分,页头导航,页面主体,页尾,页头导航和页尾所有视图共享;
- 通过路由改变页面主体的视图,实现功能切换;
- 在数据展示界面根据接收到的数据数量动态生成组件;
- 在接收数据时增加加载动画,减少卡顿感,优化用户体验;
- 考虑到部分选手的照片缺失,对这部分进行默认替换处理;
- 奖牌统计使用echarts图表库,让展示更直观且美观;
- 有关嵌套的版块暂时以静态形式嵌入源码中。
①在第一次实现前后端数据传输的时候,遇到了跨域的情况。
- 解决方法:在后端代码中实现了WebMvcConfigurer接口中的addCorsMappings方法,并加上了@Configuration注释。
②在解决跨域的问题之后发现,传过来的数据是空的,不是期待中的json文件数据。
- 解决方法:实现在后端代码中实现的类没有打上@JsonSerialize注释,也没有对类中存在的变量实现get方法,因此打上注释并实现get方法就有json数据了。
③在部署前端项目时,Nginx服务器老是启动不了,显示端口被占用
- 在输入查看Ngnix服务器的文件路径时,发现有自己不小心下载了两个Nginx,因此在删除其中一个后正常部署了。
④在本地访问resources文件夹下的数据正常,部署到服务器上后发现访问不到
- 首先是把访问的那个路径文件分隔符从/改成File.separator,然后发现在Linux上是区分文件大小写的,因此在将文件名中的大小写区分好后就可以在服务器上运行。
⑤在本地解决完跨域问题后,发现在服务器上依旧出现了跨域问题
- 把原先在本地的解决方法改为在所有Controller类中添加上@CrossOrigin注释即可。
- Game类:
@JsonSerialize
public class Game {
String gameName;
List<GameMessage> gameMessages;
···//这里省略基本方法
}
- GameMessage类
@JsonSerialize
public class GameMessage {
String gameType;
String gameData;
String gameTime;
List<PlayerMessage> playerMessageList;
...//这里省略基本方法
}
- GameSchedule类
@JsonSerialize
public class GameSchedule {
String gameName;
GameMessage gameMessage;
...//这里省略基本方法
}
- PlayerMessage类
@JsonSerialize
public class PlayerMessage {
String fullName;
String country;
int[] age;
String preliminaryRank;
String semifinalRank;
String finalRank;
double preliminaryTotalScore;
double semifinalTotalScore;
double finalTotalScore;
double pointBehind;
...//这里省略基本方法
}
- Medals
@JsonSerialize
public class Medals {
String countryName;
int goldCount;
int silverCount;
int bronzeCount;
int totalCount
public void addGold() {
goldCount++;
}
public void addSilver() {
silverCount++;
}
public void addBronze() {
bronzeCount++;
}
public void addTotal() {
totalCount++;
}
// 按照金牌数量降序,金牌数量一样按银牌数量,银牌数量一样按铜牌
public static Comparator<Medals> CountComparator = new Comparator<Medals>() {
@Override
public int compare(Medals medals1, Medals medals2) {
if (medals1.goldCount != medals2.goldCount) {
return medals2.goldCount - medals1.goldCount;
} else if (medals1.silverCount != medals2.silverCount) {
return medals2.silverCount - medals2.silverCount;
} else {
return medals1.bronzeCount - medals1.bronzeCount;
}
}
};
}
...//这里省略基本方法
- GameService类中:解析各场比赛的数据,获得比赛的信息和运动员信息的方法,得到一个Game类
public class GameService {
/*功 能:解析比赛信息的json*/
/*入口参数: 对应比赛文件字符串*/
/*返 回:比赛中运动员信息列表*/
public Game ParseGameDetail(String gameJSON) throws JSONException {
JSONObject jsonObject = new JSONObject(gameJSON);
JSONArray messageArray = jsonObject.getJSONArray("Heats");
List<GameMessage> gameMessages = new ArrayList<>();
for (int i = messageArray.length() - 1; i >= 0; i--) {
List<PlayerMessage> playerMessages = new ArrayList<>();
GameMessage gameMessage = new GameMessage();
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat outputFormat = new SimpleDateFormat("EEEE d'st' MMMM");
// 日期转换
Date date = null;
try {
date = inputFormat.parse(jsonObject.getString("DisciplineStartDate"));
} catch (ParseException e) {
e.printStackTrace();
}
gameMessage.setGameData(outputFormat.format(date));
// 处理比赛中运动员信息
JSONObject gameObject = messageArray.getJSONObject(i);
//每个运动员的得分
JSONArray gameArray = gameObject.getJSONArray("Results");
//取出比赛是final、Semifinal还是Preliminary
String gameType = gameObject.getString("PhaseName");
gameMessage.setGameType(gameType);
gameMessage.setGameTime(gameObject.getString("EndTime"));
int nowPlayerIndex = 0;
//从第一次比赛开始读(Results)
for (int j = 0; j < gameArray.length(); j++) {
JSONObject playerMessageObject = gameArray.getJSONObject(j);
String fullName = playerMessageObject.getString("FullName");
String[] name = fullName.split("/");
PlayerMessage playerMessage = new PlayerMessage();
playerMessage.setCountry(playerMessageObject.getString("NAT"));
if (!playerMessageObject.get("PointsBehind").toString().equals("null")) {
playerMessage.setPointBehind(Double.parseDouble(playerMessageObject.get("PointsBehind").toString()));
} else {
playerMessage.setPointBehind(0.0);
}
//判断是否为单人项目
if (name.length == 1) {
playerMessage.setFullName(playerMessageObject.getString("FullName"));
playerMessage.setAge(playerMessageObject.getInt("AthleteResultAge"));
} else {
String player1LastName = name[0].trim();
String player2LastName = name[1].trim();
playerMessage.setFullName(player1LastName, player2LastName);
JSONArray competitors = playerMessageObject.getJSONArray("Competitors");
playerMessage.setAge(competitors.getJSONObject(0).getInt("AthleteResultAge"), competitors.getJSONObject(1).getInt("AthleteResultAge"));
}
playerMessages.add(playerMessage);
//找出当前取出的运动员在队列中的下标
for (PlayerMessage playerMessage1 : playerMessages) {
if (name.length == 1) {
if (playerMessage1.getFullName().equals(playerMessageObject.getString("FullName")))
nowPlayerIndex = playerMessages.indexOf(playerMessage1);
} else {
String player1LastName = name[0].trim();
String player2LastName = name[1].trim();
String playerFullName = "";
playerFullName = player1LastName + " & " + player2LastName;
if (playerMessage1.getFullName().equals(playerFullName)) {
nowPlayerIndex = playerMessages.indexOf(playerMessage1);
}
}
}
playerMessage = playerMessages.get(nowPlayerIndex);
//判断比赛类型,存入相关信息
if (gameType.equals("Preliminaries")) {
playerMessage.setPreliminaryTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
playerMessage.setPreliminaryRank(Integer.toString(playerMessageObject.getInt("Rank")));
} else if (gameType.equals("Semifinals")) {
playerMessage.setSemifinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
playerMessage.setSemifinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
} else {
playerMessage.setFinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
playerMessage.setFinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
}
playerMessages.set(nowPlayerIndex, playerMessage);
}
gameMessage.setPlayerMessageList(playerMessages);
gameMessages.add(gameMessage);
}
Game game = new Game(jsonObject.getString("DisciplineName"), gameMessages);
return game;
}
}
- MessageController类:具有返回每日赛程和运动员信息的方法、返回具体比赛具体信息的方法、返回奖牌个数的方法、全体运动员信息的方法和处理json文件的方法,返回给前端用于展示
@CrossOrigin
@RestController
public class MessageController {
GameService gameService = new GameService();
private final ResourceLoader resourceLoader;
public MessageController(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/*功 能:用于返回每日赛程信息和参赛选手*/
/*入口参数:无*/
/*返 回:对应日期和比赛信息*/
@GetMapping("/schedule")
public LinkedHashMap<String, List<GameSchedule>> GetGameMessage() {
LinkedHashMap<String, List<GameSchedule>> dailyGame = new LinkedHashMap<>();
List<GameSchedule> Thursday = new ArrayList<>();
List<GameSchedule> Friday = new ArrayList<>();
List<GameSchedule> Saturday = new ArrayList<>();
List<GameSchedule> Sunday = new ArrayList<>();
Game gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 1m Springboard"));
Game gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 1m Springboard"));
Thursday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(0)));
Thursday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(0)));
Thursday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(1)));
Thursday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(1)));
Thursday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")).getGameMessages().get(0)));
dailyGame.put("Thursday 18th January", Thursday);
gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 10m Platform"));
gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 3m Springboard"));
for (int i = 0; i <= 2; i++) {
Friday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(i)));
Friday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(i)));
}
dailyGame.put("Friday 19th January", Friday);
gameMessagesw = gameService.ParseGameDetail(ReadFile("Women 3m Springboard"));
for (int i = 0; i <= 2; i++) {
Saturday.add(new GameSchedule(gameMessagesw.getGameName(), gameMessagesw.getGameMessages().get(i)));
}
Saturday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameMessages().get(0)));
Saturday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")).getGameMessages().get(0)));
dailyGame.put("Saturday 20th January", Saturday);
gameMessagesm = gameService.ParseGameDetail(ReadFile("Men 10m Platform"));
for (int i = 0; i < 2; i++) {
Sunday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(i)));
}
Sunday.add(new GameSchedule(gameService.ParseGameDetail(ReadFile("Women 3m Synchronised")).getGameName(), gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")).getGameMessages().get(0)));
Sunday.add(new GameSchedule(gameMessagesm.getGameName(), gameMessagesm.getGameMessages().get(2)));
dailyGame.put("Sunday 21st January", Sunday);
return dailyGame;
}
/*功 能:用于返回详细赛程*/
/*入口参数:无*/
/*返 回:比赛信息*/
@GetMapping("/detail")
public List<Game> GetGameDetail() throws JSONException {
List<Game> games = new ArrayList<>();
games.add(gameService.ParseGameDetail(ReadFile("Women 1m Springboard")));
games.add(gameService.ParseGameDetail(ReadFile("Women 3m Springboard")));
games.add(gameService.ParseGameDetail(ReadFile("Women 10m Platform")));
games.add(gameService.ParseGameDetail(ReadFile("Women 3m Synchronised")));
games.add(gameService.ParseGameDetail(ReadFile("Women 10m Synchronised")));
games.add(gameService.ParseGameDetail(ReadFile("Men 1m Springboard")));
games.add(gameService.ParseGameDetail(ReadFile("Men 3m Springboard")));
games.add(gameService.ParseGameDetail(ReadFile("Men 10m Platform")));
games.add(gameService.ParseGameDetail(ReadFile("Men 3m Synchronised")));
games.add(gameService.ParseGameDetail(ReadFile("Men 10m Synchronised")));
return games;
}
/*功 能:用于计算奖牌数量*/
/*入口参数:无*/
/*返 回:奖牌信息*/
@GetMapping("/g")
public List<Medals> GetMedalsCount() throws JSONException {
Map<String, Medals> medalsMap = new HashMap<>();
List<Game> games = GetGameDetail();
for (Game game : games) {
for (GameMessage message : game.getGameMessages()) {
if (message.getGameType().equals("Finals")) {
List<PlayerMessage> playerMessages = message.getPlayerMessageList();
for (int i = 0; i < 3; i++) {
Medals medals;
if (!medalsMap.containsKey(playerMessages.get(i).getCountry())) {
medals = new Medals();
} else {
medals = medalsMap.get(playerMessages.get(i).getCountry());
}
if (i == 0) {
medals.addGold();
} else if (i == 1) {
medals.addSilver();
} else {
medals.addBronze();
}
medals.addTotal();
medals.setCountryName(playerMessages.get(i).getCountry());
medalsMap.put(medals.getCountryName(), medals);
}
}
}
}
List<Medals> medals = new ArrayList<>();
medalsMap.forEach((key, value) -> medals.add(value));
Collections.sort(medals, Medals.CountComparator);
return medals;
}
/*功 能:运动员信息*/
/*入口参数:无*/
/*返 回:运动员json信息*/
@GetMapping("/player")
public String GetPlayerMessage(){
return ReadFile("Player");
}
/*功 能:读json文件*/
/*入口参数:返回json文件为字符串*/
/*返 回:文件名*/
public String ReadFile(String fileName) {
Resource resource = resourceLoader.getResource("classpath:game" + File.separator + fileName + ".json");
StringBuilder str = null;
try {
InputStream inputStream = resource.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
str = new StringBuilder("");
String line;
while ((line = reader.readLine()) != null) {
str.append(line);
}
reader.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return str.toString();
}
}
- urlStore,用于储存服务器地址,便于修改
import { defineStore } from 'pinia'
export const urlStore = defineStore('url', {
actions: {},
state() {
return {
baseUrl: 'http://118.178.124.104',
backendPort: '8083',
}
},
getters: {
url: (state): string => state.baseUrl + ':' + state.backendPort,
}
})
- ts数据限制接口,保证从服务器fetch到的数据的正确性
interface PlayerMessageList
{
age: Array<number>;
country: string;
finalRank: string;
finalTotalScore: number;
fullName: string;
pointBehind: number;
preliminaryRank: string;
preliminaryTotalScore: number;
semifinalRank: string;
semifinalTotalScore: number;
}
interface GameMessage
{
gameDate: string;
gameTime: string;
gameType: string;
playerMessageList: Array<PlayerMessageList>;
}
export interface MatchDataList
{
gameName: string;
gameMessages: Array<GameMessage>;
}
- 每日赛程数据视图
<el-timeline-item v-for="(date, index) in tableData " :key="index" :timestamp="index" placement="top"
:hollow="true" type="primary" size="large">
<el-collapse v-model="activeNames" class="listview">
<el-collapse-item v-for="(match, index) in date " :key="index" class="listitem">
<template #title>
<div class="title-bar">
<label v-if="timeArea === 'your'"
class="title">{{ match.gameMessage.gameTime.substring(0, 5) }}
PM</label>
<label v-else-if="timeArea === 'local'"
class="title">{{ getLocalTime(match.gameMessage.gameTime) }}</label>
<el-divider direction="vertical" />
<img src="/dive.png" class="logo">
<h3 class="title">{{ match.gameName }}</h3>
<h3 style="font-weight: bold; font-size:36px; margin:0 10px; color:lightgray">·
</h3>
<h3 v-if="match.gameMessage.gameType != 'Finals'" class="type-title-normal">
{{ match.gameMessage.gameType }}
</h3>
<h3 v-else class="type-title-final">{{ match.gameMessage.gameType }}</h3>
<el-button type="primary" plain style="position: absolute; left:1050px;"
@click="goDetail()">查看详情</el-button>
</div>
</template>
<template #default>
<el-divider />
<div class="center">
<label class="title">参赛选手列表</label>
</div>
<el-table :data="match.gameMessage.playerMessageList" style="width:100%">
<el-table-column prop="country" label="Country">
<template v-slot="scope">
<div class="cell-container">
<img :src="getFlagPath(scope.row.country)" class="table-icon">
<span>{{ scope.row.country }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="athlete" label="Athlete" style="position: relative;">
<template v-slot="scope">
<div class="cell-container">
<img :src="getPlayerPath(scope.row.fullName)" class="table-icon"
style="position: absolute;left:100px;" @error="handleImageError" />
<span v-if="match.gameMessage.playerMessageList[0].age[1] === 0"
style="position: absolute;left:150px;">{{ scope.row.fullName }}</span>
<span v-else style="position: absolute;left:150px;">
<div>
<div>
{{ cutName(nameSplit(scope.row.fullName)[0]) }}
</div>
<div>
{{ cutName(nameSplit(scope.row.fullName)[1]) }}
</div>
</div>
</span>
</div>
</template>
</el-table-column>
<el-table-column v-if="match.gameMessage.playerMessageList[0].age[1] === 0"
prop="age[0]" label="Age" />
<el-table-column v-else label="Age">
<template #default="{ row }">
<div>
<div style="font-size: 12px;">
{{ row.age[0] }}
</div>
<div style="font-size: 12px;">
{{ row.age[1] }}
</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-collapse-item>
</el-collapse>
</el-timeline-item>
- 详细赛况数据视图
<el-table :data="match.gameMessages[dataIndex[index]].playerMessageList" style="width: 100%">
<el-table-column v-if="match.gameMessages[dataIndex[index]].gameType === 'Finals'"
prop="finalRank" label="Overall Rank" width="180" />
<el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Semifinals'"
prop="semifinalRank" label="Overall Rank" width="180" />
<el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Preliminaries'"
prop="preliminaryRank" label="Overall Rank" width="180" />
<el-table-column prop="country" label="Country" width="180">
<template v-slot="scope">
<div class="cell-container">
<img :src="getFlagPath(scope.row.country)" class="table-icon">
<span>{{ scope.row.country }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="athlete" label="Athlete" style="position: relative;">
<template v-slot="scope">
<div class="cell-container">
<img :src="getPlayerPath(scope.row.fullName)" class="table-icon"
style="position: absolute;left:50px;" @error="handleImageError">
<span v-if="match.gameMessages[dataIndex[index]].playerMessageList[0].age[1] === 0"
style="position: absolute;left:100px;">{{ scope.row.fullName }}</span>
<span v-else style="position: absolute;left:100px;font-size: 12px;">
<div>
<div>
{{ cutName(nameSplit(scope.row.fullName)[0]) }}
</div>
<div>
{{ cutName(nameSplit(scope.row.fullName)[1]) }}
</div>
</div>
</span>
</div>
</template>
</el-table-column>
<el-table-column v-if="match.gameMessages[dataIndex[index]].playerMessageList[0].age[1] === 0"
prop="age[0]" label="Age" width="180" />
<el-table-column v-else label="Age" width="180">
<template #default="{ row }">
<div>
<div style="font-size: 12px;">
{{ row.age[0] }}
</div>
<div style="font-size: 12px;">
{{ row.age[1] }}
</div>
</div>
</template>
</el-table-column>
<el-table-column v-if="match.gameMessages[dataIndex[index]].gameType === 'Finals'"
prop="finalTotalScore" label="Points" width="180" />
<el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Semifinals'"
prop="semifinalTotalScore" label="Points" width="180" />
<el-table-column v-else-if="match.gameMessages[dataIndex[index]].gameType === 'Preliminaries'"
prop="preliminaryTotalScore" label="Points" width="180" />
<el-table-column prop="pointBehind" label="Pts Behind" />
</el-table>
- echarts配置
const totalChart = echarts.init(totalMedalChartContainer.value);
const optionTotal = {
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center'
},
series: [
{
name: '奖牌总数',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 10
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: 40,
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: totalMedal.value,
}
]
};
totalChart.setOption(optionTotal);
const medalChart = echarts.init(medalChartContainer.value);
const option = {
color: ['#F5DE0D', '#BCBDB5', '#E2862A'],
legend: {},
tooltip: {},
dataset: {
dimensions: ['name', '金牌', '银牌', '铜牌'],
source: medalCount.value,
},
xAxis: {
type: 'category',
data: medalCount.value.map(item => item.name),
},
yAxis: {
type: 'value',
},
series: [{ type: 'bar' }, { type: 'bar' }, { type: 'bar' }]
};
medalChart.setOption(option);
- 222100123 姚磊:在这次作业中,第一次学习使用springboot框架,在这次学习和使用中,遇到了各种各样的问题,好在和队友一同解决了,也使我在这次学习中信心大增。应该是一次次的解决出现的问题后渐渐有信心,也有可能是告诉自己问题总能解决,这次的作业中对于以往遇到问题就心浮气躁,产生放弃念头的我,在本次作业中,罕见的没有出现这种情况。
- 222100125 钱元城:这段时间我正在学习Vue框架,这次作业刚好就能用上了,在学习时我觉得,Vue框架看起来也挺简单嘛,但是真正实践起来才发现,哪有那么容易哇!跌跌撞撞了几天,也总算是把这次的作业完成了,在完成的过程中,我才知道我还远远没有领会到Vue框架的精髓,学习切忌急于求成,并且对于我们这个专业,我认为实践一定是大于理论的,只有自己真正动手去做去感悟了,才能体会到其中的巧妙的思想,这就是我在这段时间的实践中得到的最大的收获。
- 222100123 姚磊 对 222100125 钱元城:已经是数不清多少次合作了,每次的合作都能让我感受到和他合作真好,在遇到问题需要解决,需要抱怨的时候,他总能给我帮助。而且他的知识面比较广,经常能给我一些惊喜。在对比我老是找他抱怨,他就显得非常的安静,给人一种特别踏实的感觉。
- 222100125 钱元城 对 222100123 姚磊:怎么又是你,肚子里的墨水都快全部用来评价你了,你还是一如既往的靠谱,因为我个人的原因我在开发初期耽搁了一段时间,即使你自己也很忙,但是在这段时间里你还是认真完成了任务,你的行动力还是那么强,可惜最后我还是没能来得及把当时的想法全部实现,这也算是一个遗憾吧,在这里和你说声抱歉,下次也要一起加油呀。
关于我们的界面中,是否可以用一个列表或者更有趣的时间列表来显示“世界游泳运动与奥林匹克运动”呢。如果是纯搜集的文本粘贴会大大降低用户的使用体验和可读性。
整体较完整,使用过程中对于赛事通过鼠标滑动寻找,缺少必要的分类,用户体验较差。