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

222200134游镇诚 2024-09-30 22:39:01
这个作业属于哪个课程https://bbs.csdn.net/topics/619333839
这个作业要求在哪里结对第二次作业——编程实现
结对学号222200134、222200201
这个作业的目标一个功能完善、用户体验优秀的2024年巴黎奥运会赛况展示平台
其他参考文献

目录

  • 1. 项目和规范地址
  • 2. PSP表格
  • 3. 部署地址
  • 4. 成果展示
  • 4.1 主页
  • 4.2 奖牌榜
  • 4.3 每日赛程
  • 4.4 赛程详情
  • 4.5 对阵图
  • 4.6 更多信息
  • 5. 讨论过程
  • 5.1. 初步讨论
  • 5.2. 问题解决
  • 5.3. 查找资料
  • 5.4. 定期回顾
  • 5.5. 讨论截图
  • 6. 设计与实现
  • 6.1 功能结构图
  • 6.2 分析过程
  • 6.3 设计过程
  • 6.4 实现过程
  • 6.5 遇到的问题及解决方式
  • 6.6 扩展功能
  • 7. 关键代码与思路说明
  • 7.1 主页
  • 7.2 奖牌榜
  • 7.3 每日赛程
  • 7.4 赛程详情
  • 7.5 对阵图
  • 7.6 更多信息
  • 8. 心路历程与收获
  • 8.1 222200134游镇诚
  • 8.2 222200201于浩飞
  • 9. 队友评价
  • 9.1 222200134游镇诚对222200201于浩飞的评价
  • 9.2 222200201于浩飞对222200134游镇诚的评价

1. 项目和规范地址

222200134_222200201

代码规范文档地址:
Style Guide | Vue.js

2. PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划6060
•Estimate估计这个任务需要多少时间6060
Development开发15901370
•Analysis需求分析(包括学习新技术)300180
•Design Spec生成设计文档6060
•Design Review设计复审3020
•Coding Standard代码规范 (为目前的开发制定合适的规范)6060
•Design具体设计180120
•Coding具体编码600720
•Code Review代码复审6030
•Test测试(自我测试,修改代码,提交修改)300180
Reporting报告240180
•Test Report测试报告6030
•Size Measurement计算工作量3030
•Postmortem & Process Improvement Plan事后总结, 并提出过程改进计划150120
Sum Up合计18901610

3. 部署地址

222200134_222200201_Paris_Olympics

4. 成果展示

4.1 主页

展示巴黎奥运会logo和标题信息,提供奖牌榜、每日赛程、更多信息的功能入口,采用一些动效和gif文件组成。

img

4.2 奖牌榜

显示所有国家地区的奖牌情况,上下滚动查看,制作了一些高亮事件。

4.3 每日赛程

在顶端使用下拉列表提供选择日期查看赛事功能,可以一次性查看所有赛程,不过会导致崩溃。
赛事显示方面同样制作了高亮动效,点击查看详情可跳转到Detail页面。

4.4 赛程详情

通过点击赛程页面的查看详情按钮跳转,提供了分组查看,点击某一个赛事卡可以在页面底部新建一个赛事卡体现该场比赛。

4.5 对阵图

对阵图页面通过详情页面顶端分组最右边的按钮GoToVst进入,对阵图提供了四分之一决赛后的比赛对阵情况,通过高亮体现晋级情况,当鼠标移到一个国家上时,会体现其晋级之路。

4.6 更多信息

更多信息页面提供了巴黎奥运会的相关信息及巴黎奥运会相关网址

5. 讨论过程

项目结构图在模块6设计与实现中体现

5.1. 初步讨论

  • 目标和愿景:
    创建一个用户友好的、信息丰富的平台,让全球观众能够实时了解2024年巴黎奥运会的赛况。
    平台应该能够提供实时更新的数据,包括奖牌榜、赛程、比赛结果等。
    设计应该具有吸引力,能够激发用户对奥运会的兴趣。
  • 功能需求:
    首页:提供一个清晰的导航系统,用户可以轻松访问奖牌榜、赛程和更多信息。
    奖牌榜:实时更新的奖牌榜,显示各国的金牌、银牌和铜牌数量。
    每日赛程:展示当天的赛事安排,包括比赛类型、时间、项目、参赛国家和比分。获胜国家的名字应该突出显示。
    详细赛况:提供每场比赛的详细信息,包括参赛国家、出赛名单和比赛详情。
    对阵表:展示即将进行的比赛的对阵情况。
    了解更多:提供关于巴黎奥运会的背景信息,包括历史、文化、场馆介绍等
  • 技术需求:
    需要一个强大的后端系统来处理实时数据更新。
    前端设计需要考虑跨平台兼容性,包括手机、平板和电脑。
    需要考虑多语言支持,以满足不同国家用户的需求。
  • 用户体验:
    界面设计应该简洁明了,避免信息过载。
    提供搜索功能,方便用户查找特定比赛或国家的信息。
    考虑加入社交媒体分享功能,让用户可以轻松分享他们感兴趣的内容。

