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

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游镇诚的评价

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

...全文
21 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
AJAX——新手快车道 前言 AJAX是什么? 首先、AJAX是一种很酷的技术,一旦采用了AJAX,就能让你的Web页面, 你的网站,甚至连同你们公司,都变得很酷。在Web2.0的时代里,不使用一点 AJAX技术的网站,就会显得很老土,很落伍。 但是,这样的理解,其实是很肤浅的。仅仅是从一个外行,从一个使用者的 角度出发,来理解AJAX,就像我在本书的第一章AJAX我也行中那样,开发 出很愚蠢,甚至都没有资格被称之为AJAX应用的纯IE、XMLHTTP应用。 AJAX更酷的一点在于,对于传统的Web开发人员来说,AJAX所运用的, 是更加先进的,更加标准化的,更加和谐高效的,完整的Web开发技术体系。 遵循这样的体系开发Web应用,能让你的开发过程变得更加轻松,也能使你们 的开发团队,显得很酷。在Web2.0 的时代里,还在采用过时的技术来开发 Web,会显得很老土,很落伍。 AJAX的相关组成技术,每一个都已经出现了N年以上了,对这些技术的 组合运用,也远远早于AJAX这个名词出现之前。所以,我真正敬佩的,并非提 出 AJAX这个缩写的Jesse James Garrett。而是那些早在N年以前,就已经在探索、 实践的先行者,他们始终在追求的:是更好的用户体验,以及更好的开发体验。 这样的精神,才是最可宝贵的,也是最值得我们学习的。许多年过去以后,当我 们再回头来看当年的这些热门技术,也许早已经变得老土,变得落伍了。在这样 的历程中,哪些人会成长为高手?会成长为大师呢?就是那些永不满足,永远 在追求更好的用户体验,永远在追求更好的开发体验的人! 新手如何上路 软件开发这个领域,永远都在飞速发展,大家都必须不断的学习新的知识、 技能、框架、IDE、甚至新的语言。传说中的骨灰级高手们,就像传说中的大侠, 任何武器、哪怕是一块木头到了他们手里,也能发挥惊人的威力,人家练了几十 年的看家本领,他们随手使来,也竟然像是打娘胎里就开始练了一样。为什么? 就算不吹那么玄的,平常我们能够碰到的那些老手,在学新东西的时候, 也比那些新手学得更快,理解得更深,运用得更熟练。而新手们呢?往往就会漫 无头绪,焦头烂额,以一副张着茫然的大眼睛的经典表情,出现在各大论坛的 新手求助区里。他们欠缺的,究竟是什么呢?为什么老手学新东西,就没遇到那 么多困难呢? 泛泛地说,自然是经验上的欠缺。仔细地说来,又可以分为三个方面: 一、本质,一种技术与另一种技术之间,往往会有本质上的相通之处,当你 对一种技术的理解与思考越来越深入时,学习一种新技术也会更加容易。触类旁 通,举一反三的能力,就是来自于对于技术本质的追寻。 二、地图,本质上或多或少的相通,也提示着我们技术之间的相互关联,当 你了解的技术越多,了解得越是深入,在你的内心,就能建立起越发清晰的技 术地图。各种知识都有一个自然、合理的位置。那么当一个老手要学习一门新技术 的时候,他其实并非在探索一个全新的、未知的领域,而是有很多脉络可寻,也 很多已知可以帮助他们快速了解未知。 三、技巧,面对同样的未知,面对同样的难题,新手们一筹莫展,而老手们 却掌握着更多的技巧和手段,帮助他们试探可能性、缩小问题的范围、迅速定位 问题、不犯明显愚蠢的错误、甚至能够列举出更具命中力的搜索关键词,而这些 技巧,都帮助老手在前进的道路上,更少跌倒,即使跌倒,也能更快的爬起来。 作为一本写给新手的入门书籍,我们希望展现给读者的,是一个老手如何 学习新技术的过程。我们相信,这样的一个学习过程,对于新手来说,是更具有 价值的。 何谓快车道 必须老老实实的承认,我吹牛了!老手虽然会比新手学习得更快一些,但 是也同样会碰到麻烦,遇到障碍,感觉头痛。如果没有真正的专家的指导,我不 可能如此迅速地将AJAX掌握到目前这样的程度,要真是让我自学三个月,然 后就写出书来的话,那真是在骗钱了。 老手能够快速学习的另一个重要的诀窍是:认识很多牛人朋友 如果没有李锟与赵泽欣的专家级指导与帮助,如果没有与李锟AJAX结对 编程的体验,如果没有三个人在MSN上无数次的长聊,我想要在短期内建立起: 对于AJAX本质的理解; 对于整个AJAX以及相关技术地图的理解; 对于AJAX编程开发所需要的很多技巧、手段的掌握; 几乎是不可能的。 如果没有(N多需要感谢的人)的(N多方面的帮助),我们这本书,也 不可能以现在这样的深度,以(N个月)内完成的速度,送到读者的面前。 希望这本书,能够对大家快速学习AJAX,有所帮助。

108

社区成员

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

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