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

222200125郑韵 2024-09-30 22:55:25
这个作业属于哪个课程https://bbs.csdn.net/forums/2401_CS_SE_FZU?typeId=7771625&category=0
这个作业要求在哪里https://bbs.csdn.net/topics/619333839
结对学号222200125 222200305
这个作业的目标基于Web技术的网页原型实现、Git协作、项目部署
其他参考文献https://www.runoob.com/css/css-tutorial.htmlhttps://www.runoob.com/html/html-tutorial.htmlhttps://www.runoob.com/js/js-tutorial.html

目录

  • 1.项目地址和代码规范
  • 项目地址
  • 代码规范
  • 2.PSP表格
  • 3.部署地址
  • 4.成果展示
  • 4.1 首页
  • 4.2奖牌榜
  • 4.3每日赛程
  • 4.4详细赛程
  • 4.5对阵图
  • 4.6了解更多
  • 5.结对讨论过程
  • 6.设计实现
  • 6.1 功能结构图
  • 6.2 分析过程
  • 6.3 设计过程
  • 6.4 实现过程
  • 6.5 遇到的问题以及解决方式
  • 7.关键代码与思路解释
  • 7.1主页
  • 7.2奖牌榜
  • 7.3每日赛程
  • 7.4详细赛况
  • 7.5对阵图
  • 7.6了解更多
  • 8.心路历程与收获
  • 8.1 222200125郑韵感想
  • 8.2 222200305卢禧感想
  • 9.队友评价
  • 9.1 222200125郑韵对222200305卢禧的评价
  • 9.2 222200305卢禧对222200125郑韵的评价

1.项目地址和代码规范

项目地址

仓库项目地址

代码规范

前端
后端

2.PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planing计划3030
• Estimate• 估计这个任务需要多少时间3030
Development开发19902230
• Analysis分析150160
• Design Spec生成设计文档6050
• Design Review• 设计复审3020
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)6080
• Design具体设计10090
• Coding具体编码12001500
• Code Review代码复审9080
• Test• 测试(自我测试,修改代码,提交修改300250
Reporting报告130110
• Test Repor测试报告6050
• Size Measurement• 计算工作量3030
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划4030
合计21502370

3.部署地址

222200125_222200305巴黎奥运会部署地址

4.成果展示

4.1 首页

4.2奖牌榜

4.3每日赛程

4.4详细赛程

4.5对阵图

4.6了解更多

5.结对讨论过程

img

git记录

img

6.设计实现

6.1 功能结构图

img

  • 首页:提供巴黎奥运会的精彩时刻、奖牌榜、夺金时刻以及下一届奥运会的相关信息。点击首页,即可跳转到了解更多页面,深入了解巴黎奥运会。
  • 了解更多:通过图文结合的方式,详细介绍巴黎奥运会的各个方面,让您全面了解赛事信息。
  • 奖牌榜:展示参赛国家的排名、国旗、国家名称,并详细列出各国获得的金、银、铜牌数量及奖牌总数。
  • 每日赛程:自动记录您上次查看的日期,或默认展示7月24日的赛程信息。您可以通过日历选择特定日期,加载对应的赛程数据。点击感兴趣的团体赛,即可查看详细赛程
  • 详细赛程:为您展示所选比赛的具体信息,包括小组队伍、比分、开始时间等。同时显示比赛所属的组别,点击组别即可加载并查看该小组的详细数据。
  • 对阵图:通过图表形式直观展示1/4决赛、半决赛和决赛的参赛国家及比赛成绩。鼠标悬停于特定国家时,将高亮显示,帮助您清晰了解各国的比赛情况。

6.2 分析过程

在项目启动初期,我们首先进行了细致的需求分析,以确立系统的核心功能。目标是打造一个用户友好的平台,为用户提供丰富的2024巴黎奥运会信息,包括赛事的精彩时刻、奖牌榜、夺金时刻以及下一届奥运会的预告。

需求分析的重点包括:

  • 用户体验:确保用户界面直观易用,信息易于获取。
  • 数据准确性:实时更新奖牌榜和赛程信息。
  • 功能完整性:覆盖从首页概览到详细赛程的全方位信息。

6.3 设计过程

在设计阶段,我们采取了以下步骤来构建系统:

  1. 技术选型:
  • 后端:选择Spring Boot作为后端服务框架,进行数据的获取与预处理。
  • 前端:采用HTML、CSS和JavaScript的经典组合,确保广泛的浏览器兼容性和丰富的用户交互体验。
  • 数据存储:选择JSON文件作为数据存储解决方案,用户存储奖牌榜、每日赛程、详细赛程数据,放置在项目的 resources\static\data 目录下。
  1. 数据模型设计:
  • 奖牌榜:包含国家名、国家ID、金牌数、银牌数、铜牌数和总奖牌数的数据模型。

  • 赛程信息:创建了赛事日期、时间、队伍、比分等字段的数据模型。

  1. 用户界面设计:
  • 交互设计:设计了直观的导航和交互元素,如日历选择器和赛事筛选器。
  1. 部署策略
  • 一次性部署:在项目开发完成后,进行一次性部署到生产环境。
  • 环境准备:在生产环境中准备好所需的硬件和软件资源。

6.4 实现过程

  1. 后端网页原始数据获取

分别爬取奖牌榜与每日赛程数据到本地的medal.json与schedule目录下的MM-DD.json文件中,如果项目读取不到数据,则重新爬取并且存储到本地的文件下。这样做是为了防止每次都要重新爬取,多人同时访问服务器的时候,服务器的压力会比较大。

而对于详细赛程的数据,网站设置了反爬机制所以使用浏览器的抓包工具,获得性别与大类对应的详细赛况数据。如男子足球,它在每日赛程数据中的大类Id:eventId = "FBLMTEAM11------------------------",经过研究发现后面详细赛程的code将会对应这个数据,但是后面的-数量会存在出入,所以决定,截取eventId前面的字母,以eventId_1/2.json(男1女2)为命名存储到本地目录下。

  1. 后端原始数据处理与返回

1)奖牌榜与详细赛程数据预处理

