这个作业属于哪个课程 | 2302软件工程社区 |
---|---|
这个作业要求在哪里 | 结对第二次作业–编程实现 |
结对学号 | 222100323,222100325 |
这个作业的目标 | 通过之前学习过的web前后端技术,将上次的原型设计编程实现其中的基础功能。 |
其他参考文献 | 《构建之法》、《Git版本控制实战》、《数据库设计与优化》、《web程序设计》 |
目录
1. git仓库链接和代码规范链接
1.1 git仓库链接
1.2 代码规范链接
2. PSP表格
PSP | Personal Software Process Stages | 预估时间(分钟) | 实际时间(分钟) |
---|---|---|---|
步骤一 | 项目规划与准备 | ||
1 | 确定团队合作方式,建立在Git上的合作流程。 | 60 | 75 |
2 | 选择合适的开发语言和框架,确保平台兼容性。 | 30 | 20 |
3 | 设计项目目录结构,创建项目仓库并设置好.gitignore。 | 60 | 60 |
4 | 编写README.md,包括作业链接、结对学号、项目介绍等内容。 | 20 | 20 |
步骤二 | 基础功能实现 | ||
5 | 实现选手信息页面,包括展示选手的国家、姓名、性别和出生日期。 | 180 | 200 |
6 | 开发每日赛况页面,展示每天的比赛类型、参与选手和比赛时间,并支持点击查看详细情况。 | 240 | 260 |
7 | 完成详细赛况页面,展示比赛成绩,包含参赛选手、排名、积分等信息。 | 500 | 620 |
8 | 设计并实现奖牌榜页面,展示各个国家的获奖情况。 | 150 | 170 |
步骤三 | 附加功能实现 | ||
9 | 创建“了解更多”页面,介绍世界游泳锦标赛的背景,吸引用户对比赛的兴趣。 | 120 | 130 |
10 | 添加更多特色功能,增加网页的吸引力。 | 180 | 190 |
步骤四 | 部署与提交 | ||
11 | 部署项目到云服务器,确保网站能够正常访问。 | 200 | 240 |
12 | 编写代码规范文件codestyle.md,参考大公司推荐的规范或官方规范。 | 60 | 70 |
合计 | 1800 | 2055 |
3. 云服务器访问链接
4. 成品展示
4.1 主页(HOME)
-
显示了我们小组以及世界游泳锦标赛的Logo。
-
页面中心有一个导航栏,包括首页、赛程、奖牌榜、成绩、了解更多和运动员个人信息六个个链接,、当鼠标悬停时,对应字体放大加粗,提升用户体验,当用户点击可跳转到相应页面。
-
展示了比赛的标题、日期和地点信息。
-
描述了游泳比赛的特点,包括充满激情、竞争激烈和清新爽快的特点。
-
页面采用了背景图片,并设置了一些样式,如字体、颜色、布局等,使页面内容更具吸引力。
4.2 赛程(SCHEDULE)
-
每日赛程展示:
显示每日的比赛安排,包括比赛类型、当天比赛的具体时间以及比赛阶段(预赛、半决赛、决赛)。
-
详细赛程查看:
用户可以通过点击赛程信息(Event Details)来跳转页面以查看详细的比赛安排,包括参赛人员、比分情况、比赛进程等信息。
-
日期选择功能:
提供下拉菜单或其他方式让用户选择不同日期,以便查看选定日期的赛程安排和结果。这样用户可以方便地浏览不同日期的比赛情况。
通过以上基本功能,赛程(SCHEDULE)模块能够帮助用户了解每日的比赛安排、结果,并提供方便的日期选择功能,让用户能够轻松查看不同日期的赛事情况。
4.3 奖牌榜(MEDAL TABLES)
界面展示:
-
奖牌统计:
统计并展示本次比赛中各国家的获奖情况,包括金牌、银牌、铜牌的数量,以及总奖牌数。按照金牌数量进行排序,以展示各国在比赛中的表现。
-
表格展示:
以表格的形式呈现奖牌榜信息,包括国家名称、金牌数量、银牌数量、铜牌数量和总奖牌数等数据。用户可以通过表格直观地了解各国的排名和奖牌数量。以及当鼠标悬停在具体国家对应的某一行时,对应行会通过放大加粗,让用户更好地看到对应国家的奖牌信息,提升用户体验。
-
前三名柱状图展示:
针对前三名国家(金牌数量最多的前三个国家),用柱状图动态展示其排名情况,使用户更直观地看到前三名国家的差距和比较结果。
通过以上基本功能,奖牌榜模块可以为用户提供清晰的奖牌统计信息,帮助用户了解各国在比赛中的表现,并通过可视化的方式直观呈现前三名国家的排名情况。
4.4 成绩(RESULTS)
-
赛事结果展示:
详细展示每项赛事的结果,包括初赛、半决赛、决赛等不同阶段的比赛结果。用户可以通过点击赛事名称展开来查看详细的比赛信息。
-
得分情况展示:
用户可以通过点击“EVENT DETAILS”号来获取更加详细的得分情况,包括各个参赛选手或队伍在比赛中获得的具体得分情况。
-
赛事阶段划分:
将赛事结果按照不同阶段(初赛、半决赛、决赛)进行清晰的分类和展示,使用户能够方便地找到所需的比赛结果。
通过以上基本功能,赛事结果模块能够帮助用户全面了解不同赛事的结果,深入了解选手的表现,并提供方便的交互方式让用户能够轻松查看和探索各项赛事的详细情况。
4.5 了解更多(MORE)
界面展示:
-
图片展示:
用轮播图的形式展示了四张图片,形成一个类似幻灯片的结构。 -
轮播图导航:
提供了两个按钮,分别用于切换到上一张和下一张图片。
-
段落信息展示:
通过三个<div class="paragraph">
元素展示了关于世界水上运动锦标赛的相关信息,包括比赛的历史、主办方、举办地点的选择方式以及其国际化和包容性的特点,向用户提供了解改赛程的历史背景以及特点的渠道。
4.6 运动员个人信息(ATHLETE)
界面展示:
ATHLETE页面是一个用来展示跳水运动员信息的表格页面。每一行对应一个跳水运动员,列包括以下内容:
- 国家:显示该跳水运动员所代表的国家或地区。
- 个人形象:是一个包含该运动员照片或头像的图像。
- 名字:该跳水运动员的姓名。
- 性别:显示该运动员的性别,男(Male)或女(Female)。
- 出生年月:显示该运动员的出生日期,以年-月-日的格式呈现。
通过这个表格,用户可以方便地浏览不同跳水运动员的基本信息。这样的设计使得用户可以快速了解每位运动员的背景信息,以及当用户鼠标悬停在具体某一运动员对应行上,该行会自动放大加粗,以便用户更好地获取信息,有助于提高用户体验和页面的实用性。
4.7 关键特性描述
-
交互性:
具有一定的交互性,例如用户可以点击赛程进行展开、收起,快速找到特定比赛信息。 -
更新与实时性:
确保赛程信息的及时更新和实时性,以反映最新的比赛安排和结果。 -
用户友好性:
界面设计应简洁清晰,信息呈现直观明了,用户能够方便快速地找到所需的赛程信息。
5. 结对讨论过程描述
我们的结对讨论如下:
-
审查原型设计: 我们一起审查原型设计,确保大家对页面布局、功能交互有一致的理解。比如确认各个页面的元素和交互效果是否符合预期。
-
技术实现方案讨论: 我们会讨论如何根据原型设计选择合适的技术实现方案。比如哪些框架适合实现特定的页面效果,以及如何保证页面在不同设备上的兼容性等问题。
-
任务分工: 我们会根据原型设计的具体页面和功能,进行任务分工,明确谁负责哪个部分的实现工作。可能会按照页面或功能模块来划分任务。
-
解决技术难题: 如果在实现过程中遇到技术难题,我们会共同讨论并寻求解决方案。这可能涉及在网上查找相关文档、教程,或者向其他开发者寻求帮助。
-
代码审查与反馈: 在实现过程中,我们会相互进行代码审查,提出改进建议,并就代码质量、性能优化等方面给予反馈,以确保最终的实现符合预期。
-
持续沟通与协作: 我们会保持持续的沟通与协作,及时分享进展和遇到的问题,以便及时调整和协作解决,确保项目顺利进行。
通过以上结对讨论过程,我们更好地理解了任务需求,高效地实现原型设计,确保最终的实现符合预期。
6. 设计实现过程
6.1 过程步骤描述
-
页面布局与导航设计:
首先,确定页面整体结构和布局,包括放置小组和比赛Logo的位置,导航栏的设计,比赛标题以及相关信息的展示方式。使用HTML和CSS来实现页面布局,确保页面内容层次清晰、美观。 -
导航栏交互设计:
设计导航栏的交互效果,包括鼠标悬停时字体放大加粗的效果,以及点击链接跳转到对应页面的功能。使用JavaScript来实现这些交互效果,提升用户体验。 -
背景图片与样式设置:
选择合适的背景图片,并根据页面主题设置字体样式、颜色、布局等,使页面内容更具吸引力。通过CSS样式表对页面元素进行美化,确保视觉效果达到预期。 -
赛程模块设计与实现:
- 数据库设计:设计数据库表
scheduletable
,包括日期、时间、比赛项目、阶段等字段,用于存储赛程信息。 - 后端开发:
- 编写 PHP 后端脚本,建立与数据库的连接,编写 SQL 查询语句从数据库中获取赛程数据。
- 将查询到的赛程数据转换为 JSON 格式,并通过 HTTP 响应返回给前端页面。
- 前端开发:
- 设计前端页面,包括选择框和用于展示赛程信息的div,使用 HTML 和 CSS 实现页面布局。
- 使用 JavaScript 监听选择框的变化事件,向后端发送 AJAX 请求获取赛程数据,并根据返回的数据动态生成赛程信息并展示在页面上。
- 交互设计:设计页面交互逻辑,包括根据选择框的数值切换赛程信息的展示,在页面上清晰地展示不同日期的赛程安排。
- 奖牌榜模块设计与实现:
-
数据库设计:
- 数据库设计包括确定数据库中的表结构以及字段设计。在这个数据表中包括国家名称、金牌数、银牌数、铜牌数和总奖牌数字段,使用了MySQL数据库。
-
后端开发:
- 后端开发主要负责处理前端页面的请求,并根据请求从数据库中获取相应的数据,然后将数据以JSON格式返回给前端页面。
- 后端使用PHP来编写。PHP连接MySQL数据库,执行查询操作,并将查询结果转换成JSON格式输出。
-
前端开发:
- 前端开发负责构建页面结构、样式和交互逻辑,使用户能够直观地浏览和操作页面。使用HTML、CSS和JavaScript来实现页面的布局、样式和动态效果。
-
交互设计:
- 交互设计关注用户与系统之间的交互体验,包括页面导航、数据展示方式、用户操作等方面。
- 在这个案例中,交互设计通过定时切换效果、国旗显示以及图表库实现柱状图展示增强了页面的动态性和吸引力,提升了用户的浏览体验。
- 同时,页面中的菜单导航和表格交互也是交互设计的一部分,使用户可以方便地查看和操作页面内容。
- 成绩模块设计与实现:
-
前端部分:
- HTML 部分定义了页面结构和内容,包括页面布局、图片元素、链接等。
- CSS 部分定义了页面的样式,通过外部样式表 results.css 控制元素的外观和布局。
- JavaScript 部分包括两个事件监听器:
- 第一个监听器在页面加载完成后会获取 URL 参数中的
showDiv
值,并根据该值显示对应的 div 元素。 - 第二个监听器发送 XMLHttpRequest 请求到
results.php
获取数据,并根据返回的 JSON 数据动态生成并插入表格到页面中。同时,也包含了点击事件处理函数detail(i)
和events(i)
,用于显示/隐藏详细信息和切换不同比赛阶段的成绩表格。
- 第一个监听器在页面加载完成后会获取 URL 参数中的
-
后端部分(PHP):
PHP 部分连接数据库,从数据库中获取运动员信息,并以 JSON 格式返回给前端 JavaScript 部分处理。
- 了解更多模块设计与实现:
-
HTML 结构:
- 在 HTML 中定义了轮播图的结构,包括包含轮播图的容器和每张图片的元素。
- 通过设置不同的 class 和 id 来区分不同的元素,如包含轮播图的容器、每张图片等。
-
CSS 样式:
- 使用 CSS 样式对轮播图进行布局和美化,设置了图片的样式,包括宽度、高度等。
- 通过设置不同的样式类来定义不同元素的外观和布局。
-
JavaScript 实现:
- JavaScript 部分定义了一些变量和事件监听器,用于控制轮播图的切换和显示。
- 初始化了轮播图的初始状态,并定义了
showSlides
函数用于显示特定索引的图片。 - 通过监听“上一个”和“下一个”按钮的点击事件来切换到上一张或下一张图片。
- 使用
setInterval
函数定时切换轮播图,实现自动播放功能。
-
功能实现:
- 用户可以通过点击按钮切换到上一张或下一张图片,也可以自动播放轮播图。
showSlides
函数控制显示特定索引的图片,实现了切换效果。- 通过设置定时器和事件监听器,实现了用户交互和自动播放功能。
- 运动员个人信息模块设计与实现
-
数据库设计:
创建personinfo
表存储运动员信息,包括国家、姓名、性别、出生日期和项目。 -
前后端开发:
前端页面展示美化的表格,JavaScript通过请求向服务器获取数据,服务器端使用PHP连接数据库并返回JSON格式数据。 -
交互设计:
用户可以在页面上直观地查看运动员信息,数据交互流程保证了用户可以快速获取所需信息。
-
测试与调优:
在完成以上设计与实现后,进行页面功能测试和样式调优,确保各模块功能正常运行且页面展示符合预期。根据测试结果和反馈进行必要的修改和优化,提高页面的稳定性和用户体验。 -
部署与发布:
最终将设计完成的页面部署到服务器上,并发布给用户访问。确保页面能够在不同设备和浏览器上正常显示,并随时准备处理可能出现的问题或需求变更。
6.2 功能结构图
7. 代码说明
7.1 基础功能
7.1.1 选手信息
- HTML部分:
- 包含一个表格
<table>
用于展示运动员信息。 - 使用CSS样式美化表格和页面布局。
- 引入一个JavaScript文件
athlete.js
,用于处理数据请求和展示。
- 包含一个表格
<table id="athlete_table">
<tr>
<th>Country</th>
<th>Athlete</th>
<th>Gender</th>
<th>DOB</th>
<th>Discipline</th>
</tr>
</table>
<script src="athlete.js"></script>
- JavaScript部分:
- 在DOM加载完成后,通过
XMLHttpRequest
对象向服务器请求数据。 - 当收到服务器响应后,解析JSON数据并动态构建表格内容。
- 将每个运动员的信息以表格行的形式插入到HTML表格中。
- 在DOM加载完成后,通过
document.addEventListener('DOMContentLoaded', function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'athlete.php', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log('Response:', response);
var dataTable = document.getElementById('athlete_table');
if (response && Array.isArray(response)) {
var tableHtml = '</tr>';
response.forEach(function(item) {
tableHtml += '<tr>';
tableHtml += '<td><img src="' + item.Flag + '" alt="' + item.Country + '" class="flag">' + item.Country + '</td>';
tableHtml += '<td><img src="' + item.Image + '" alt="' + item.Athlete + '" class="flag">' + item.Athlete + '</td>';
tableHtml += '<td>' + item.Gender + '</td>';
tableHtml += '<td>' + item.DOB + '</td>';
if (item.Discipline == "Diving")
tableHtml += '<td><img src="image/跳水.png" alt="Diving" class="diving">' + item.Discipline + '</td>';
else {
// Handle other disciplines if needed
}
tableHtml += '</tr>';
});
if (dataTable) {
dataTable.insertAdjacentHTML('beforeend', tableHtml);
} else {
console.error('Element with ID "data_table" not found');
}
} else {
console.error('Invalid or empty response');
}
} else if (xhr.status !== 200) {
console.error('Failed to fetch data from the server.');
}
};
xhr.send();
});
- PHP部分:
- PHP脚本用于从MySQL数据库中获取人员信息。
- 将数据库查询结果转换为JSON格式,并输出给前端页面。
<?php
$conn = new mysqli('localhost', 'root', '', 'demo');
$result = $conn->query("SELECT * FROM personinfo");
$data = array();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$data[] = $row;
}
}
mysqli_free_result($result);
$conn->close();
header('Content-Type: application/json');
echo json_encode($data);
?>
7.1.2 每日赛况
- HTML部分:
- 在页面上创建了一个下拉选择框(select),用于选择不同的日期。
- 创建了两个具有不同 id 的
div
元素,分别用于展示不同日期的赛事安排。
<div id="choice">
<select id="choices" >
<option value="option1">Thursday 18th January</option>
<option value="option2">Friday 19th January</option>
</select>
</div>
<div id="option1">
<div>
<div class="head1"><span>Thursday 18th</span></div>
<div class="head2">January</div>
</div>
</div>
<div id="option2">
<div>
<div class="head1"><span>Friday 19th</span></div>
<div class="head2">January</div>
</div>
</div>
</div>
<script src="schedule.js"></script>
- JavaScript部分:
- 监听日期选择框的变化事件,根据选择的日期展示对应的赛事安排区域。
- 根据选择的选项值,控制不同日期对应的赛事安排区域的显示与隐藏。
if (xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log('Response:', response);
var dataTable_1=document.getElementById('option1');
var dataTable_2=document.getElementById('option2');
if (response && Array.isArray(response)) {
var tableHtml_1='<br>';
var tableHtml_2='<br>' ;
var i=1;
var j=1;
response.forEach(function(item) {
if(item.Date=='Thursday 18th January'){
tableHtml_1+='<div class="event">';
tableHtml_1+='<div id="event'+i+'"></div>';
tableHtml_1+='<div class="time">'+item.Time+'</div><img src="image/跳水.png" alt="driving">';
tableHtml_1+='<div class="name">'+item.Event+'</div>';
tableHtml_1+='<div class="'+item.Stage+'">·'+item.Stage+'</div>';
if(item.Stage=='Finals')
tableHtml_1+='<img src="image/金牌.png" style="width:2vw; height:2vw;" alt="金牌">';
tableHtml_1+='<div class="details">EVENT DETAILS</div><img src="image/箭头_向右.png" class="arrow" alt="->"></div>';
i++;
}
if(item.Date=='Friday 19th January'){
tableHtml_2+='<div class="event">';
tableHtml_2+='<div id="event'+j+'"></div>';
tableHtml_2+='<div class="time">'+item.Time+'</div><img src="image/跳水.png" alt="driving">';
tableHtml_2+='<div class="name">'+item.Event+'</div>';
tableHtml_2+='<div class="'+item.Stage+'">·'+item.Stage+'</div>';
if(item.Stage=='Finals')
tableHtml_2+='<img src="image/金牌.png" style="width:2vw; height:2vw;" alt="金牌">';
tableHtml_2+='<div class="details">EVENT DETAILS</div><img src="image/箭头_向右.png" class="arrow" alt="->"></div>';
j++;
}
});
tableHtml_1+='<br><br><br><br>';
tableHtml_2+='<br><br><br><br>';
if (dataTable_1) {
dataTable_1.insertAdjacentHTML('beforeend', tableHtml_1);
}
else {
console.error('Element with ID "option1" not found');
}
if (dataTable_2) {
dataTable_2.insertAdjacentHTML('beforeend', tableHtml_2);
} else {
console.error('Element with ID "option2" not found');
}
}
else {
console.error('Invalid or empty response');
}
}
document.getElementById('choices').addEventListener('change', function() {
var selectedOption = this.value;
var div1 = document.getElementById('back1');
var div2 = document.getElementById('back2');
if (selectedOption === 'option1') {
div1.style.display = 'block';
div2.style.display = 'none';
} else if (selectedOption === 'option2') {
div1.style.display = 'none';
div2.style.display = 'block';
}
});
- PHP部分:
- 建立与数据库的连接,并查询赛事日程表数据。
- 将查询结果转换为 JSON 格式并输出,以便前端 JavaScript 处理。
$conn = new mysqli('localhost', 'root', '', 'demo');
$result = $conn->query("SELECT * FROM scheduletable");
$data = array();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$data[] = $row;
}
}
mysqli_free_result($result);
$conn->close();
header('Content-Type: application/json');
echo json_encode($data);
该模块的相关代码根据用户选择的日期来展示不同赛事安排的功能,通过前端 JavaScript 监听事件和后端 PHP 连接数据库实现数据的动态展示。
7.1.3 详细赛况
- 页面加载完成后根据 URL 参数显示特定的 div:
document.addEventListener('DOMContentLoaded', function() {
var urlParams = new URLSearchParams(window.location.search);
var showDiv = urlParams.get('showDiv');
if (showDiv) {
var divToDisplay = document.getElementById(showDiv);
if (divToDisplay) {
divToDisplay.style.display = 'block';
divToDisplay.scrollIntoView();
}
}
});
- 通过 XMLHttpRequest 获取结果数据并动态生成表格:
document.addEventListener('DOMContentLoaded', function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'results.php', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
// 解析响应数据并生成表格
} else if (xhr.status !== 200) {
console.error('Failed to fetch data from the server.');
}
};
xhr.send();
});
- 展开/收起事件详情的函数:
function detail(i) {
var hiddenContent = document.getElementById('hidden'+i);
if (hiddenContent.style.display === "none") {
hiddenContent.style.display = "block";
} else {
hiddenContent.style.display = "none";
}
}
- 切换不同比赛阶段的显示:
function events(i) {
var eve=[];
eve[3]=document.getElementById('Preliminary_score');
eve[2]=document.getElementById('Semifinals_score');
eve[1] = document.getElementById('Final_score');
for(var x=1;x<4;x++){
if(x!=i&&eve[x]!=null)
eve[x].style.display = "none";
if(x==i)
eve[x].style.display = "block";
}
}
7.1.4 奖牌榜
- 前端页面关键代码:
- HTML结构部分,用于展示奖牌榜的表格和国旗图片:
<div id="medalTable">
<!-- 这里用于展示奖牌榜的表格和国旗图片 -->
</div>
- JavaScript部分,定时请求后端接口获取数据,并更新页面展示:
<script>
function updateMedalTable() {
fetch('/api/medaltable')
.then(response => response.json())
.then(data => {
// 更新页面上的奖牌榜表格和国旗图片
// ...
});
}
setInterval(updateMedalTable, 5000); // 每5秒更新一次
</script>
document.addEventListener('DOMContentLoaded', function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'medal_table.php', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log('Response:', response);
var dataTable=document.getElementById('medal_table');
var NO1_flag=document.getElementById('NO1_flag')
var NO2_flag=document.getElementById('NO2_flag')
var NO3_flag=document.getElementById('NO3_flag')
if (response && Array.isArray(response)) {
var tableHtml='</tr>' ;
response.forEach(function(item) {
tableHtml+='<tr>';
tableHtml+='<td>'+item.OverallRank+'</td>';
tableHtml+='<td><img src="'+item.Flag+'" alt="'+item.Country+'" class="flag">'+item.Country+'</td>';
tableHtml+='<td>'+item.Gold+'</td>';
tableHtml+='<td>'+item.Silver+'</td>';
tableHtml+='<td>'+item.Bronze+'</td>';
tableHtml+='<td>'+item.Total+'</td>';
tableHtml+='</tr>';
if(item.OverallRank=="1")
NO1_flag.innerHTML='<img src="'+item.Flag+'" alt="'+item.Country+'">'
if(item.OverallRank=="2")
NO2_flag.innerHTML='<img src="'+item.Flag+'" alt="'+item.Country+'">'
if(item.OverallRank=="3")
NO3_flag.innerHTML='<img src="'+item.Flag+'" alt="'+item.Country+'">'
});
if (dataTable) {
dataTable.insertAdjacentHTML('beforeend', tableHtml);
} else {
console.error('Element with ID "data_table" not found');
}
} else {
console.error('Invalid or empty response');
}
} else if (xhr.status !== 200) {
console.error('Failed to fetch data from the server.');
}
};
xhr.send();
});
- 后端服务器关键代码(使用PHP):
连接数据库部分,建立与数据库的连接,从数据库中获取奖牌榜数据并以JSON格式输出:
<?php
$conn = new mysqli('localhost', 'root', '', 'demo');
$result = $conn->query("SELECT * FROM medaltable");
$data = array();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$data[] = $row;
}
}
mysqli_free_result($result);
$conn->close();
header('Content-Type: application/json');
echo json_encode($data);
?>
通过这些代码,前端页面定时请求后端接口获取数据,并更新页面展示;后端服务器连接数据库获取奖牌榜数据,并将数据以JSON格式返回给前端页面。
7.2 附加功能
7.2.1 了解更多
- HTML 结构的思路描述:
首先,在HTML结构中,我们需要创建一个包含轮播图片和切换按钮的容器。每张图片使用<img>
元素表示,并具有一个共同的类名,以便通过JavaScript操作。同时,我们还需要添加前进和后退按钮,为它们添加相应的点击事件监听器。
<div class="slideshow-container">
<div class="slide">
<img src="image/m1.jpg" alt="Image 1">
</div>
<div class="slide">
<img src="image/m2.jpg" alt="Image 2">
</div>
<div class="slide">
<img src="image/m3.jpg" alt="Image 3">
</div>
<div class="slide">
<img src="image/m4.png" alt="Image 4">
</div>
<button id="prevBtn"><</button>
<button id="nextBtn">></button>
</div>
- CSS 样式的思路描述:
在CSS样式中,我们需要设置轮播图容器的样式,包括其宽度、最大宽度、居中显示等。另外,我们还需要对图片和切换按钮进行样式设置,使其呈现出预期的外观。
.slideshow-container {
max-width: 60vw;
position: relative;
margin: auto;
overflow: hidden; /* 隐藏溢出的部分 */
border: 2px solid #ccc; /* 添加边框 */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影 */
}
.slide {
display: none;
animation: fadeIn 1s ease-in-out; /* 添加淡入动画效果 */
}
.slide img {
width: 60vw; /* 图片宽度100%填充 */
height: 80vh; /* 图片高度100%填充 */
}
- JavaScript 逻辑的思路描述:
在JavaScript部分,我们需要初始化一些变量,如当前显示的图片索引,以及获取所有轮播图片的元素。然后编写函数来显示特定索引的图片,并隐藏其他图片;同时,编写逻辑处理前进和后退按钮的点击事件,以及自动播放功能的设置。
let slideIndex = 0;
const slides = document.querySelectorAll('.slide');
const prevButton = document.getElementById('prevBtn');
const nextButton = document.getElementById('nextBtn');
// 显示初始轮播图
showSlides(slideIndex);
// 点击“上一个”按钮时切换到上一张图片
prevButton.addEventListener('click', () => {
slideIndex--;
if (slideIndex < 0) {
slideIndex = slides.length - 1;
}
showSlides(slideIndex);
});
// 点击“下一个”按钮时切换到下一张图片
nextButton.addEventListener('click', () => {
slideIndex++;
if (slideIndex >= slides.length) {
slideIndex = 0;
}
showSlides(slideIndex);
});
// 自动切换图片
setInterval(() => {
slideIndex++;
if (slideIndex >= slides.length) {
slideIndex = 0;
}
showSlides(slideIndex);
}, 5000); // 切换间隔时间为5秒
function showSlides(index) {
for (let i = 0; i < slides.length; i++) {
slides[i].style.display = 'none';
}
slides[index].style.display = 'block';
}
7.2.2 主页模块
主要是CSS 代码针对页面中的标题元素进行样式设置,使其具有独特的外观和动画效果,使页面中的标题元素呈现出炫丽多彩的外观,吸引用户的注意力。
.title {
text-align: center;
font-size: 5.6vw;
display: flex;
justify-content: center;
align-items: center; /* 添加垂直居中属性 */
position: absolute;
top: 95%; /* 将顶部位置设为页面高度的一半 */
left: 50%; /* 将左侧位置设为页面宽度的一半 */
transform: translate(-50%, -50%); /* 使用 transform 属性进行微调 */
width: 100%; /* 设置标题元素的宽度 */
max-width: 10000vw; /* 设置最大宽度 */
font-family: 'Goudy Stout Bold Oblique', 'Goudy Stout Bold', 'Goudy Stout Normal', 'Goudy Stout', sans-serif;
font-weight: 700;
font-style: oblique;
background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet, red);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: rainbowText 5s linear infinite, brightnessChange 4s linear infinite;
text-shadow: 2px 2px 2px rgba(105, 104, 104, 0.711); /* 添加文字立体阴影效果 */
}
@keyframes rainbowText {
0% { background-position: 0 0; }
100% { background-position: 200% 0; }
}
@keyframes brightnessChange {
0% { filter: brightness(50%); } /* 开始时文字亮度为50% */
50% { filter: brightness(200%); } /* 中间时文字亮度为200% */
100% { filter: brightness(50%); } /* 结束时恢复到50% */
}
8. 问题总结以及解决方案
- AJAX请求错误处理:
问题:AJAX请求可能会因为网络问题或服务器端错误导致请求失败或超时。
解决方案:在前端代码中添加错误处理机制,如设置超时时间、显示加载提示信息或失败提示信息,以便用户得知请求状态。 - 数据格式处理不当:
问题:从后端返回的数据格式不符合前端预期,导致页面无法正确展示数据。
解决方案:在后端确保返回的数据格式统一且符合前端需求,可以使用JSON.stringify()
和JSON.parse()
等方法对数据进行处理和转换。 - 动态内容更新问题:
问题:页面上的动态内容更新不及时,用户无法及时看到最新信息。
解决方案:通过定时刷新技术实现实时更新内容,以及在用户操作时触发更新动作,确保用户可以及时获取最新数据。 - 页面性能问题:
问题:页面加载速度慢、交互卡顿等影响用户体验的性能问题。
解决方案:优化前端代码结构和逻辑,减少不必要的DOM操作和请求次数,避免页面资源过大导致加载缓慢,以及通过JavaScript事件监听器和异步请求优化前端交互体验,确保页面响应速度和交互效果流畅。 - 浏览器兼容性:
问题:不同浏览器对JavaScript和CSS的解析存在差异,可能导致页面在某些浏览器下显示异常。
解决方案:在开发过程中测试并适配不同主流浏览器,根据需要添加特定的CSS前缀或使用JavaScript兼容性库来解决兼容性问题。 - 数据库连接和数据返回异常:
问题:后端与数据库连接出现问题,导致数据无法正确返回或页面加载缓慢。
解决方案:在后端编写的PHP脚本中添加错误处理机制,确保数据库连接稳定,还可以使用缓存技术减少数据库访问次数,提高数据返回速度。
9. 心路历程和阅读收获
9.1 心路历程
222100323林锦晖:完成这样的项目作业,从期待到困难,再到成就和满足,同时也会从合作中获得愉悦和成长,因为这是一个实际应用所学知识的机会,意味着要面对挑战和困难。
在项目进行过程中,遇到了各种各样的技术问题、设计思路上的瓶颈以及与队友的合作协调等挑战。比如,要完成选手信息展示、每日赛况、详细赛况、奖牌榜等基本功能,并可以添加更多特色功能。这些功能的实现需要深入理解数据结构和算法,数据库的导入解析从而获取表中数据并且在网页设计方面也需要有一定的审美和用户体验意识。
这时可能会感到焦虑和挫折,但随着问题一一解决,功能逐步完善,会带来成就感和满足感,同时也会对自己的成长和学习有更深刻的认识。
在与周庆鸿同学在合作开发的过程中有着共同努力、互相学习的愉快经历。这种合作不仅可以加速项目进展,也是学习团队协作和沟通技巧的宝贵机会!
222100325周庆鸿:
一开始,面对这个作业的种种要求,感到有些茫然,不知道该从哪里下手。但是随着两个人之间的讨论,我逐渐明确了项目的整体框架和需求,并开始分析每个功能模块应该如何实现。我和林锦晖同学商讨了数据库设计、页面展示、后端逻辑等方面的问题,逐步理清了思路。
在分工方面,根据每个人的技能和兴趣进行了合理的分配,确保每个人都能发挥自己的优势。我主要负责网页的附加功能的实现、数据库导入、CSS设计以及博客撰写。我们建立了合理的Git分支结构,使得每个人都可以独立地进行开发,并且及时地进行代码合并和解决冲突。
随着时间的推移,逐渐进入了状态,开始按部就班地完成各个功能模块。在这个过程中克服了一些技术上的困难比如浏览器兼容性等问题,查找了大量的资料来解决问题,同时也和林锦晖同学相互交流、讨论,共同攻克了许多难题。最终,我们成功地完成了作业的所有要求,并且部署到了云服务器上。
通过这次合作开发,我学会了如何规划一个复杂项目的开发过程,如何分析和设计数据库模型、如何进行合作开发、如何使用Git协同开发以及如何解决技术上的困难。与队友的密切合作也让我收获颇丰,我们相互学习、相互促进,共同完成了这个挑战性很强的作业!
9.2 《构建之法》(第四章)阅读收获
通过通读《构建之法》(第四章)之后,我们总结出:
在合作编程方面,代码规范和设计规范是非常重要的。代码规范包括代码风格规范和代码设计规范,其中简明易读是一个核心原则,确保代码的可维护性和可读性。在代码风格规范中,要注意缩进、行宽、括号使用、命名规范等,这些规范有助于团队成员之间的协作和代码的统一性。
代码设计规范则强调函数的单一职责原则,错误处理的重要性,以及类的处理方式。确保代码逻辑清晰,错误处理完善,可以提高代码的质量和可靠性。
代码复审是非常重要的环节,通过不同形式的复审可以发现代码中的错误、逻辑问题和潜在的改进空间,同时也有利于我们团队成员之间的经验传承和知识分享。
结对编程则是一种高效的合作方式,通过两个人之间的共同协作,可以提高代码的设计和质量,增强双方的信心和满足感,同时也有利于团队之间的交流和学习。
通过这些规范和方式,可以促进团队合作的效率和质量,提升代码编写的水平和团队的整体能力。在学习过程中,要注重实践和应用这些规范和方式,不断提升自己的编程技能和团队协作能力。
10. 评价结对队友
222100323林锦晖:在实现首页和更多功能的前后端开发以及主要的 CSS 设计方面展现了认真专研的态度,这让整个项目能够顺利推进并取得进展。他对前端技术的深入研究和努力工作使得我们的项目页面看起来更加吸引人,并且功能上也更加完善。
虽然在数据库导入过程中偶尔会出现一些小错误,但这并不影响他在其他方面的表现。错误是在学习和实践过程中不可避免的一部分,重要的是他能够及时发现问题并尝试解决。这种积极的态度和对技术的追求是非常值得肯定的。
总的来说,我的队友在项目中展现出了专业的技术能力和扎实的前端开发功底,通过他的努力和贡献,我们得以共同完成这项任务。我对他的工作态度和成果表示肯定,期待未来能有更多的合作机会!
222100325周庆鸿:在整个项目过程中,林锦晖同学展现出了非常强的时间规划能力和清晰的思维逻辑。他不仅能够明确每个阶段需要完成的任务,而且在实现基本功能时能够快速理清思路。此外,林同学还表现出了吃苦耐劳的品质,当遇到问题时,比如数据库连接以及返回数据格式不正确这些问题时,会投入大量时间和精力进行深入研究,直到找到解决方案为止。
他对待事情认真负责、勤奋上进的态度让整个团队受益匪浅。无论是每天的任务安排还是面对技术难题,他都能以积极的态度去面对并解决。作为一个优秀的队友,他始终保持着高度的工作热情和专业水准,为项目的顺利完成贡献了重要的力量。
希望未来我们还能有更多的机会继续合作,共同克服挑战,创造更多的成就!