108
社区成员
这个作业属于哪个课程 | https://bbs.csdn.net/topics/619333839 |
---|---|
这个作业要求在哪里 | 结对第二次作业——编程实现 |
结对学号 | 222200134、222200201 |
这个作业的目标 | 一个功能完善、用户体验优秀的2024年巴黎奥运会赛况展示平台 |
其他参考文献 | 无 |
代码规范文档地址:
Style Guide | Vue.js
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
•Estimate | 估计这个任务需要多少时间 | 60 | 60 |
Development | 开发 | 1590 | 1370 |
•Analysis | 需求分析(包括学习新技术) | 300 | 180 |
•Design Spec | 生成设计文档 | 60 | 60 |
•Design Review | 设计复审 | 30 | 20 |
•Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 60 |
•Design | 具体设计 | 180 | 120 |
•Coding | 具体编码 | 600 | 720 |
•Code Review | 代码复审 | 60 | 30 |
•Test | 测试(自我测试,修改代码,提交修改) | 300 | 180 |
Reporting | 报告 | 240 | 180 |
•Test Report | 测试报告 | 60 | 30 |
•Size Measurement | 计算工作量 | 30 | 30 |
•Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 150 | 120 |
Sum Up | 合计 | 1890 | 1610 |
222200134_222200201_Paris_Olympics
展示巴黎奥运会logo和标题信息,提供奖牌榜、每日赛程、更多信息的功能入口,采用一些动效和gif文件组成。
显示所有国家地区的奖牌情况,上下滚动查看,制作了一些高亮事件。
在顶端使用下拉列表提供选择日期查看赛事功能,可以一次性查看所有赛程,不过会导致崩溃。
赛事显示方面同样制作了高亮动效,点击查看详情可跳转到Detail页面。
通过点击赛程页面的查看详情按钮跳转,提供了分组查看,点击某一个赛事卡可以在页面底部新建一个赛事卡体现该场比赛。
对阵图页面通过详情页面顶端分组最右边的按钮GoToVst进入,对阵图提供了四分之一决赛后的比赛对阵情况,通过高亮体现晋级情况,当鼠标移到一个国家上时,会体现其晋级之路。
更多信息页面提供了巴黎奥运会的相关信息及巴黎奥运会相关网址
项目结构图在模块6设计与实现中体现
设定定期交流时间,评估项目进度和遇到的问题。
展示了该项目在Vue框架下的组件:
前端开发:
使用HTML, CSS, JavaScript等技术实现界面。
使用框架Vue提高开发效率。
主页设计与实现
奖牌榜模块
每日赛程模块
详细赛程模块
对阵图的round-box之间的连线需要记录位置进行线条绘制,但我们尝试了许多方法,只能够做到显示垂直方向的线条。这大概与我们将该页分为三个column有关。所以我们放弃线条绘制,在讨论许久后,我们选择通过采用相同国家高亮设计体现晋级,解决了线条难画的问题。
主页的设计友一个会标GIF和三个按钮组成,由页面路由实现跳转,实现方式较简单。Home.vue展示:
<template>
<div class="home">
<header>
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" @click="goToHome"/>
</header>
<main>
<div class="button-container">
<button class="btn" @click="goToMedals">奖牌榜</button>
<button class="btn" @click="goToSchedule">赛程表</button>
</div>
<button class="learn-more-btn" @click="goToMoreInf">了解更多</button>
</main>
</div>
</template>
<script>
export default {
name: 'Home',
methods: {
goToMedals() {
this.$router.push('/MedalBoard');
},
goToSchedule() {
// 这里可以添加跳转到赛程表的逻辑
this.$router.push('/Schedule');
},
goToDetail(){
this.$router.push('/Detail')
},
goToVst(){
this.$router.push('/Vst')
},
goToMoreInf() {
this.$router.push('/MoreInf')
// alert('了解更多信息');
},
goToHome() {
this.$router.push('/');
}
}
};
</script>
<style scoped>
.home {
text-align: center;
background-color: #262626; /* 暗色背景 */
color: white;
padding: 40px;
}
header {
margin-bottom: 40px;
}
.olympic-emblem {
width: 680px;
height: auto;
}
.button-container {
display: flex;
justify-content: center;
margin-bottom: 10px;
}
.btn {
display: inline-block;
margin: 0 10px;
margin-bottom: 10px;
padding: 30px 100px;
font-size: 30px;
font-weight: 900;
cursor: pointer;
background-color: #555; /* 按钮背景色 */
color: #D4BE66;
border: 5px solid #D4BE66;
border-radius: 10px;
outline: none;
}
.btn:hover {
border: 5px solid #FFFFFF;
border-radius: 10px;
background-color: #131313; /* 背景颜色 */
color: #FFF;
}
.learn-more-btn {
display: block;
margin: 10px auto;
padding: 30px 245px;
font-size: 30px;
font-weight: 900;
cursor: pointer;
background-color: #555; /* 了解更多按钮背景色 */
color: #D4BE66;
border: 5px solid #D4BE66;
border-radius: 10px;
outline: none;
}
.learn-more-btn:hover {
border: 5px solid #FFF; /* 边框 */
border-radius: 10px;
background-color: #131313; /* 背景颜色 */
color: #FFF;
}
/* Add more styling as needed */
</style>
奖牌榜部分,我们选择了直接通过表格形式,在css部分创建了.table、.table-cell等对奖牌榜进行style规范。将rank、country、gold、sliver、bronze、total放在table-cell里,再被嵌套在.medal-board里。MedalBoard.vue展示:
<template>
<div class="headerRow">
<header style="
background-color: #262626;
padding: 40px;
">
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" @click="goToHome"/>
</header>
<main>
<div class="medal-board">
<h1 style="background-color: #333;color:#D4BE66;">奖牌榜</h1>
<div class="table">
<div class="table-row table-header">
<div class="table-cell">Rank🏆</div>
<div class="table-cell">Country</div>
<div class="table-cell">Gold🥇</div>
<div class="table-cell">Silver🥈</div>
<div class="table-cell">Bronze🥉</div>
<div class="table-cell">Total🎖🎖🎖</div>
</div>
<div v-for="country in countries" :key="country.code" class="table-row">
<div class="table-cell">{{ country.rank }}</div>
<div class="table-cell">
<img :src="getFlagUrl(country.code)" alt="Flag" class="flag" />
<span style="font-size: small;font-style: italic;">{{ country.name }}</span>
</div>
<div class="table-cell">{{ country.gold }}</div>
<div class="table-cell">{{ country.silver }}</div>
<div class="table-cell">{{ country.bronze }}</div>
<div class="table-cell">{{ country.total }}</div>
</div>
</div>
</div>
</main>
</div>
</template>
<script>
export default {
name: 'MedalBoard',
data() {
return {
countries: []
};
},
created() {
this.fetchMedalData();
},
methods: {
async fetchMedalData() {
try {
// Request the file from the server's static directory
const response = await fetch('/static/rank.txt');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text();
this.countries = this.parseMedalData(data);
} catch (error) {
console.error('Error fetching medal data:', error);
}
},
parseMedalData(data) {
// Split the text data by lines, then map each line to an object
return data.trim().split('\n').slice(0, -1).map(line => {
const parts = line.split('\t');
return {
rank: parseInt(parts[0], 10),
code: parts[1],
name: parts[1],
gold: parseInt(parts[2], 10),
silver: parseInt(parts[3], 10),
bronze: parseInt(parts[4], 10),
total: parseInt(parts[5], 10)
};
});
},
getFlagUrl(code) {
// Construct the URL for the flag image
return `https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/${code}.png`;
},
goToHome() {
this.$router.push('/');
}
}
};
</script>
<style scoped>
.headerRow {
text-align: center;
background-color: #262626;
color: white;
}
.medal-board {
max-width: 50%;
background-color: #333;
margin: auto;
border: 10px solid #D4BE66;
border-radius: 10px;
}
.table {
width: 100%;
border-collapse: collapse;
color: #000000;
}
.table-row {
display: flex;
background-color: #f0f0f0;
border-bottom: 1px solid #ddd;
color:#000000;
}
.table-row:hover {
border: 3px solid #D4BE66;
background-color: #000000; /* 背景颜色 */
color: #FFF;
}
.table-header {
background-color: #d3d3d3;
font-weight: bold;
}
.table-cell {
flex: 1;
padding: 10px;
text-align: center;
}
.flag {
width: 45px;
height: 30px;
margin-right: 10px;
}
</style>
每日赛程组件,总体上我们选择在schedule-container中嵌套even-item。同时我们选择使用VUE自带的下拉组件来对日期进行选择,在项目为足球的even-item中,添加了查看详情的按钮,用于跳转到Detail组件页面。Schedule.vue代码展示:
<template>
<div class="headerRow">
<header style="background-color: #262626; padding: 40px;">
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" @click="goToHome"/>
</header>
<main>
<div class="schedule-container">
<h1 style="color: #000;">奥运会赛程和比赛结果 | 2024年巴黎奥运会</h1>
<!-- 下拉列表选择日期 -->
<select class="selectButton" v-model="selectedDate" @change="filterEvents">
<option value="">全部赛程(选这个电脑会爆炸!)</option>
<option v-for="date in uniqueDates" :key="date" :value="date">
{{ date }}
</option>
</select>
<!-- 显示所选日期的赛程 -->
<div class="event-item"
v-for="event in filteredEvents"
:key="event.id"
@mouseenter="hoverEvent(event.id)"
@mouseleave="hoverEvent(null)"
:class="{ 'highlight': hoveredEventId === event.id }">
<p>{{ event.date }}</p>
<h3>{{ event.time }}</h3>
<h2>{{ event.sport }}</h2>
<p>{{ event.match }}</p>
<p>地点: {{ event.venue }}</p>
<!-- 检查项目是否为足球,并根据结果决定显示哪个按钮 -->
<button v-if="event.sport === '足球'" @click="viewResults(event.id)">查看结果</button>
</div>
</div>
</main>
</div>
</template>
<script>
export default {
name: 'Schedule',
data() {
return {
events: [],
selectedDate: '7月24日', // 默认选择的日期
filteredEvents: [],
hoveredEventId: null // 新增属性,用于存储鼠标悬停的事件ID
};
},
created() {
this.fetchEvents();
this.filterEvents(); // 默认过滤事件
},
methods: {
fetchEvents() {
fetch('/static/matchs.txt')
.then(response => response.text())
.then(data => {
const lines = data.trim().split('\n');
this.events = lines.map((line, index) => {
const parts = line.split('\t');
return {
id: index,
date: parts[0],
time: parts[1],
sport: parts[2],
match: parts[3],
venue: parts[4]
};
});
this.filterEvents(); // 重新过滤事件
})
.catch(error => console.error('Error fetching the schedule:', error));
},
filterEvents() {
this.filteredEvents = this.events.filter(event => {
return !this.selectedDate || event.date === this.selectedDate;
});
},
viewResults(eventId) {
this.$router.push({ name: 'Detail', params: { eventId } });
},
goToHome() {
this.$router.push('/');
},
hoverEvent(eventId) {
this.hoveredEventId = eventId; // 更新鼠标悬停的事件ID
}
},
computed: {
uniqueDates() {
const dates = this.events.map(event => event.date);
return [...new Set(dates)].sort(); // 移除重复的日期并排序
}
}
};
</script>
<style scoped>
.headerRow {
text-align: center;
background-color: #262626;
color: white;
}
.schedule-container {
width: 50%;
margin: auto;
padding: 20px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
background-color: #f9f9f9;
border: 10px solid #D4BE66;
border-radius: 10px;
}
.event-item {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
background-color: white;
transition: background-color 0.3s, border-color 0.3s; /* 添加过渡效果 */
color: #000;
border: 5px solid #262626;
border-radius: 10px;
}
.event-item h3 {
color: #333;
}
.event-item p {
color: #666;
}
.selectButton {
margin: auto;
background-color: #262626;
color: #D4BE66;
font-size: 20px;
font-weight: 900;
border: 5px solid #D4BE66;
border-radius: 10px;
padding: 20px 40px;
cursor: pointer;
}
.selectButton:hover{
background-color: #D4BE66;
color: #000;
border: 5px solid #262626;
border-radius: 10px;
}
button {
border: 2px solid #262626;
border-radius: 10px;
background-color: #D4BE66;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
button:hover {
color: #000;
background-color: #FFF;
border: 2px solid #D4BE66;
border-radius: 10px;
}
/* 新增高亮样式 */
.event-item:hover {
border: 5px solid #FFD700; /* 金色边框 */
background-color: #000000; /* 背景颜色 */
color: #FFF;
}
.event-item h2:hover {
color: #FFF;
}
.event-item h3:hover {
color: #FFF;
}
.event-item p:hover {
color: #FFF;
}
</style>
赛程详情组件中,点击ABCDQSF分组按钮可以做到查看具体分组里的赛程,点击GoToVst按钮可以前往对阵图页面。点击具体的赛程可以在页面底端显示赛事结果。Detail.vue的具体代码展示:
<div class="headerRow">
<header style="background-color: #262626; padding: 40px;">
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" @click="goToHome"/>
</header>
<h1 style="font-size: 50px; color: #D4BE66;">Details.</h1>
<main>
<div class="detail-container">
<div class="groups">
<!-- 循环生成组别按钮 -->
<button v-for="group in groups" :key="group" @click="groupSelected(group)">
{{ group }}
</button>
<button style="font-weight: 900;" @click="goToVst">GoToVst</button>
</div>
<div class="matches">
<!-- 循环显示当前选中组别的比赛信息 -->
<div class="match" v-for="match in currentMatches" :key="match.id" @click="DisplayMatch(match)">
<div style="display:flex">
<p style="padding-right: 5%;padding-left: 5%;">日期: {{ match.date }}</p>
<p>时间: {{ match.time }}</p>
</div>
<div style="display:flow-root">
<div style="display:flex">
<img :src="getFlagUrl(match.team1)" alt="Flag" class="flag" style="padding-left: 20%;"/>
<p>{{ match.team1 }}</p>
<p style="padding-left: 20%;">{{ match.score1 }}</p>
</div>
<div style="display:flex">
<img :src="getFlagUrl(match.team2)" alt="Flag" class="flag" style="padding-left: 20%;"/>
<p>{{ match.team2 }}</p>
<p style="padding-left: 20%;">{{ match.score2 }}</p>
</div>
</div>
<div style="text-align: right;"> <p>状态: {{ match.status }}</p></div>
</div>
</div>
<div class="match-long" v-if="selectedMatch">
<div style="display:flex">
<p style="padding-right: 5%;padding-left: 5%;">日期: {{ selectedMatch.date }}</p>
<p>时间: {{ selectedMatch.time }}</p>
</div>
<div style="display:flow-root">
<div style="display:flex">
<img :src="getFlagUrl(selectedMatch.team1)" alt="Flag" class="flag-long" style="padding-left: 20%;"/>
<p>{{ selectedMatch.team1 }}</p>
<p style="padding-left: 20%;">{{ selectedMatch.score1 }}</p>
<p style="padding-left: 1%;padding-right: 1%;">:</p>
<p style="padding-right: 20%;">{{ selectedMatch.score2 }}</p>
<p>{{ selectedMatch.team2 }}</p>
<img :src="getFlagUrl(selectedMatch.team2)" alt="Flag" class="flag-long" style="padding-right: 10%;"/>
</div>
</div>
<div style="text-align: right;"> <p>状态: {{ selectedMatch.status }}</p></div>
</div>
</div>
</main>
</div>
</template>
<script>
export default {
data() {
return {
matches: [],
currentGroup: '',
currentIndex: 0,
matchesPerPage: 5,
selectedMatch: null, // 使用 selectedMatch 来存储被选中的 match 项
};
},
created() {
this.fetchMatches();
},
computed: {
groups() {
// 使用 Set 来获取所有独特的组别
return [...new Set(this.matches.map(match => match.group))];
},
currentMatches() {
// 根据当前选中的组别来过滤比赛,并进行分页
return this.matches
.filter(match => this.currentGroup === '' || match.group === this.currentGroup)
.slice(this.currentIndex * this.matchesPerPage, (this.currentIndex + 1) * this.matchesPerPage);
}
},
methods: {
fetchMatches() {
// 读取 football.txt 文件
fetch('/static/football.txt')
.then(response => response.text())
.then(data => {
const lines = data.trim().split('\n');
this.matches = lines.map(line => {
const parts = line.split('\t');
return {
id: parts[1], // 比赛编号作为唯一 ID
group: parts[0], // 组别
team1: parts[2], // 国家1 code
team2: parts[3], // 国家2
score1: parts[4], // GIN 得分
score2: parts[5], // NZL 得分
date: parts[6], // 日期
time: parts[7], // 时间
status: parts[8] // 状态
};
});
})
.catch(error => console.error('Error fetching the matches:', error));
},
groupSelected(group) {
// 更新当前选中的组别
this.currentGroup = group;
this.currentIndex = 0; // 重置分页到第一页
},
prevMatches() {
// 上一页
if (this.currentIndex > 0) this.currentIndex--;
},
nextMatches() {
// 下一页
if (this.currentIndex < Math.ceil(this.currentMatches.length / this.matchesPerPage) - 1) this.currentIndex++;
},
getFlagUrl(code) {
// Construct the URL for the flag image
return `https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/${code}.png`;
},
goToVst() {
this.$router.push('/Vst');
},
goToHome() {
this.$router.push('/');
},
DisplayMatch(match){
this.selectedMatch = match; // 更新 selectedMatch 为被点击的 match 项
}
}
};
</script>
<style scoped>
.headerRow {
text-align: center;
background-color: #262626;
color: #000;
}
.detail-container {
max-width: 75%;
margin: 20px auto;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
background-color: #fff;
border: 5px solid #D4BE66;
border-radius: 10px;
}
.detail-con {
display: flex;
}
.groups button {
margin-right: 10px;
background-color: #D4BE66;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
border: 3px solid #262626;
border-radius: 10px;
}
.matches {
width: 100%;
margin-top: 20px;
display: flex;
border: 5px solid #262626;
border-radius: 10px;
}
.match {
font-size: 18px;
border: 5px solid #D4BE66;
border-radius: 10px;
padding: 20px;
margin: 10px;
width: 50%;
background-color: white;
color:#000;
}
.match-long {
font-size: 30px;
border: 1px solid #ccc;
padding: 20px;
padding-left:9% ;
padding-right:9% ;
margin: 10px;
width: 80%;
background-color: white;
color:#000;
border: 5px solid #D4BE66;
border-radius: 10px;
}
.match:hover {
border: 5px solid #FFD700; /* 金色边框 */
background-color: #000000; /* 背景颜色 */
color: #FFF;
}
.match-long:hover {
border: 5px solid #FFD700; /* 金色边框 */
background-color: #000000; /* 背景颜色 */
color:#FFF;
}
.flag {
width: 45px;
height: 30px;
margin-right: 10px;
}
.flag-long{
width: 90px;
height: 60px;
margin-right: 10px;
}
button {
font-weight: 600;
background-color: #D4BE66;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
margin-right: 10px;
}
button:hover {
background-color: #262626;
color: #D4BE66;
border: 3px solid #D4BE66;
border-radius: 10px;
}
</style>
对阵图组件中,我们将对阵图放在一个detail-container中,再将detail-container分为三列:(round1-box)、(round2-box)、(final1、final2)中,再于各列的内部以xxx-cell的形式存储国家国旗和分数。同时以同一个国家同时高亮显示达到晋级的效果。Vst.vue具体代码如下:
<template>
<div class="bracket">
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" />
<div>
<h1>Football_Versus_t.</h1>
</div>
<div class="round-box">
<div class="round-cell quarter-finals">
<h2>Quarter_Finals</h2>
<div class="match-box">
<div class="team">
<div class="match-cell" @mouseenter="setHover('法国')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('法国') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/FRA.png`"
alt="Country Flag">
<span class="country">FRA</span>
<span class="score">✅1</span>
</div>
<div class="match-cell" @mouseenter="setHover('阿根廷')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('阿根廷') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/ARG.png`"
alt="Country Flag">
<span class="country">ARG</span>
<span class="score">0</span>
</div>
</div>
<div class="team">
<p class="game-type">PSO</p>
<div class="match-cell" @mouseenter="setHover('埃及')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('埃及') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/EGY.png`"
alt="Country Flag">
<span class="country">EGY</span>
<span class="score">✅1[5</span>
</div>
<div class="match-cell" @mouseenter="setHover('巴拉圭')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('巴拉圭') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/PAR.png`"
alt="Country Flag">
<span class="country">PAR</span>
<span class="score">1[4</span>
</div>
</div>
<div class="team">
<div class="match-cell" @mouseenter="setHover('摩洛哥')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('摩洛哥') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/MAR.png`"
alt="Country Flag">
<span class="country">MAR</span>
<span class="score">✅4</span>
</div>
<div class="match-cell" @mouseenter="setHover('美国')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('美国') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/USA.png`"
alt="Country Flag">
<span class="country">USA</span>
<span class="score">0</span>
</div>
</div>
<div class="team">
<div class="match-cell" @mouseenter="setHover('日本')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('日本') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/JPN.png`"
alt="Country Flag">
<span class="country">JPN</span>
<span class="score">0</span>
</div>
<div class="match-cell" @mouseenter="setHover('西班牙')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('西班牙') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/ESP.png`"
alt="Country Flag">
<span class="country">ESP</span>
<span class="score">✅3</span>
</div>
</div>
</div>
</div>
<div class="round-cell semi-finals">
<h2>Semi_Finals</h2>
<div class="match-box">
<div class="team">
<p class="game-type">AET</p>
<div class="match-cell" @mouseenter="setHover('法国')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('法国') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/FRA.png`"
alt="Country Flag">
<span class="country">FRA</span>
<span class="score">✅3</span>
</div>
<div class="match-cell" @mouseenter="setHover('埃及')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('埃及') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/EGY.png`"
alt="Country Flag">
<span class="country">EGY</span>
<span class="score">1</span>
</div>
</div>
<div class="team">
<div class="match-cell" @mouseenter="setHover('摩洛哥')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('摩洛哥') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/MAR.png`"
alt="Country Flag">
<span class="country">MAR</span>
<span class="score">1</span>
</div>
<div class="match-cell" @mouseenter="setHover('西班牙')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('西班牙') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/ESP.png`"
alt="Country Flag">
<span class="country">ESP</span>
<span class="score">✅2</span>
</div>
</div>
</div>
</div>
<div class="final-1">
<h2>Finals</h2>
<div class="final-2">
<div class="team">
<p class="game-type">Gold AET</p>
<div class="match-cell" @mouseenter="setHover('法国')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('法国') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/FRA.png`"
alt="Country Flag">
<span class="country">FRA</span>
<span class="score">🥈3</span>
</div>
<div class="match-cell" @mouseenter="setHover('西班牙')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('西班牙') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/ESP.png`"
alt="Country Flag">
<span class="country">ESP</span>
<span class="score">🥇5</span>
</div>
</div>
<div class="team" style="padding-top: 200px;">
<p class="game-type">Bronze</p>
<div class="match-cell" @mouseenter="setHover('埃及')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('埃及') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/EGY.png`"
alt="Country Flag">
<span class="country">EGY</span>
<span class="score">0</span>
</div>
<div class="match-cell" @mouseenter="setHover('摩洛哥')" @mouseleave="clearHover()"
:class="{ hovered: isHovered('摩洛哥') }">
<img :src="`https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/MAR.png`"
alt="Country Flag">
<span class="country">MAR</span>
<span class="score">🥉6</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
hoveredTeam: null, // 新增属性
};
},
methods: {
setHover(team) {
this.hoveredTeam = team; // 设置悬停的队伍
},
clearHover() {
this.hoveredTeam = null; // 清除悬停
},
isHovered(team) {
return this.hoveredTeam === team; // 判断是否为悬停状态
},
},
};
</script>
<style scoped>
.olympic-emblem {
width: 680px;
height: auto;
}
.headerRow {
text-align: center;
background-color: #262626;
color: white;
}
.game-type {
text-align: left;
font-size: 20px;
padding-left: 20px;
color: #D4BE66;;
}
.final-1 {
width: 200px;
display: flex;
flex-direction: column;
justify-content: space-around;
height: 80%;
}
.final-2 {
display: flex;
flex-direction: column;
margin-top: 200px;
justify-content: space-around;
height: 80%;
}
.country {
text-align: center;
}
.score {
text-align: right;
}
img {
width: 45px;
height: 30px;
object-fit: cover;
}
.bracket {
display: flex;
flex-direction: column;
align-items: center;
background-color: #262626;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.round-box {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 20px;
background-color: #565656;
border: 5px solid #D4BE66;
border-radius: 10px;
}
.round-cell {
margin: 0 10px;
width: 220px;
}
h1 {
font-size: 50px;
color: #D4BE66;
margin-bottom: 20px;
}
h2 {
font-size: 1.5em;
color: #D4BE66;
text-align: center;
margin: 10px 0;
}
.match-box {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 90%;
}
.match-cell {
display: grid;
width: 220px;
grid-template-columns: 25% 25% 50%;
justify-content: center;
align-items: center;
padding: 15px;
margin-bottom: 15px;
margin: 10px 0;
font-size: 30px;
border-radius: 10px;
background-color: #FFFFFF;
color: #D4BE66;
border: 5px solid #D4BE66;
transition: background-color 0.3s, border-color 0.3s, color 0.3s;
}
.match-cell.hovered {
background-color: #262626;
color: #FFFFFF;
border: 5px solid #D4BE66;
}
.country {
text-align: center;
padding: 5px;
font-weight: bold;
}
</style>
了解更多界面,我们添加了巴黎奥运会的介绍,相关网址的导航,以及精美的背景图,来吸引网友探索。More-inf.Vue具体代码如下:
<template>
<div class="headerRow">
<header style="
background-color: #262626;
padding: 40px;
">
<img src="https://www.sj51.net/wp-content/uploads/2023/01/ea5b33f1afd24c96b49fd78dce017a90.gif" alt="Paris 2024 Olympic Emblem" class="olympic-emblem" @click="goBackHome"/>
</header>
<div>
<h1>More Information</h1>
</div>
<main>
<div class="more-info">
<div class="background-image"></div>
<div class="content">
<h1>More Information about Paris 2024 Olympics</h1>
<p style="font-size: 25px">The 33rd Summer Olympic Games, also known as the 2024 Paris Olympics, is an international Olympic event held in Paris, France. It opened on July 26, 2024 and closed on August 11, 2024 local time. Some events started on July 24, with a total of 32 major events and 329 minor events, and 206 countries and regions participated.</p>
<ul style="display: flex;margin-left: 30%;font-size: 30px;">
<li><strong>Official Website:</strong> <a href="https://www.olympic.org/paris-2024" target="_blank">Olympic Games Paris 2024</a></li>
</ul>
<ul style="display: flex;margin-left: 30%;font-size: 30px">
<li><strong>Paris 2024 on Wikipedia:</strong> <a href="https://en.wikipedia.org/wiki/2024_Summer_Olympics" target="_blank">Wikipedia - 2024 Summer Olympics</a></li>
</ul>
<ul style="display: flex;margin-left: 30%;font-size: 30px">
<li><strong>Paris 2024 on Twitter:</strong> <a href="https://twitter.com/Paris2024" target="_blank">@Paris2024</a></li>
</ul>
<button @click="goBackHome">Back to Home</button>
</div>
</div>
</main>
</div>
</template>
<script>
export default {
name: 'MoreInf',
methods: {
goBackHome() {
this.$router.push('/');
}
}
};
</script>
<style scoped>
.headerRow {
text-align: center;
background-color: #262626;
color: white;
}
.more-info {
max-width: 75%;
margin: 20px auto;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
position: relative;
text-align: start;
border: 10px solid #D4BE66;
border-radius: 10px;
}
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://ts1.cn.mm.bing.net/th/id/R-C.f7fdcea5fcdddceff51ad65485f5848a?rik=a7WFZnjajL19Hw&riu=http%3a%2f%2fpic.bizhi360.com%2fbbpic%2f89%2f4689.jpg&ehk=sxI%2bQBOqrAVZHjQb%2b%2bP9tds%2ftYH4nAbShX2kmCLVMIE%3d&risl=&pid=ImgRaw&r=0');
background-size: cover;
background-position: center;
filter: blur(8px); /* 这里的8px是模糊度,可以根据需要调整 */
}
.content {
position: relative;
z-index: 1;
}
.more-info h1 {
font-size: 50px;
text-align: center;
color: #000;
}
.more-info p {
text-align: justify;
color: #000;
margin-bottom: 20px;
}
.more-info ul {
list-style-type: none;
padding: 0;
}
.more-info li {
margin-bottom: 10px;
color: #000;
}
.more-info a {
color: #D4BE66;
text-decoration: none;
}
.more-info a:hover {
text-decoration: underline;
}
button {
display: block;
width: 100px;
margin: 20px auto;
padding: 10px;
font-size: 16px;
color: #fff;
background-color: #D4BE66;
border: none;
border: 3px solid #262626;
border-radius: 10px;
cursor: pointer;
}
button:hover {
background-color: #fff;
color: #000;
border: 3px solid #D4BE66;
border-radius: 10px;
}
h1 {
font-size: 50px;
color: #D4BE66;
margin-bottom: 20px;
}
</style>
这是我的第一次web合作项目,也是第一次web项目,学新技术很耗心力,我们认真学习了html、css、JavaScript等技术,学习了vue框架,学会了部署服务器等,有安卓开发经验的我的搭档在这次合作项目中对我起了很大的指导作用,使我对团队开发的经验在一片空白上得到了很大的补足。总之,我学会了很多学识,也得到了很多经验。
这次是我第一次web合作项目,各项流程都不太熟悉,这次的项目使用了vue3,我的搭档学习新技术非常快,在开发过程帮我很大的忙,并且在我学习过程中也指导了我很多,避免我白白浪费时间去干没用的事情。这次的合作项目,让我学会了使用vue开发,然后部署到服务器,开发成真正的网页,让我学到了很多有用的知识,丰富了我的开发经验。
总能在问题出现的前期就与我进行讨论,极大限度的保证了合作的效率,同时注重细节,专攻难题,脚踏实地,沉着冷静,是完美的合作对象
对待作业非常认真,作业有问题时会积极讨论,这次作业开发过程中非常用心,注重很多细节,开发出的页面与项目原型设计几乎一致,耐心可靠,踏实肯干,是可遇不可求的好搭档