获取奖牌榜数据或者详细赛程仅进行简单的数据获取与数据返回。

2)每日赛程数据预处理
首先由于我们网站面向中国用户,而爬取的数据是基于巴黎时间,所以在接收到前端发来的日期date请求以后,要在保证不是开始日期的情况下,获取前一天的比赛数据,不是比赛结束日期的情况下,获取今天的比赛数据。分别将这两个数据中的比赛开始时间转换为上海时间,与当天日期比较最终获取到当天的数据。

3.前端实现
1)首页
使用 <div class="homepage"> 作为主页内容的容器,确保所有内容居中显示。
页面的 <body> <html>元素被设置为 flex 容器,内容垂直排列,且在垂直方向上自动适应高度。
图片使用百分比宽度和自动高度来确保它们在不同设备上保持比例并自适应屏幕宽度。
.text-overlay 类用于在第一张图片上添加文本覆盖层,使用绝对定位放置在右上角。
通过 JavaScript 为文本覆盖层中的<span>元素添加点击事件监听器,当用户点击时,页面会跳转到相应的页面(例如奖牌榜或每日赛程)。

2)奖牌榜
使用<div class="medalpage">作为奖牌榜页面的容器。
使用 <div class="text-overlay"> 在图片上添加可点击的文本覆盖层,提供导航链接。
.header 类用于头部图片的样式,使用 background-image 来展示背景图片,并使用 padding 和 color 属性来调整布局和文本颜色。
.table 类用于创建奖牌榜数据表格的样式,使用 box-shadow 属性添加阴影效果。
.table-header.data-row 类用于控制表格头部和数据行的样式。

3)每日赛程
.Competition1 .Competition2类用于控制不同类型比赛信息块的样式。
.Time, .Itemcodename, .Title, .Awayname, .Homename, .Homescore, .Awayscore 类用于定位和样式化比赛信息。
使用 <div class="calendar"> 显示日历,允许用户选择日期。
为日历触发器添加点击事件,实现日历的显示和隐藏。

