142
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 福大软工实践W班 |
|---|---|
| 这个作业要求在哪里 | 作业要求的链接 |
| 结对学号 | 221900228、221900225 |
| 这个作业的目标 | 学会使用git共同协作项目 学会使用Vue框架搭建项目,实现基础、附加功能 基于原型实现项目并作出适当完善 将项目部署到云服务器上 |
| 其他参考文献 | Vue官方文档 highchart图表绘制 Element组件库 |
该爬取行为仅用于课程教学
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | ||
| • Estimate | • 估计这个任务需要多少时间 | 20 | 30 |
| Development | 开发 | ||
| • Analysis | • 需求理解 | 20 | 20 |
| • division of labor | • 分工 | 20 | 20 |
| • Learn technology | • 学习相关技术 | 300 | 420 |
| • Medal map | • 整体布局 | 30 | 60 |
| • Medal map | • 首页 | 30 | 60 |
| • Medal list | • 奖牌总榜 | 120 | 150 |
| • Daily schedule | • 每日赛程 | 150 | 360 |
| • Three schedules | • 三大详细赛程 | 150 | 300 |
| • Medal map | • 奖牌地图 | 120 | 360 |
| • Learn more | • 了解更多和拓展 | 60 | 120 |
| • Group discussion | • 结对讨论 | 90 | 150 |
| • Project deployment | • 项目部署 | 120 | 300 |
| Reporting | 报告 | ||
| • Size Measurement | 计算工作量 | 10 | 15 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 30 |
| 合计 | 1275 | 2395 |
可以看出psp表格实际的时间比预估的时间多了将近一倍
其中与预期区别较大的是编码部分:由于项目开发较早,且未向其他同学询问问题(主要是想尝试自己解决),导致有些问题会卡住较长时间。
其次的就是项目部署部分:这一块的问题在于自己的项目实现了跨域访问,而跟的那个视频是没教我们如何配置的,再加上csdn也没找到相关的说明,拖慢了很长时间。
这是三个没有交互功能的页面
首页
通过查找资料后引入css文件实现的,不过有个缺点就是可能是浏览器兼容性问题导致有些浏览器不能程现真实效果,这一点有待改善。
了解更多
使用了饿了么组件库的标签、轮播图等等组件。
奖牌榜
使用了highchart图表的堆叠柱状图,数据来源于axios从对应的接口获取。
奖牌地图的实现使用了echart图表,数据来源与奖牌榜一样。
功能:
点击查询按钮可以根据筛选查询
查询过程到会显示加载中
可以同切换图表的形式以不同形式呈现
表格以分页的形式呈现
备注事项:
三类赛程之外的赛程显示待开发页面(待开发页面即未实现的那些详细赛程的页面)
点击同类赛程的不同赛程可以呈现不同数据(具体数据从网站的接口获得)
待开发赛程
使用了饿了么的组件
冰壶混双循环赛(图)
高山滑雪混合团体(图+表)
跳台滑雪男子个人大跳台(表)
这类赛程赛程较少,筛选条件比较苛刻
复用了每日赛程的几个组件
这时候复用性就体现出来了,开发很快,就只需要修改属性constCondition,至于切换功能因为没弄对抗图后来给删掉了



由于接口数据可以直接在前端通过axios跨域从冬奥会官网获取,因此我们采取的是前端vue
项目的整体结构
一开始设计的组件图
后来具体实现的组件情况(与一开始有些出入)
详细赛程
奖牌地图
了解更多
每日赛程列表
奖牌榜
导航栏