5.2. 问题解决

  • 数据获取:
    获取的奥运会数据?可能需要与奥运会官方数据提供商合作。
  • 用户界面设计:
    如何设计一个既美观又实用的用户界面?需要进行用户调研和原型测试。
  • 技术实现:
    如何在短时间学习vue技术?需要结合AI技术和相关技术文献。

5.3. 查找资料

  1. 研究其他成功的体育赛事展示平台,了解他们的优势和不足。
  2. 查阅关于奥运会的官方资料,了解比赛规则和历史背景。
  3. 了解用户需求和偏好,可以通过问卷调查或社交媒体分析。

5.4. 定期回顾

设定定期交流时间,评估项目进度和遇到的问题。

5.5. 讨论截图

img1

img2

6. 设计与实现

6.1 功能结构图

展示了该项目在Vue框架下的组件:

img

6.2 分析过程

  • 功能需求:细化每个界面的功能,确定必须实现的功能和可选功能:奖牌榜、赛程表、详细赛况、对阵图等
  • 技术需求:分析实现这些功能所需的技术栈和工具:使用Vue框架和Vscode进行开发

6.3 设计过程

  • 界面设计:
    使用工具Figma设计界面原型。
  • 系统架构设计:
    前端设计:确定使用Vue框架。
  • 数据流设计:
    数据获取:设计数据获取和更新的流程:从静态库读取文件。
    数据展示:设计数据如何在界面上展示:读取文件暂存数组,界面销毁数组同时销毁。
  • 关键设计点:
  1. 由于奥运会已经结束,所以我们选择爬取数据放入静态库读取,简便的同时占用性能少
  2. 在对阵图采用相同国家高亮设计体现晋级,解决了线条难画的问题

6.4 实现过程

  • 前端开发:
    使用HTML, CSS, JavaScript等技术实现界面。
    使用框架Vue提高开发效率。

  • 主页设计与实现

  • 奖牌榜模块

  • 每日赛程模块

  • 详细赛程模块

6.5 遇到的问题及解决方式

对阵图的round-box之间的连线需要记录位置进行线条绘制,但我们尝试了许多方法,只能够做到显示垂直方向的线条。这大概与我们将该页分为三个column有关。所以我们放弃线条绘制,在讨论许久后,我们选择通过采用相同国家高亮设计体现晋级,解决了线条难画的问题。

6.6 扩展功能

  • 更多信息页面:通过展示巴黎风景、介绍巴黎奥运会的形式,,提供相关官网网址,让用户对本次奥运会有更丰富的了解。

7. 关键代码与思路说明

7.1 主页

主页的设计友一个会标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>

7.2 奖牌榜

奖牌榜部分,我们选择了直接通过表格形式,在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>

7.3 每日赛程

每日赛程组件,总体上我们选择在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>

7.4 赛程详情

赛程详情组件中,点击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>

7.5 对阵图

对阵图组件中,我们将对阵图放在一个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>

7.6 更多信息

了解更多界面,我们添加了巴黎奥运会的介绍,相关网址的导航,以及精美的背景图,来吸引网友探索。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>

8. 心路历程与收获

8.1 222200134游镇诚

这是我的第一次web合作项目,也是第一次web项目,学新技术很耗心力,我们认真学习了html、css、JavaScript等技术,学习了vue框架,学会了部署服务器等,有安卓开发经验的我的搭档在这次合作项目中对我起了很大的指导作用,使我对团队开发的经验在一片空白上得到了很大的补足。总之,我学会了很多学识,也得到了很多经验。

8.2 222200201于浩飞

这次是我第一次web合作项目,各项流程都不太熟悉,这次的项目使用了vue3,我的搭档学习新技术非常快,在开发过程帮我很大的忙,并且在我学习过程中也指导了我很多,避免我白白浪费时间去干没用的事情。这次的合作项目,让我学会了使用vue开发,然后部署到服务器,开发成真正的网页,让我学到了很多有用的知识,丰富了我的开发经验。

9. 队友评价

9.1 222200134游镇诚对222200201于浩飞的评价

总能在问题出现的前期就与我进行讨论,极大限度的保证了合作的效率,同时注重细节,专攻难题,脚踏实地,沉着冷静,是完美的合作对象

9.2 222200201于浩飞对222200134游镇诚的评价

对待作业非常认真,作业有问题时会积极讨论,这次作业开发过程中非常用心,注重很多细节,开发出的页面与项目原型设计几乎一致,耐心可靠,踏实肯干,是可遇不可求的好搭档

...全文
32 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

109

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 助教姜词杰
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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