139
社区成员
这个作业属于哪个课程 | 2022年福大-软件工程;软件工程实践-W班 |
---|---|
这个作业要求在哪里 | 软件工程实践结对作业一 |
结对学号 | 221900135;221900234 |
这个作业的目标 | 1.实现三个基础功能板块(奖牌总榜、每日赛程、奖牌地图) 2.酌情完成附加功能 3.将项目部署到云服务器 |
其他参考文献 | CSDN、博客园、简书、B站、部分参考资料 |
Personal Software ProcessStages | 预估耗时(分钟) | 实际耗时(分钟) | |
---|---|---|---|
Planning | 计划 | 30 | 40 |
- Estimate | - 估计这个任务需要多少时间 | 15 | 20 |
Development | 开发 | 400 | 520 |
- Analysis | - 需求分析(包括学习新技术) | 200 | 260 |
- Coding Stardard | - 代码规范 | 15 | 15 |
- Discuss | - 结对讨论 | 40 | 50 |
- Coding | - 编码 | 450 | 520 |
- Code Review | - 代码复审 | 30 | 30 |
- Test | - 测试(自我测试、修改代码) | 55 | 60 |
Reporting | 报告 | 60 | 60 |
- Test Report | - 测试报告 | 30 | 40 |
- Size Measurement | - 计算工作量 | 10 | 20 |
- Postmortem & Process Improvement Plan | - 事后总结, 并提出过程改进计划 | 120 | 120 |
合计 | 1455 | 1755 |
对比PSP表格中实际用时和预估用时,发现主要是编码过程和需求分析(学习新技术)差距较大。
主要是学习新技术效率较低,拖慢了该项进程,最开始预估已经预留出了一定的额外时间,但实际上还是超出预计了。下次可以在
过程
中先定好基础编程框架
和(细一点的)功能的实现方向
,然后再去找相关资料学习,避免大量无意义学习。
(eg.之前去B站搜到的Vue语言学习标题是《一周学会Vue》,看到这个已经有点恐慌了,评论区还火上浇油“不愧是大佬只要一周”,实际上本次开发不需要全面掌握,只要了解涉及到的部分技巧就可以顺利完成编写啦~ 引以为戒引以为戒 )
使用不熟悉的编程语言也很大程度上拖慢了编程效率(
整个过程非常艰难简直是面向百度编程)。下次使用新技术之前可以先多查阅相关的资料视频,定好基础框架之后也不会脑子浆糊一样一团糟了。编程过程要尽量目标明确,功能模块封装实现会让代码的阅读性更好,也能帮助梳理思路,让编码过程更加顺畅。
我们原本打算做前后端分离的网站,前端用vue-cli的脚手架,后端用Node.js。但是因为我们不熟悉基于 Node.js 的构建工具。于是选择使用前后端不分离的形式来进行开发。具体情况如下:
相关技术:CSS、HTML、Vue、ElementUI、Echarts
相关工具:VSCode IDEA
数据库:SQlite
代码托管平台:Gitcode
【该爬取行为仅用于课程教学】
数据来源主要是直接对某CCTV冬奥栏目的数据获取然后保存于json格式文件
首页
可以点击导航栏进行页面跳转,首页轮播图展示2022冬奥精彩时刻。
奖牌总榜
奖牌地图
查询赛程
了解更多
我们根据我们上次结对作业的原型,把这次作业分成了六个界面,分别是首页、奖牌总榜、奖牌地图、查询赛程、了解更多和导航栏。
首页
我们通过
CDN引入VUETIFY
,实现可选择调节的轮播图来进行冬奥会的精彩展示。
奖牌总榜
我们通过
CDN引入VUETIFY
引入基于VUE.js的UI-element,实现可点击表格头部对奖牌进行升序和降序,同时在奖牌榜的右下角实现可选展示行数和分页。
奖牌地图
首先,我们在网上找到了世界热力图ECHARTS组件,然后通过css调整地图的样式,在JavaScript中存入国家的奖牌数据,最后通过
tooltips
这个属性实现了鼠标移动到对应国家显示对应国家的奖牌数据。
查询赛程
最开始是想使用
JDBC
进行数据库连接和数据查询,但是由于数据库服务器
部署到云服务器上较为困难,所以改为使用SQLite嵌入式数据库
。数据库返回查询结果之后使用JSTL
的<c:for>标签循环输出展示,实现赛程查询功能。
我们创建了rank_table标存放查询赛程所需数据。表中设有九个字段,(ID、itemcodename……)数据库结构如下。
了解更多
在了解更多的这个界面,我们选择了科普与冬奥吉祥物有关的知识。我们选取了近几届的冬奥吉祥物,通过图文并茂的方式展示了吉祥物的外观名字以及由来。
导航栏
为了提高代码的复用率,我们将导航栏写了一个单独的页面,并用css进行美化,用JavaScript进行导航栏的交互颜色变化,最后我们将导航栏这个界面用
iframe
这个组件引入到每一个界面中。
之前原型的时候就有点难搞,世界地图的贴图数据有点难处理,自己写的话工作量和难度都有点大。不过好在这次找到了相应的echarts组件——world.js,导入之后对照echarts手册,查找部件对应属性进行修改添加,修改图例
format
、增加光标提示信息tooltips
,以及细节方面的处理,让它更加契合我们的整体风格。
因为很久没有用html写页面了(忏悔)所以对整体语法架构都生疏了很多。也是查了各种资料试了很多方法,先是用的Mysql进行的数据库连接,因为IDEA有相关组件
SSMS
用起来会比较方便,但是部署到云服务器上就麻烦很多,因为远程服务器上软件残缺不全都要重新下载安装配置环境。
所以转换方向使用SQLite进行嵌入式数据库编写,这样可以直接将数据库db文件带过去在云服务器上进行部署,节约时间成本。
表单提交最开始是用jsp实现,因为想要实现“点击查询之后刷新页面数据,不进行页面跳转”(动态查询),所以也查了一点资料,像是ajax
(异步请求),但是有和我们的项目框架不合所以放弃了,转而将表单提交到自身,然后对请求request
进行parameter参数校验,刷新整个页面,达到数据刷新的目的。
因为之前web的知识不扎实,对css语法格式比较生疏。引入组件后一直不知道怎么对组件的内部样式进行更改。我们有两个组件都会出现莫名的空白,查了许多资料都没有解决。最后通过
F12
开发者选项一步步的调试,最终才确定了是哪个div,才通过CSS取消了空白。这让我意识到F12
开发者选项是web程序编写过程中是很有帮助的一个武器,可以很好地帮助我们对网页进行排版。
我们的导航栏部署到云服务器上有些页面出现了乱码,有些页面却是正常的。我通过查询一系列阿里云的资料和各种配置都没有解决这个问题。我们甚至挂了阿里云的公件,咨询了阿里云的工程师也没有解决。最后我发现是因为我一开始偷懒直接将导航栏的html文件在网上的网站进行在线转换成JSP文件直接引入。最后我们通过在head部分强调
utf-8
,并且用iframe
引入导航栏,才解决了文字乱码问题。
我们一开始项目的搭建是通过IDEA的webapp的形式,我们很自然地用了IDEA自带的数据库。可是我们部署云服务器的时候发现我们的jsp文件老是因为连接不到数据库而打不开。最后通过查资料和询问同学们,我们改用了嵌入式数据库SQLite,最后才成功地将文件部署到云服务器上。
我们将导航栏打包成组件形式,然后在每个界面使用iframe引入,减少代码冗余。
//css样式
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: rgba(255,255,255,0.5);
}
li {
float: left;
}
li a {
display: block;
color: rgb(10, 0, 0);
text-align: center;
padding: 20px 22px;
text-decoration: none;
}
li a:hover {
background-color: rgb(158, 217, 245);
}
</style>
</head>
//导航栏主体
<body>
<ul>
<li><a class="active" href="firstpage.html">首页</a></li>
<li><a href="medals.html">奖牌总榜</a></li>
<li><a href="medalmap.html">奖牌地图</a></li>
<li><a href="matches.jsp">查询赛程</a></li>
<li><a href="konwmore.html">了解更多</a></li>
</ul>
//点击事件
<script>
let navButtons = document.getElementsByTagName('a');
for (let i = 0; i < navButtons.length; ++i) {
navButtons[i].onclick = function () {
window.parent.location.href = navButtons[i].href;
}
}
</script>
我们通过
CDN引入VUETIFY
实现轮播图
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, height=device-width,user-scalable=no, minimal-ui">
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
//引入轮播组件
<div class="showpicture" id="app">
<v-app>
<template>
<v-carousel>
<v-carousel-item
v-for="(item,i) in items"
:key="i"
:src="item.src"
reverse-transition="fade-transition"
transition="fade-transition"
></v-carousel-item>
</v-carousel>
</template>
</v-app>
</div>
```
我们通过CDN引入VUETIFY引入基于VUE.js的
UI-element
,实现可点击表格头部对奖牌进行升序和降序
,同时在奖牌榜的右下角实现可选展示行数和分页。因为奖牌榜的数据是静态的且数据量很小,于是我们选择直接存在JavaScript中。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
//奖牌榜组件下有空白,通过下面这个css取消空白
<style>
.v-application--wrap {
min-height: 0ch;
}
</style>
<body>
//引入导航栏
<div class="medalnav">
<iframe MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0
SCROLLING=no src="newnav.html" height=“auto” width="100%">
</iframe>
</div>
//引入奖牌榜组件
<div class="medalchart" id="app">
<v-app>
<template>
<v-data-table
:headers="headers"
:items="medalsList"
:items-per-page="15"
class="elevation-1"
></v-data-table>
</template>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
headers: [
{
text: '排名',
align: 'start',
// sortable: false,
value: 'rank',
},
{
text: '国家',
sortable: false,
value: 'countryname'
},
{ text: '金牌', value: 'gold' },
{ text: '银牌', value: 'silver' },
{ text: '铜牌', value: 'bronze' },
{ text: '总数', value: 'count' },
],
medalsList: [
{
rank: "1",
countryname: "挪威",
gold: "16",
silver: "8",
bronze: "13",
count: "37",
}</script>
</body>
</html>
奖牌地图部分我们使用了
echart组件
进行代码实现,使界面简洁美观。
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
option = {
backgroundColor: '#ffffff',
title: {
subtext: '冬奥奖牌地图',
left: 'center',
top: 'top'
},
//设置光标悬停时的提示框
tooltip: {
trigger: 'item',
formatter: function (params) {
return '<div style="border-bottom: 1px solid rgba(255,255,255,.3); font-size: 18px;padding-bottom: 7px;margin-bottom: 7px">'
+ params.data.cname
+ '</div>'
+ '总数:' + params.value
+ "<div></div>"
+ '金牌:' + params.data.gold
+ "<div></div>"
+ '银牌:' + params.data.silver
+ "<div></div>"
+ '铜牌:' + params.data.bronze;
}
},
//设置图例样式
visualMap: {
pieces: [
{min:21},
{min:16,max:20},
{min:11,max:15},
{min:6,max:10},
{min:0,max:5}
],
text:['>20','0'],
splitNumber: 5,
realtime: false,
calculable: false,
color: ['#02a7f0', '#4ec2f5', '#b3e0fb', '#a7e0fa', '#ccedfc']
},
……
}
</script>
……
```
<div class="scheduleSearchCard">
<form id="w0" action="matches.jsp" method="get">
<div class="itemcodenameSearch" display="inline">
<label class="control-label" for="schedulesearch-itemcodename">项目名称</label>
<select id="schedulesearch-itemcodename" class="form-control" name="itemcodename">
<option value="">全部项目赛程</option>
<option value="高山滑雪">高山滑雪</option>
<option value="雪车">雪车</option>
<option value="冬季两项">冬季两项</option>
<option value="越野滑雪">越野滑雪</option>
<option value="冰壶">冰壶</option>
<option value="自由式滑雪">自由式滑雪</option>
<option value="花样滑冰">花样滑冰</option>
<option value="冰球">冰球</option>
<option value="雪橇">雪橇</option>
<option value="北欧两项">北欧两项</option>
<option value="单板滑雪">单板滑雪</option>
<option value="跳台滑雪">跳台滑雪</option>
<option value="钢架雪车">钢架雪车</option>
<option value="速度滑冰">速度滑冰</option>
<option value="短道速滑">短道速滑</option>
<option value="开幕式">开幕式</option>
<option value="闭幕式">闭幕式</option>
</select>
</div>
<div class="startdatecnSearch" display="inline">
<label class="control-label" for="schedulesearch-startdatecn">比赛日期</label>
<select id="schedulesearch-startdatecn" class="form-control" name="startdatecn">
<option value="">全部日期赛程</option>
<option value="02">02-02</option>
<option value="03">02-03</option>
<option value="04">02-04</option>
<option value="05">02-05</option>
<option value="06">02-06</option>
<option value="07">02-07</option>
<option value="08">02-08</option>
<option value="09">02-09</option>
<option value="10">02-10</option>
<option value="11">02-11</option>
<option value="12">02-12</option>
<option value="13">02-13</option>
<option value="14">02-14</option>
<option value="15">02-15</option>
<option value="16">02-16</option>
<option value="17">02-17</option>
<option value="18">02-18</option>
<option value="19">02-19</option>
<option value="20">02-20</option>
</select>
</div>
<div class="venueSearch" display="inline">
<label class="control-label" for="schedulesearch-venuename">场馆</label>
<select id="schedulesearch-venuename" class="form-control" name="venuename">
<option value="">全部场馆赛程</option>
<option value="国家高山滑雪中心">国家高山滑雪中心</option>
<option value="国家雪车雪橇中心">国家雪车雪橇中心</option>
<option value="国家冬季两项中心">国家冬季两项中心</option>
<option value="国家越野滑雪中心">国家越野滑雪中心</option>
<option value="国家游泳中心">国家游泳中心</option>
<option value="云顶滑雪公园">云顶滑雪公园</option>
<option value="首钢滑雪大跳台">首钢滑雪大跳台</option>
<option value="首都体育馆">首都体育馆</option>
<option value="国家体育馆">国家体育馆</option>
<option value="五棵松体育中心">五棵松体育中心</option>
<option value="国家跳台滑雪中心">国家跳台滑雪中心</option>
<option value="国家速滑馆">国家速滑馆</option>
<option value="国家体育场">国家体育场</option>
</select>
</div>
<div class="subbuttun">
<button type="submit" name="Submit" class="scheduleSearch" >查询</button>
</div>
</form>
</div>
<table border="1" width="100%">
<tr>
<th>项目类型</th>
<th>比赛名称</th>
<th>比赛队伍</th>
<th>赛后比分</th>
<th>比赛时间</th>
<th>场馆名字</th>
</tr>
<tbody>
<c:forEach var="row" items="${result.rows}">
<tr>
<td><c:out value="${row.itemcodename}"/></td>
<td><c:out value="${row.title} "/></td>
<td>
<c:if test="${row.homename != \"\"}">
<c:out value="${row.homename}VS${row.awayname}"/>
</c:if>
<c:if test="${row.homename == \"\"}">
<c:out value="非对抗赛"/>
</c:if>
</td>
<td>
<c:if test="${row.homescore != \"\"}">
<c:out value="${row.homescore}:${row.awayscore}"/>
</c:if>
<c:if test="${row.homescore == \"\"}">
<c:out value="无比分信息"/>
</c:if>
</td>
<td><c:out value="${row.startdatecn}"/> </td>
<td><c:out value="${row.venuename}"/> </td>
</tr>
</c:forEach>
</tbody>
</table>
最开始的设想是使用Vue框架,摸索了一段,包括配置node.js环境 和npm,搭建Vue框架,查阅相关资料试着写代码之后,终于!完全被打败了。Vue框架对于纯新手来说有点难懂,框架里的代码编写和实现逻辑实在难懂。
所以我们决定不用框架啦!直接了当就是干(ノ=Д=)ノ┻━┻!干脆放弃沉没成本重新开始之后顺利很多,按照之前讨论的分工重新自己细化、完善、提交、测试,互相看过进度之后又自己修改,提交代码到Gitcode上,最后将整个项目部署到云服务器上(又是一场艰难战争T_T)。
过程中还是有很多困难的,但是一个成熟的软工人是不会被轻易打倒的。不断查找资料修改代码,一次次尝试功能实现,踏着前人的脚印往前走,最终呈现出满意的成果啦~
收获还是很多的,浅显的像是jsp和vue的语法组件学习,以及html、css相关语句的复习;更深层的当然是新的项目经验和团队合作磨合的处理啦~一起讨论一起努力一起熬夜
掉头发的经历是真的很珍贵,就算很久以后想起来这样的时光也会觉得珍惜吧。
超级棒的队友呀!本来平时就在一块玩,步调习惯比较吻合,编程和环境配置的时候遇到问题都一块顺利解决了,讨论过程也是小case啦。虽然写
bug代码的过程很痛苦,但是友好的结对伙伴真是大大减轻了这个过程中的折磨啦~~
超级nice!!对界面设计的嗅觉真的棒,基本上不用操心css样式的事情(滑水脸),工作效率也真的高,一直在鞭策督促我赶工OTZ。合作起来非常省心。
1、Gitcode项目多人合作
2、用echartsjs 实现散点图与table表格双向交互
3、Tomcat的下载与安装
4、Tomcat配置到IDEA
5、IntelliJ IDEA 2020.2 破解版(附永久破解激活方法)
6、VUE中CDN引入VUETIFY,实现轮播图
记录下了实现难点,很赞!
第一次进入首页和奖牌地图页面加载得有点久不知道能否优化一下?
查询赛程页面还是在报错。