每次更新页面实现局部更新(更适合导航和点击查看详细赛程的功能),渲染页面更快速
路由器:
script局部代码:
export default new VueRouter({
routes:[
{
name:'Match',
path:'/matchlist',
component:MatchList,
},
{
name:'Medal',
path:'/medallist',
component:MedalList
},
...
...
]
})
路由器:
style局部代码:
.el-menu-item{
min-width:150px;
font-size:20px;
}
.el-carousel__item h3 {
color: #475669;
font-size: 50px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
导航栏:
template:
<el-menu :default-active="this.$router.path" class="el-menu-demo" mode="horizontal" @select="handleSelect"
text-color="#FFFFFF" background-color="#000000" active-text-color="#008AD7" router>
<el-menu-item ><img alt="nav-icon" src="@/assets/nav_icon_tigger.svg" width="61px" height="71px"/></el-menu-item>
<el-menu-item index="/mainpage">首页</el-menu-item>
<el-menu-item index="/medallist">奖牌总榜</el-menu-item>
<el-menu-item index="/matchlist">每日赛程</el-menu-item>
...
...
</el-menu>
方便状态和数据的存取,方便关系较为疏远的组件间传值
export default new Vuex.Store({
modules:{
matchAbout:match,
...
...
}
})
表格
表格及内部的组件也是采用了ELEMENT组件库的部分组件,比如分页、表格、按钮、查询图标、加载、切换等等
加载功能的实现依赖于自定义的数据datagetted,
切换功能依赖于自定义数据showChart对抗图
对抗图需要在渲染前获取数据,所以使用了v-if属性判断是否获取完数据再进行渲染
对抗图需要根据筛选条件进行更新,所以使用了监视属性,对应的matchList一更新就更改渲染数据
template:(在父组件中)
<div class="MatchList">
<el-switch style="display: block" v-model="showChart" active-color="#DEDEDE" inactive-color="#333333"
active-text="图形" inactive-text="表格"></el-switch>
<MatchSelect :constCondition="constCondition"></MatchSelect>
<div v-loading="!dataGetted" element-loading-text="查询数据中">
<MatchBattleChart v-if='showChart' :matchList='matchList'></MatchBattleChart>
<MatchTable v-if='!showChart' :matchList='matchList'></MatchTable>
</div>
</div>
javascript:(筛选框组件中的局部方法)
//设置查询条件
setCondition(){
this.condition+="&startdatecn=2022"+this.date;
if (this.venue!="null")
this.condition+="&venue="+this.venue;
if (this.majorItem!="null")
this.condition+="&itemcode="+this.majorItem+"-------------------------------";
},
//获取比赛列表的方法
getMatchList(){
console.log(this.api+this.condition);
this.dataGetted=false;
var that=this;//下面要用,防止回调函数调用不到vue对象
if (!this.isRightDate(this.date)) {//日期判断
alert("日期有误!请重新选择...");
}
else {
this.setCondition();
this.$axios({ //调用axios对象
method: 'get',
url: that.api+this.condition,
}).then(function (res) {//开始对数据进行处理
//console.log(that.api+this.condition);
that.condition=that.constCondition;//查询后就改回去
if (res.data.startsWith('{"errcode')) {//错误情况
this.$message.error({
duration: 500,
showClose: true,
message: res.data,
type: 'error'
})
}
else {//解析json数据
var jsonData=JSON.parse(res.data.substring(res.data.indexOf('{'),res.data.lastIndexOf('}')+1));//除去错误字符串
that.matchList=jsonData.data.matchList;//比赛数据对象数组赋值
that.dataGetted=true;
}
}).catch(function (err) {//错误处理
...
})
}
javascript:(对抗图组件中)
//初始化数据
mounted(){
var that=this;
this.matchList.forEach(match => {
if (match.homename!=""&&match.awayname!="")
that.chartOptions.series[0].data.push([match.homename,match.awayname,1]);
});
},
//更新图表
watch:{
matchList:{
handler(value){
this.chartOptions.series[0].data=new Array();
value.forEach(match => {
if (match.homename!=""&&match.awayname!="")
this.chartOptions.series[0].data.push([match.homename,match.awayname,1]);
});
return this.matchList;
}
}
},
data(){
return {
...
...
}
}
matchList数组来自上一个组件通过props传值
使用了编程式路由
template:
<el-table :data="matchList" style="width: 100%" :default-sort = "{prop: 'date', order: 'descending'}">
<el-table-column align="center" header-align="center" prop="startdatecn" label="时间" sortable width="180"></el-table-column>
......
<el-table-column align="center" header-align="center" label="数据" width="">
<template slot-scope="scope">
<el-button icon="el-icon-search" @click="viewDetail(scope.row.documentcode)" circle>
成绩公报
</el-button>
</template>
</el-table-column>
</el-table>
跳转方法
viewDetail(documentcode){
var matchPath;
if (documentcode.startsWith('CURXTEAM2')) //冰壶混双循环赛
matchPath='/curlingmatch';
else if (documentcode.startsWith('ALPXTE')) //高山滑雪混合团体
matchPath='/alpineskiing';
else if (documentcode.startsWith('SJPMLH')) //男子个人大跳台
matchPath='/skijumping';
else matchPath='/developingpage';//待开发
this.$router.push({
path:matchPath,
query:{
code: documentcode
}}
);
},
computed:{
//从vuex获取和修改数据
medalList:{
get(){return this.$store.state.medalAbout.medalList;},
set(value){this.$store.dispatch('medalAbout/updateMedalList',value);}
},
...mapState('medalAbout',['api']),
}
...
data() {
return {
dataGetted:false,
CountryRank:[],
CountryGold:[],
CountrySilve:[],
CountryBronze:[],
chart: null,
};
},
//数据初始化函数
initData(){
var TmpData;
ChartData=new Array();
var MedalData=new Array();
MedalData=this.medalList;
console.log(MedalData);
MedalData.forEach(data=>{
this.CountryRank[data.countryname]=data.rank;
this.CountryGold[data.countryname]=data.gold;
this.CountrySilve[data.countryname]=data.silver;
this.CountryBronze[data.countryname]=data.bronze;
TmpData={
name: data.countryname,
value:parseInt(data.gold)+parseInt(data.silver)+parseInt(data.bronze),
}
ChartData.push(TmpData);
console.log(TmpData);
})
console.log(ChartData);
},
//数据渲染方面用echarts自带的tooltip组件,在formatter函数中return html代码,并从数组中根据国家名字返回数据。
tooltip: {
trigger: 'item',
formatter: function (val) {
...
}
//return val.data.name + ': ' + val.data.value
}
},
//颜色划分方面,用echarts自带的 visualMap组件
visualMap: {
type: 'piecewise',
pieces: [ //自定义『分段式视觉映射组件(visualMapPiecewise)』的每一段的范围,以及每一段的文字,以及每一段的特别的样式
...
],
},
历程:
遇到了许许多多不同方面的问题(这里就不一一举例了),有些问题困扰了许久,过程是痛苦的,但在最终解决的时候是很有收获感的
遇到的问题不止这些,只是忘记记录了...
收获:
首先是意识到组件的内聚降耦的重要,越大的项目越需要更好的可复用性,不然代码会有点乱,
比如本项目的某些地方写的不太好。然后是顺便巩固了下寒假学的一些Vue相关的知识,又在原来的基础上学习了vuex和router,还解决了之前没遇到的许多问题,同时还练习了如何在Vue项目中使用Element组件和highchart图表。
本次项目历程中感觉最难的就是给highchart传值,有些图表需要导入的js文件和它备注的不太一致,刚开始对图表的传值也不太熟悉,导致效率不是很高。
1.学习了vue相关知识并进行运用。
2.学习了echarts的传值,根据获取的数据填入data中。
3.部署云服务器的时候在跨域问题中遇到了些麻烦,下面这张图是本地中vue.config.js的配置

部署到服务器上该配置失效

在csdn进行搜索时,下述三个链接都是通过配置宝塔本地上的nginx代理
链接1
链接2
链接3
尝试了许多方法后发现该配置根本无法生效,后来经过自己的思考和尝试,在宝塔的网站页面中直接对刚刚部署的网站点击设置,进行配置文件的修改,得以配置成功。

思考:在遇到问题时,不能盲目的搜索和相信,尤其是配置问题时,这跟文章的时效性、版本的更迭和本机等配置都有很大的关系。
就像上述问题中,宝塔网站页面的设置两字很明显,我却被搜索引擎蒙蔽了双眼,浪费了许多时间,希望以后解决问题时不能仅仅依赖于搜索引擎,甚至是迷信,要注入自己的思考。
1、221900225_XXL To 221900228_YXJ:
在项目构建和整体布局方面做了大部分工作,我还在学vue的时候队友已经写了挺多了,督促了我的学习和进度,对待作业认真负责,积极性高。
2、221900228_YXJ To 221900225_XXL:
学习能力强(能直接看代码学习),善于思考(比如这个云服务器的config配置文件配置
有被折磨到) ,执行任务积极不拖沓(分配任务的时候立即执行)。