4)详细赛况
.group 类用于控制比赛信息组的样式,包括背景模糊和背景图片。
.match-info .score-header类用于定位和样式化比赛信息和比分。
.group-buttons 类用于样式化按钮组,.group-button 类用于单个按钮的样式。
.match-card 类用于样式化单个比赛结果卡片。
使用 fillMatchResults 函数动态生成比赛结果卡片,并添加到页面中。
为比赛结果卡片添加点击事件,点击时切换选中状态并更新对阵信息。

5)对阵图
使用 <div class="match-component"> 创建单个比赛信息块,包括国家旗帜、队名和比分。
使用 <div class="aet"> <div class="aet-extended"> 展示特殊状态,如加时赛和点球大战。
.match-component .match-extended-component 类用于创建比赛信息块,包括背景、国家旗帜、队名和比分。
使用 JavaScript 实现鼠标悬停在国家名称上时,高亮显示所有相同的国家名称。

6.5 遇到的问题以及解决方式

  1. 问题

1)详细赛况数据有反爬机制:通过url获取到的详细赛况数据只有空的html,而通过浏览器则是可以获得json数据的。

2) 父页面每日赛程如何获取子页面日历中用户选择的日期,并且展示在页面的比赛日期,且获取相应的每日赛程数据。

3)默认其他页面跳转到07-24的每日赛程,所以页面默认加载会自动获取07-24的数据。但是在加载完新的日期以后,由于以上设置会又变回07-24。

4)部署的时候无法读取到resources资源包内的文件,而报错。

  1. 解决方案
    1)将详细赛况的json数据通过浏览器抓包下载到本地,但前端无法直接通过目录读取,故从后端读取。

2)父页面创建dateSelected自定义事件触发器。子页面用户点击相应的日期以后会触发创建dateSelected自定义事件,并将日期放入事件的detail属性中。通过父窗口发送事件。父页面获取数据以后调用fetchMatchesForDate(date)更新日期显示,并且更新页面。

3)使用localStorage本地用户选择过的日期,在页面加载完成以后优先加载用户选择过的日期,否则为默认日期07-24。

4)文件读取采用获取资源文件的输入流class.getResourceAsStream才能读取JAR包中资源。

7.关键代码与思路解释

7.1主页

<div class="homepage"> 作为整个页面的容器,包含所有的内容。
<img> 标签用于展示页面的图片,其中 id 用于后续的 JavaScript 交互。
<div class="text-overlay"> 用于在图片上添加文本覆盖层,提供导航链接。

<div class="homepage">
  <img class="Frontpage1" id="learnmore" src="image/frontpage.png" alt="frontpage"/>
  <div class="text-overlay">
    <span class="underline">首页</span> 
    <span id="medal">奖牌榜</span> 
    <span id="schedule">每日赛程</span>
  </div>
  <img class="Frontpage2" id="medal2" src="image/frontpage2.png" alt="frontpage2"/>
  <img class="Frontpage3" src="image/frontpage3.png" alt="frontpage3"/>
</div>

使用 document.getElementById 获取元素,并为它们添加点击事件监听器。
当用户点击文本覆盖层上的 <span> 元素时,页面会跳转到相应的页面(例如奖牌榜或每日赛程)。

document.getElementById("medal").addEventListener("click", function() {
  window.location.href = "medal.html";
});

document.getElementById("schedule").addEventListener("click", function() {
  window.location.href = "DailyFixtures.html";
});

document.getElementById("learnmore").addEventListener("click", function() {
  window.location.href = "learnmore.html";
});

document.getElementById("medal2").addEventListener("click", function() {
  window.location.href = "medal.html";
});

7.2奖牌榜

<div class="medalpage"> 作为奖牌榜页面的容器,包含背景图片和文本覆盖层。
<img class="medalpage1"> 用于展示背景图片。
<div class="text-overlay"> 用于在背景图片上添加可点击的文本覆盖层,提供导航链接。

