这个作业属于哪个课程 | 2020春|S班 |
---|---|
这个作业要求在哪里 | 第二次结对作业 |
结对学号 | 221701415/221701437 |
这个作业的目标 | 某次疫情统计可视化的实现 |
作业正文 | 结对第二次 |
其他参考文献 | 跨域问题处理 |
Github仓库地址和代码链接
作品展示
此次作业采用前后端分离并将后台在云服务器的方式完成,后端技术采用了ssm框架,前端技术采用了通过vue来快速搭建,使用element-ui和echarts来搭建视图.
后端服务器启动
后将后台程序转换为服务器守护进程,可长期访问
数据库部分数据展示
前端页面展示
- 主页面1,将全国的某日数据展示,可以了解一些有关疫情的数据,同时可以通过地图,直观地了解疫情的分布情况。
- 子页面1,将某省的数据展示(如图为湖北),可以通过折线图直观了解到各个数据的增长趋势。
- 子页面1,通过鼠标可以指示某日的情况,也可以通过选择日期,了解某日的数据情况。
- 主页面2,将全国的累计确诊的数据在地图上展示
结对讨论过程论述
讨论过程
山今:老王老王,咱们那个结对作业咋整?
老王:还能咋整,后端赶紧去写。
山今:有啥设计思路吗?
老王:你自己看咯。
山今:还有数据库设计/苦涩
老王:这也是你负责的部分,想不到吧。
很久很久以后(大概不到20min
山今:那我用ssm弄了
老王:可以。
山今:给个工期呗?
老王:三天内,今天开始算。
功能结构图
代码说明
后端代码说明
public class Data {
private Integer infect;
private Integer doubt;
private Integer cure;
private Integer dead;
private String provinceName;
private String date;
...//
get/set函数
}
//Bean的编写,设计用于存储数据
public interface DataMapper {
//查询某日所有信息
@Select("SELECT * FROM data WHERE date=#{date}")
List<Data> findByDate(String date);
//查询某省所有信息
@Select("SELECT * FROM data WHERE provincename=#{provinceName}")
List<Data> findByProvince(String provinceName);
//查询某省某日所有信息
@Select("SELECT * FROM data WHERE provincename=#{provinceName} AND date=#{date} ")
List<Data> findByDateAndProvince(@Param("provinceName") String provinceName, @Param("date") String date);
...
}
//DataMapper的实现,用于DAO层
public interface DataService {
List<Data> findByDate(String date);
List<Data> findByProvince(String provinceName);
List<Data> findByProvinceAndDate(String provinceName, String date);
String getInfectDate(String provinceName, String date);
String getDoubtDate(String provinceName, String date);
String getCureDate(String provinceName, String date);
String getDeadDate(String provinceName, String date);
}
//服务层接口
public class DataImplService implements DataService {
@Autowired
DataMapper dataMapper;
@Override
public List<Data> findByDate(String date) {
return dataMapper.findByDate(date);
}
@Override
public List<Data> findByProvince(String provinceName) {
return dataMapper.findByProvince(provinceName);
}
@Override
public List<Data> findByProvinceAndDate(String provinceName, String date) {
return dataMapper.findByDateAndProvince(provinceName,date);
}
...
}
//服务层接口的实现
前端代码说明
前端页面通过vue来快速搭建,使用element-ui和echarts来搭建视图,仿造这里搭建了一个基本的页面模型
chinaConfigure() {
let myChart = echarts.init(this.$refs.myEchart); //这里是为了获得容器所在位置
window.onresize = myChart.resize;
myChart.setOption({
// 进行相关配置
backgroundColor: '#f8f8f8',
title: {
text: '地图趋势',
left: 'center'
},
tooltip: {
formatter(params) {
if (params.data != null) {
return `
地区:${params.data.name}<br>确诊:${params.data.value}
`
}
}
}, // 鼠标移到图里面的浮动提示框
dataRange: {
show: true,
min: _.minBy(this.province, (o)=>{return o.value}).value,
max: _.maxBy(this.province, (o)=>{return o.value}).value,
// text: ["High", "Low"],
realtime: true,
calculable: true,
color: ["#000066", "white"]
},
geo: {
// 这个是重点配置区
map: "china", // 表示中国地图
roam: true,
label: {
normal: {
show: false, // 是否显示对应地名
textStyle: {
color: "rgba(0,0,0,0.4)"
}
}
},
itemStyle: {
normal: {
borderColor: "rgba(0, 0, 0, 0.2)"
},
emphasis: {
areaColor: null,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: "rgba(0, 0, 0, 0.5)"
}
}
},
series: [
{
type: "scatter",
coordinateSystem: "geo" // 对应上方配置
},
{
type: "map",
geoIndex: 0,
data: this.province
}
]
});
myChart.on('click', (params)=>{
this.$store.state.title=params.name
this.$router.push('/detail')
})
}
这是首页地图的初始化代码,使用echarts 在vue生命周期中mount
这个阶段初始化地图。
<div class="table">
<div style="text-align:left; color:#888888">数据更新至{{current}}
<el-tooltip class="item" effect="dark" content="趋势图与国家卫健委官网发布一致,每日更新" placement="bottom">
<span style="float:right; color:"><span class="el-icon-warning-outline"></span>数据说明</span>
</el-tooltip>
</div>
<el-row :gutter="24" :type="type" :justify="justify">
<el-col :span="8" >
<el-card shadow="always">
<span class="content-title">现有确诊</span> <br>
<div style="margin-top:5px;"></div>
<span class="content-number" style="color: #FF6633;">{{tableData.infect}}</span> <br>
<span class="content-yesterday">昨日
<span style="color: #FF6633"><span v-if="tableData.infect-yesterday.infect>=0">+</span><span v-else>-</span>{{tableData.infect-yesterday.infect}}</span>
</span>
</el-card>
</el-col>
<el-col :span="8" >
<el-card shadow="always" >
<span class="content-title">现有疑似</span> <br>
<div style="margin-top:5px;"></div>
<span class="content-number" style="color: #FFCC00">{{tableData.doubt}}</span> <br>
<span class="content-yesterday">昨日
<span style="color: #FFCC00"><span v-if="tableData.infect-yesterday.infect>=0">+</span><span v-else>-</span>{{tableData.infect-yesterday.infect}}</span>
</span>
</el-card>
</el-col>
</el-row>
<el-row :gutter="24" style="margin-top: 5px;">
<el-col :span="8" >
<el-card shadow="always" >
<span class="content-title">累计确诊</span> <br>
<div style="margin-top:5px;"></div>
<span class="content-number" style="color: #FF0000">{{tableData.sumCount}}</span> <br>
<span class="content-yesterday">昨日
<span style="color: #FF0000"><span v-if="tableData.sumCount-yesterday.sumCount>=0">+</span><span v-else>-</span>{{tableData.sumCount-yesterday.sumCount}}</span>
</span>
</el-card>
</el-col>
<el-col :span="8" >
<el-card shadow="always" >
<span class="content-title">累计治愈</span> <br>
<div style="margin-top:5px;"></div>
<span class="content-number" style="color: #67C23A">{{tableData.cure}}</span> <br>
<span class="content-yesterday">昨日
<span style="color: #67C23A"><span v-if="tableData.cure-yesterday.cure>=0">+</span><span v-else>-</span>{{tableData.cure-yesterday.cure}}</span>
</span>
</el-card>
</el-col>
<el-col :span="8" >
<el-card shadow="always" >
<span class="content-title">累计死亡</span> <br>
<div style="margin-top:5px;"></div>
<span class="content-number" style="color: #000000">{{tableData.dead}}</span> <br>
<span class="content-yesterday">昨日
<span style="color: #000000"><span v-if="tableData.dead-yesterday.dead>=0">+</span><span v-else>-</span>{{tableData.dead-yesterday.dead}}</span>
</span>
</el-card>
</el-col>
</el-row>
</div>
使用element中的card来表示地图上部分的表格,并用axios获取数据
getTableData() {
this.$ajax.get('/get/all', {
params: {'date':'2020-02-02'} //数据不全,只能先这样,否则可以调用date函数
}).then(
(res)=>{
var resJson = res.data
this.tableData = resJson
var count = 0
count += this.tableData.infect
count += this.tableData.cure
count += this.tableData.dead
this.tableData.sumCount = count
}
)
},
getYesterday() {
this.$ajax.get(('/get/all'), {
params: {'date': '2020-02-01'}
}).then(
(res)=> {
this.yesterday = res.data
var count = 0
count += this.yesterday.infect
count += this.yesterday.cure
count += this.yesterday.dead
this.yesterday.sumCount = count
}
)
}
心路历程&评价队友
因为将前后端分离的原因,我和老王两兄弟分别完成后端和前端,技术上的交流其实较少,更多的是前后对接的交流,正所谓分离一时爽,对接火葬场。前后分离有啥好处?这次练习最直观的印象就是同时推进,根据原型,同时进行前端页面和后端接口的代码编写,最后再进行功能的对接,文档写得不规范真是要命,具体的代码编写时间可能不算长,听了二十几遍等你下课可能就写完了,两人更多地是对团队开发模式的熟悉和了解,要不下次发个产品当出气筒?。
两个做后端的来做一个web项目,前端页面咋办嘛,让更nb的那个去写呗。---张
革命尚未成功,同志还需努力(指多练练手)——王