<div class="medalpage">
    <img class="medalpage1" id="bar" src="image/bar.png" alt="medalpage" />
    <div class="text-overlay">
        <span id="homepage">首页</span>
        <span id="medal">奖牌榜</span>
        <span id="schedule">每日赛程</span>
    </div>
</div>

<div class="medal-box">
    <div class="table">
        <div class="table-header">
            <div>顺序</div>
            <div class="noc">NOC</div>
            <div></div>
            <div></div>
            <div></div>
            <div>总数</div>
        </div>
        <div id="medalsContainer" class="data-rows"></div>
    </div>
</div>

header 类用于样式化页面头部,包括背景图片和文本样式。
table 类用于样式化奖牌榜的表格。
data-row 类用于样式化表格的每一行,包括边框和布局。

.header {
    position: relative;
    width: 100%;
    height: 434px;
    background-image: url('./image/bar.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: top;
    padding: 20px;
    color: black;
    display: flex;
    justify-content: flex-end;
    align-items: flex-start;
    text-align: end;
}

.table {
    background-color: white;
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    margin-top: -4px;
}

.data-row {
    display: flex;
    padding: 10px 0;
    justify-content: space-between;
    width: 100%;
    max-width: 983px;
    margin: 0 auto;
    border-bottom: 1px solid #f0f0f0;
}

@media (max-width: 1280px) {
    .medal-box {
        width: 80%;
    }
}

fetchMedals 函数用于从服务器获取奖牌榜数据。
使用 fetch API 发送请求,获取 JSON 格式的响应数据。
动态创建 div 元素并填充奖牌榜数据,然后添加到 medalsContainer 容器中。
window.onload 事件确保在页面加载完成后自动获取奖牌榜数据。

function fetchMedals() {
    fetch('http://120.46.58.99:9090/medals')
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
        .then(data => {
            if (data.code === "200") {
                const medalBox = document.getElementById('medalsContainer');
                medalBox.innerHTML = '';
                const { items } = data.data;
                items.forEach(medal => {
                    const row = document.createElement('div');
                    row.className = 'data-row';
                    row.innerHTML = `
                        <div>${medal.rank}</div>
                        <div class="noc"><img src="https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/${medal.countryid}.png" alt="${medal.countryname}" style="width:20px; height:15px;"> ${medal.countryname}</div>
                        <div>${medal.gold}</div>
                        <div>${medal.silver}</div>
                        <div>${medal.bronze}</div>
                        <div>${medal.count}</div>
                    `;
                    medalBox.appendChild(row);
                });
            } else {
                alert(data.msg);
            }
        })
        .catch(error => {
            console.error('Error fetching medal data:', error);
            alert('网络错误或服务器无响应');
        });
}

window.onload = function () {
    fetchMedals();
};

7.3每日赛程

<div class="container"> 作为整个页面的容器,包含所有内容。
<div class="date-container"> 包含日期显示和日历触发器。
<div class="calendar"> 包含一个iframe,用于嵌入日历页面。

<div class="container">
    <div class="date-container">
        <div class="date-rectangle" id="date-rectangle"></div>
        <div class="date-image" id="calendar-trigger"></div>
        <div id="date-text">比赛日期</div>
    </div>
    <!-- Calendar Container -->
    <div class="calendar" id="calendar">
        <iframe src="calendar.html" width="580" height="480" style="border:none;"></iframe>
    </div>
    <div id="matchesContainer"></div>
</div>

container 设置为相对定位,确保内部元素可以绝对定位。
Competition1 和 Competition2 定义了比赛信息块的样式。
Time, Itemcodename, Title, Awayname, Homename, Homescore, Awayscore 定义了比赛信息的样式。
HomeNoc, AwayNoc 定义了国家旗帜的样式。

.container {
    position: relative;
    width: 1280px;
    height: auto;
    margin: 0 auto;
}

.Competition1, .Competition2 {
    position: relative;
    background: rgba(255, 255, 255, 0.50);
    box-shadow: 2px 2px 4px #BED9F3;
    border-radius: 15px;
    border: 1px #A7A1A1 solid;
    margin: 10px auto;
}

.Time, .Itemcodename, .Title, .Awayname, .Homename, .Homescore, .Awayscore {
    position: absolute;
    color: black;
    font-size: 24px;
    font-family: Microsoft YaHei;
}

.HomeNoc, .AwayNoc {
    position: absolute;
    width: 43px;
    height: 26px;
    left: 200px;
    border: 1px solid #ECE4E7;
}

fetchMatchesForDate 函数用于从服务器获取指定日期的比赛数据。
使用 fetch API 发送请求,获取 JSON 格式的响应数据。
updateMatchesContainer 函数用于将获取到的比赛数据动态生成比赛信息块,并添加到页面中。
DOMContentLoaded 事件确保在页面加载完成后自动获取比赛数据。

async function fetchMatchesForDate(date) {
    try {
        const response = await fetch(`http://120.46.58.99:9090/matchs?date=${date}`);
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        const data = await response.json();
        if (data.code === "200") {
            localStorage.setItem('selectedDate', date);
            localStorage.setItem('selectedMatches', JSON.stringify(data));
            const localDate = new Date(date);
            document.getElementById('date-text').textContent = formatDate(localDate);
            updateMatchesContainer(data);
        } else {
            alert(data.msg);
        }
    } catch (error) {
        console.error('There was a problem with the fetch operation:', error);
        alert('网络错误或服务器无响应1');
    }
}

function updateMatchesContainer(data) {
    const matchesContainer = document.getElementById('matchesContainer');
    matchesContainer.innerHTML = '';
    const matches = data.data.items;
    matches.forEach(match => {
        const group16 = document.createElement('div');
        group16.className = 'Group16';
        // ... 创建比赛信息 ...
        matchesContainer.appendChild(group16);
    });
}

document.addEventListener('DOMContentLoaded', () => {
    const storeDate = localStorage.getItem('selectedDate');
    const dateToFetch = storeDate ? storeDate : '07-24';
    fetchMatchesForDate(dateToFetch);
});

7.4详细赛况

<div class="container"> 作为页面的容器,包含所有内容。
<div class="group"> 包含比赛信息和背景图片。
<div class="match-info">显示对阵双方的信息。
<div class="score-header"> 显示比分标题。
<div class="group-buttons"> 用于放置动态生成的比赛阶段按钮。
<div class="match-results-wrapper"> <div class="match-results"> 用于展示比赛结果。
<div class="menu"> 包含导航菜单。

<div class="container">
    <div class="group">
        <img src="image/background4.png" alt="Background" style="width: 100%; height: 100%; position: absolute;">
        <div class="match-info">
            <span id="team1" style="font-weight: 700;">HOME</span>
            <span style="font-weight: 400;"> VS </span>
            <span id="team2" style="font-weight: 700;">AWAY</span>
        </div>
        <div class="score-header">比赛成绩</div>
    </div>
    <div class="group-buttons">
        <!-- 动态生成的按钮组 -->
    </div>
    <div class="match-results-wrapper">
        <div class="match-results">
            <!-- 动态生成的比赛结果卡片 -->
        </div>
    </div>
    <div class="menu">
        <div id="schedule">赛程</div>
        <div style="font-weight: 700;">成绩</div>
        <div id="medal">奖牌榜</div>
        <div id="match-table">对阵表</div>
    </div>
    <div id="homepage" style="position: absolute; left: 1152px; top: 35px; font-size: 30px;">首页</div>
</div>

页面布局采用 Flexbox 来实现水平和垂直居中。
container 设置固定宽度和高度,用于包含所有内容。
group 设置背景透明度和模糊效果。
match-card 用于展示单个比赛的信息,.dark 类用于高亮选中的比赛卡片。

body, html {
    margin: 0;
    font-family: 'Microsoft YaHei', sans-serif;
    background: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}

.container {
    width: 1280px;
    height: 1016px;
    position: relative;
}

.group {
    width: 100%;
    height: 365px;
    position: absolute;
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(90px);
}

.match-card {
    width: 325px;
    height: 190px;
    background: #fff;
    border: 1px solid #d9d9d9;
    position: relative;
    padding: 10px;
    margin: 0 10px;
    cursor: pointer;
}

.match-card.dark {
    background: #41484b;
    color: white;
}

为首页、赛程、奖牌榜和对阵表添加点击事件,实现页面跳转。
使用 getUrlParam 函数获取 URL 参数。
在页面加载时,根据赛事 ID 获取赛事详情,并动态生成比赛阶段按钮和比赛结果卡片。

document.getElementById('homepage').addEventListener('click', function() {
    window.location.href = 'index.html';
});

document.getElementById('schedule').addEventListener('click', function() {
    window.location.href = 'DailyFixtures.html';
});

document.getElementById('medal').addEventListener('click', function() {
    window.location.href = 'medal.html';
});

document.getElementById('match-table').addEventListener('click', function() {
    window.location.href = 'MatchUps.html';
});

function getUrlParam(name) {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get(name);
}

// 页面加载时自动填充页面
window.onload = async function() {
    // params的eventId与gender处理的得到详细赛程的文件名
    const eventId = getUrlParam('eventId');
    const id = getUrlParam('id');
    const gender = getUrlParam('gender')==='M'?'1':'2';
    const phaseCode = getUrlParam('phaseCode');
    if (eventId) {
        const url = `http://120.46.58.99:9090/detail?eventId=${eventId}_${gender}`; 
        try {
            const response = await fetch(url);
            if (!response.ok){
                throw new Error(`HTTP error! Status: ${response.status}`); // Check for HTTP errors
            }
            const data = await response.json();
            if (data.code === "-2") {
                alert(data.msg);
                window.history.back();
                return;
            }
            // 根据phaseCode可定位
            displayEvent(data,id,phaseCode);
        } catch (error) {
            alert(error);
            console.error('Fetch error:', error);
        }
    } else {
        console.error('Event ID not provided in the URL'); // Handle missing event ID
    }
}

7.5对阵图

<div class="container">:包含所有内容的容器。
<div class="header">:包含标题和菜单。
<div class="stage">:显示比赛阶段(1/4决赛、半决赛、决赛)。
<div class="legend">:显示比赛结果的缩写说明(AET: 加时赛后,PSO: 点球大战)。
<div class="frame">:包含比赛组件。
<div class="match-component">:单个比赛的组件,显示对阵双方的国旗、队伍名称和比分。
<div class="match-extended-component">:扩展的比赛组件,用于显示决赛和铜牌赛,包含额外的比赛标题。

<div class="container">
    <div class="header">
        <div class="header-title">
            <h2>足球-男子</h2>
            <h1>对阵表</h1>
        </div>
        <div class="menu">
            <div class="active">对阵表</div>
            <div id="schedule">赛程</div>
            <div id="medal">奖牌榜</div>
        </div>
        <div class="home-button" id="homepage">首页</div>
    </div>
    <div class="stage">
        <div>1/4决赛</div>
        <div>半决赛</div>
        <div>决赛</div>
    </div>
    <div class="legend">
        <div>AET : 加时赛后</div>
        <div>PSO : 点球大战</div>
    </div>
    <div class="frame">
        <!-- Match components go here -->
    </div>
</div>

使用Flexbox进行布局,使内容居中。
设置背景图片、字体、颜色等样式。
使用绝对定位来精确放置元素。
设置响应式布局,使网页在不同设备上都能良好显示。

body {
    margin: 0;
    font-family: Microsoft YaHei;
    background: white;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}
.container {
    width: 90%;
    max-width: 1280px;
    height: auto;
    position: relative;
    margin-top: -250px;
}
.header {
    width: 100%;
    height: 350px;
    position: relative;
    background: url('./image/background2.png') no-repeat center center;
    background-size: cover;
}
.menu {
    position: absolute;
    left: 50%;
    top: 200px;
    transform: translateX(-50%);
    display: flex;
    justify-content: space-around;
    width: 422px;
    height: 50px;
    background: rgba(255, 255, 255, 0.8);
    box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25);
    border-radius: 15px;
    padding: 5px 0;
    margin-top: 50px;
}

为.team-name和.team-name-extended添加鼠标悬停和移出事件,改变背景颜色和文字颜色,增强用户交互体验。
为#homepage、#schedule和#medal添加点击事件,实现页面跳转功能。

document.querySelectorAll('.team-name, .team-name-extended').forEach(item => {
    item.addEventListener('mouseover', function() {
        const countryName = this.textContent;
        document.querySelectorAll('.team-name, .team-name-extended').forEach(el => {
            if (el.textContent === countryName) {
                el.style.backgroundColor = 'purple';
                el.style.color = 'white';
            }
        });
    });
    item.addEventListener('mouseout', function() {
        const countryName = this.textContent;
        document.querySelectorAll('.team-name, .team-name-extended').forEach(el => {
            if (el.textContent === countryName) {
                el.style.backgroundColor = '';
                el.style.color = 'black';
            }
        });
    });
});

7.6了解更多

布局与格式与首页相似,不多做赘述

8.心路历程与收获

8.1 222200125郑韵感想

项目伊始,我们团队成员之间进行了充分的沟通,明确了各自的职责和任务。我们意识到,只有每个人都发挥出自己的长处,团队才能高效运转。在结对编程的过程中,我和我的搭档轮流编写代码和审查代码,这种模式让我们能够即时解决问题,同时也确保了代码的质量和一致性。

在编码过程中,我们也明确了代码规范的内容包括命名约定、注释风格和代码结构等。遵循统一的代码规范不仅让代码更加易于阅读和维护,也减少了因风格不一致带来的潜在错误。我们也意识到,良好的代码规范是团队协作的基石。

8.2 222200305卢禧感想

在项目执行的过程中,我们发现正如构建之道中所说的,代码复审是结对编程中不可或缺的一部分。每次编写完一个功能模块后,最好是要进行代码复审。在这个过程中,不仅要检查代码的功能是否正确,还要检查代码是否遵循了既定的规范,是否存在潜在的性能问题。复审过程中,我们经常能够发现一些在编写时未注意到的问题,这大大提高了代码的可靠性。

同时,在处理和填充页面数据时,合理分析与规划是至关重要的,因为这不仅影响数据的准确性和可用性,还直接影响到用户界面的友好度和用户体验。你需要明确页面需要展示哪些数据以及这些数据的来源。收集数据时,确保数据的完整性和准确性。也要考虑数据的多样性和覆盖范围。

这次项目,对个人而言,可以自己的编程技能,更重要的是,学会了如何与他人合作,如何进行有效的沟通和协调。团队的力量远远超过个人,而良好的团队合作能够创造出超出预期的成果。

9.队友评价

9.1 222200125郑韵对222200305卢禧的评价

在这次的项目中222200305卢禧同学承担了大部分的数据爬取和整理工作,并且帮助进行前后端
的连接,页面的跳转实现等等工作。并且在合作过程中不排斥学习前端的内容,注重细节,为页面布局做了一些细节上的调整,同时在合作过程中和我充分沟通充分交流,让项目得以高效稳定地进行。

9.2 222200305卢禧对222200125郑韵的评价

在本次项目中,222200125同学负责了初始版本静态页面的构建、页面细节的精细调整,以及对阵图的关键实现等核心任务。尽管这是她首次涉足前端领域,但她展现出了积极的学习态度和迅速的学习能力,很快就掌握了前端页面开发的基本技能。在项目的合作过程中,她每天都主动与团队沟通,确保每日的任务和目标得到明确和及时的执行。即使面临时间安排上的挑战,她也能够灵活地调整自己的工作计划,以确保项目的顺利进行。与222200125同学的合作体验非常愉快,她的专业精神和团队精神为项目的成功贡献了重要力量。

...全文
17 回复 打赏 收藏 转发到动态 举报
写回复
用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创作助手写篇文章吧