Flask+Vue前后端分离疫情可视化系统

阅读: 评论:0

Flask+Vue前后端分离疫情可视化系统

Flask+Vue前后端分离疫情可视化系统

一、引言

在2020年初爆发的新型冠状病毒,是一种传染力极强的病毒。患者在感染了新型冠状病毒后,即使在潜伏期也很容易传染其他人,该病毒会导致人呼吸困难,严重的可能会导致死亡。时至今日,疫情仍未完全褪去,新冠疫情仍是全世界人民最关注的话题之一,特别是有些国家仍处于爆发期。因此,疫情的实时数据以及相关新闻报导受到了极大的关注。本系统利用数据爬虫技术,完成疫情数据以及疫苗接种数据的爬取经数据处理后形成数据集。利用数据可视化技术,对数据集进行可视化,实现疫情情况与疫苗接种情况的实时更新。帮助民众充分了解最新疫情数据、近期疫情发展趋势以及疫苗接种情况。


Flask 框架是一个轻量级的、便捷的、Python 所提供的 Web 框架,它更加的灵活、轻便、安全且容易上手,是目前主流的服务器框架,非常适合全队的分工 协作式开发,对一个小型团队而言,大大提升了开发的效率。利用 Flask框架,实现前后端的数据交互,其对应的前端 JinJa2的模板引擎,也极大地方便了前端的数据调用。

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。   与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用(SPA)提供驱动。简单小巧的核心,渐进式技术栈,足以应付任何规模的应用。

 本系统则采用后端Flask+前端Vue的开发模型进行开发。


二、现有技术研究

目前,比较成熟的疫情数据可视化平台有:网易可视化平台、腾讯疫情数据可视化平台、 百度疫情数据可视化平台。这三家数据可视化平台内容分析,如图1所示。

 现有技术的实现均是通过对大量的疫情数据进行 爬取、数据处理,利用可视化技术进行数据的可视化。 本系统集全国疫情数据于一个页面中,让用户可以更直观的观察到疫情信息。并且,本系统在疫情分布图上做出创新,在全国疫情分布图中点击各省份,直接可查看当前省份的疫情数据。用户可以由全国疫情分布图直接进入各省份疫情分布图,了解各省份的疫情分布。


三、系统架构和实现流程

 四、系统运行流程

 五、数据爬取与处理(网易接口)

说明

ChinaTotal

中国疫情总数据

Today

今日疫情数据

Total

总计疫情数据

Confirm

确证人数

Suspect

疑似病例

Heal

康复人数

Dead

死亡人数

Input

境外输入人数

NoSymptom

无症状感染者人数

IncrNosymptom

无症状感染者较昨日增加人数

curedCount

治愈总人数

curedIncr

较昨日治愈增长人数


六、部分代码展示

  • 后端(三个接口):

from flask import Flask,jsonify
import requests,json,time
app=Flask(__name__)
&#ute('/overall')
def get_data_overall():now = time.localtime()nowt = time.strftime("%Y-%m-%d %H:%M:%S", now)headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36','referer': '/',}url='=329222187209'res&#(url=url,headers=headers).json()if res:json_overall={"success":True,"code": 200,"message": "操作成功","data":{"confirmedCount": ('data').get('chinaTotal').get('total').get('confirm'),"confirmedIncr": ('data').get('chinaTotal').get('today').get('confirm'),"curedCount": ('data').get('chinaTotal').get('total').get('heal'),"curedIncr": ('data').get('chinaTotal').get('today').get('heal'),"currentConfirmedCount": ('data').get('chinaTotal').get('total').get('confirm')- ('data').get('chinaTotal').get('total').get('dead')-('data').get('chinaTotal').get('total').get('heal'),"currentConfirmedIncr": ('data').get('chinaTotal').get('today').get('storeConfirm'),"deadCount": ('data').get('chinaTotal').get('total').get('dead'),"deadIncr": 0,"importedCount": ('data').get('chinaTotal').get('total').get('input'),"importedIncr": ('data').get('chinaTotal').get('today').get('input'),"noInFectCount": ('data').get('chinaTotal').get('extData').get('noSymptom'),"noInFectIncr": ('data').get('chinaTotal').get('extData').get('incrNoSymptom'),"suspectIncr": 0,"suspectCount": ('data').get('chinaTotal').get('total').get('suspect'),"updateTime": nowt,"curedRate": 92.7,"deadRate": 4.69}}with open('data/covid19-overall.json','w') as f:json.dump(json_overall,f)print("json_overall文件加载完成!")return json_overall
&#ute('/daily')
def get_daily():now = time.localtime()nowt = time.strftime("%Y-%m-%d %H:%M:%S", now)today=time.strftime("%Y-%m-%d")headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36','referer': '/',}url = '=329222187209'res = (url=url, headers=headers).json()importedIncrList=[]curedCountList=[]confirmedCountList=[]importedCountList=[]currentConfirmedIncrList=[]noInFectCountList=[]currentConfirmedCountList=[]for i ('data').get('chinaDayList'):importedIncrList.append([i.get('date'),i.get('today').get('input')])curedCountList.append([i.get('date'),i.get('today').get('confirm')])confirmedCountList.append([i.get('date'),i.get('total').get('confirm')])importedCountList.append([i.get('date'),i.get('total').get('input')])currentConfirmedIncrList.append([i.get('date'),i.get('total').get('heal')])# 无症状noInFectCountList.append([('data').get('chinaTotal').get('extData').get('noSymptom')])if res:json_daily={"success":True,"code": 200,"message": "操作成功","data": {# 境外输入"importedIncrList": importedIncrList,# 现有确诊"curedCountList": curedCountList,"confirmedCountList":confirmedCountList ,"currentConfirmedIncrList": currentConfirmedIncrList,"importedCountList": importedCountList,# 无症状"noInFectCountList":noInFectCountList ,"currentConfirmedCountList":currentConfirmedCountList}}with open('data/covid19-daily-list.json','w') as f:json.dump(json_daily,f)print("json_daily文件加载完成!")return json_daily
&#ute('/province')
def get_province():now = time.localtime()nowt = time.strftime("%Y-%m-%d %H:%M:%S", now)today = time.strftime("%Y-%m-%d")headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36','referer': '/',}url = '=329222187209'res = (url=url, headers=headers).json()data=[]province&#('data').get('areaTree')[2].get('children')for i in province:('total').get('dead')==0:province_dict = {"confirmedCount": i.get('total').get('confirm'),"countryLabel": "中国","countryName": "China","curedCount": i.get('today').get('heal'),"curedRate": i.get('today').get('heal') / i.get('total').get('heal'),"currentConfirmedCount": i.get('today').get('confirm'),"deadCount": i.get('today').get('dead'),"deadRate": 0 ,"provinceLabel": i.get('name'),"provinceName": None,"suspectCount": 0,"todayConfirmedCount": 0,"updateTime": None}else:province_dict = {"confirmedCount": i.get('total').get('confirm'),"countryLabel": "中国","countryName": "China","curedCount": i.get('today').get('heal'),"curedRate": i.get('today').get('heal') / i.get('total').get('heal'),"currentConfirmedCount": i.get('today').get('confirm'),"deadCount": i.get('today').get('dead')/i.get('total').get('dead'),"deadRate": 0,"provinceLabel": i.get('name'),"provinceName": None,"suspectCount": 0,"todayConfirmedCount": 0,"updateTime": None}data.append(province_dict)if res:json_province={"success": True,"code": 200,"message": "操作成功","data":data}with open('data/covid19-province.json', 'w') as f:json.dump(json_province, f)print("json_province文件加载完成!")return json_province
if __name__ == '__main__':get_daily()get_province()get_data_overall()app.run(port=8080)
#前后端分离 首先启动后端 爬取当日的数据 由于腾讯接口使用的人比较多 所以我们这次选取的是网易接口#然后启动前端 npm run dev 因为采用的vue
  •  前端(引用蓝伟洪先生​​​​​​​模板)

    <template><div class="container"><!-- 顶部 --><div class="top-header"><div class="title"><h1>{{ title }}</h1><div class="top-header-tip"><div class="sub-title">此数据为实时真实数据,数据来源:网易新闻</div><div class="last-update-time">更新时间:{{ basicData.updateTime }}</div></div></div></div><div class="main-content"><el-row><el-col :span="18"><!-- 中间信息开始 --><div class="statistics-content"><!-- 中间左侧开始 --><div class="main-inner"><el-row><el-col :span="7"><chart-cardtitle="累计排名(TOP 10)":customClass="`chart-item-bottom-sep`"><province-ranking-bar-chartref="topConfirmedCountRankChart":data="top10ProvinceData"style="width: 100%; height: 380px"/></chart-card><!-- 占比 --><chart-cardtitle="占比":customClass="`chart-item-bottom-sep`"><basic-proportion-chartref="basicProportionChart":data="basicData"style="width: 100%; height: 120px"/></chart-card><chart-card title="最近一周累计治愈"><current-confirmed-compare-bar-chartref="confirmSingleBarChart":data="confirmSingleBarChartData"style="width: 100%; height: 310px"/></chart-card></el-col><el-col :span="17"><!-- 顶部基本统计信息开始 --><div class="basic-header flex"><!-- 顶部统计信息开始 --><div class="top-basic-info"><basic-data-item-labellabel="现有确诊":config="defaultDataConfig.currentConfirmedCount":inCrValue="basicData.currentConfirmedIncr"/><basic-data-item-labellabel="累计确诊":config=&#firmedCount":inCrValue=&#firmedIncr"/><!-- 境外输入 --><basic-data-item-labellabel="境外输入":config="defaultDataConfig.importedCount":inCrValue="basicData.importedIncr"/><!-- 无症状感染者 --><basic-data-item-labellabel="无症状感染者":config=&#InFectCount":inCrValue=&#InFectIncr"/><!-- 累计治愈 --><basic-data-item-labellabel="累计治愈":config="defaultDataConfig.curedCount":inCrValue="basicData.curedIncr"/><!-- 死亡人数 -->
    <!--                      <basic-data-item-label-->
    <!--                        label="累计死亡"-->
    <!--                        :config="defaultDataConfig.deadCount"-->
    <!--                        :inCrValue="basicData.deadIncr"-->
    <!--                      />--></div><!-- 顶部统计信息结束 --></div><!-- 顶部基本统计信息开始 --><div class="main-inner-map-wraper"><!-- 地图 --><div class="map"><data-mapref="dataMap"title="":list="mapDataList"style="width: 100%; height: 100%"/></div></div></el-col></el-row></div><!-- 中间左侧结束 --></div><!-- 中间信息结束 --></el-col><el-col :span="6"><!-- 右侧区域开始 --><div class="main-right"><!-- 治愈率和死亡率 --><chart-cardtitle="治愈率和死亡率":innerClass="`cure-and-dead-rate-chart`":customClass="`chart-item-bottom-sep`"><cured-and-dead-rate-chartref="cureRateChart":data="rate"title="治愈率"style="width: 280px; height: 130px"/></chart-card><chart-card title="新增趋势" :customClass="`chart-item-bottom-sep`"><basic-trend-chart:data="basicIncrTrendData"ref="confirmedCountTrendChart"style="width: 100%; height: 320px"/></chart-card><chart-card title=""><div slot="title" class="province-table-title flex">各省累计确诊<el-linkicon="el-icon-view"style="color: #bcbcbf; padding-left: 10px":underline="false"@click="provinceTableDialogShowHandler">详情</el-link></div><dv-scroll-board:config="provinceConfirmedCountBoardConfig"style="width: 100%; height: 360px"/></chart-card></div><!-- 右侧区域结束 --></el-col></el-row></div><!-- 其他页面 --><div class="province-data-table-wrapper"><el-dialog:visible.sync="provinceTableDialogVisible"width="50%":before-close="provinceTableDialogClose"><div slot="title" class="province-data-modal-title"><p>各省数据表</p><span class="province-data-modal-update-time">(更新时间:{{ basicData.updateTime }})</span></div><div class="area-data-table-wrapper"><el-tableclass="area-data-table":data="provinceDataList"style="width: 100%"><el-table-column prop="provinceLabel" align="center" label="省份"></el-table-column><el-table-columnprop="confirmedCount"align="center"label="累计确诊"></el-table-column><el-table-columnprop="currentConfirmedCount"align="center"label="现有确诊"></el-table-column><el-table-column prop="curedCount" align="center" label="累计治愈"></el-table-column><el-table-column prop="deadCount" align="center" label="累计死亡"></el-table-column></el-table></div></el-dialog><!-- 关于弹窗 --><el-dialogtitle="关于":visible.sync="aboutDialogVisible"width="30%":before-close="aboutDialogClose"><about /></el-dialog><!-- 关于图标 --><div class="about-wraper"><iclass="el-icon-info"style="font-size: 30px"@click="aboutDialogShowHandler"></i></div></div></div>
    </template>
    <script>
    import ChartCard from '../components/ChartCard'
    import DataMap from '../components/DataMap'
    import CuredAndDeadRateChart from '../components/CuredAndDeadRateChart'
    import BasicDataItemLabel from '../components/BasicDataItemLabel'
    import BasicTrendChart from '../components/BasicTrendChart'
    import ProvinceRankingBarChart from '../components/ProvinceRankingBarChart'
    import CurrentConfirmedCompareBarChart from '../components/CurrentConfirmedCompareBarChart'
    import About from '../components/About'
    import BasicProportionChart from '../components/BasicProportionChart'import covid19Service from '../api/covid19'const formatter = (number) => {const numbers = String().split('').reverse()const segs = []while (numbers.length) segs.push(numbers.splice(0, 3).join(''))return segs.join(',').split('').reverse().join('')
    }
    // 数据样式
    const getNumberStyle = (color = '#E8EAF6', fontSize = 30, fontWeight = 'bolder') => {return {fontSize: fontSize,fill: color,fontWeight: fontWeight}
    }const initBasicConfig = (data = null) => {let currentConfirmedCount = data ? [data.currentConfirmedCount] : 0let confirmedCount = data ? [firmedCount] : 0let importedCount = data ? [data.importedCount] : 0let noInFectCount = data ? [InFectCount] : 0let deadCount = data ? [data.deadCount] : 0let curedCount = data ? [data.curedCount] : 0return {confirmedCount: {number: [confirmedCount],content: '{nt}',formatter,style: getNumberStyle()},currentConfirmedCount: {number: [currentConfirmedCount],content: '{nt}',formatter,style: getNumberStyle('#2E8EEA')},importedCount: {number: [importedCount],content: '{nt}',formatter,style: getNumberStyle()},noInFectCount: {number: [noInFectCount],content: '{nt}',formatter,style: getNumberStyle()},deadCount: {number: [deadCount],content: '{nt}',formatter,style: getNumberStyle('#D32E58')},curedCount: {number: [curedCount],content: '{nt}',formatter,style: getNumberStyle()}}
    }const initProvinceConfirmedCountBoardConfig = (resultList = []) => {return {header: ['省份', '累计确诊', '累计治愈', '累计死亡'],headerHeight: 30,data: resultList,align: ['center'],rowNum: 10,index: true,indexHeader: '排名',headerBGC: '',oddRowBGC: '',evenRowBGC: '',carousel: 'single'}
    }
    export default {components: {ChartCard,DataMap,CuredAndDeadRateChart,BasicDataItemLabel,BasicTrendChart,ProvinceRankingBarChart,CurrentConfirmedCompareBarChart,About,BasicProportionChart},data () {return {title: '全国新冠肺炎疫情数据大屏',provinceTableDialogVisible: false,aboutDialogVisible: false,commonData: {},basicData: {currentConfirmedCount: 0,currentConfirmedIncr: 0,confirmedCount: 0,confirmedIncr: 0,curedCount: 0,curedIncr: 0,deadCount: 0,deadIncr: 0,sure: 0,sureAdd: 0,importedCount: 0,importedIncr: 0,noInFectCount: 0,noInFectIncr: 0,suspectCount: 0,suspectIncr: 0,updateTime: '2022-3-1'},defaultDataConfig: initBasicConfig(),cureRateConfig: {data: [0],shape: 'round'},deadRateConfig: {data: [0],shape: 'round'},countryRankingTakeTurnChartConfig: {data: [],waitTime: 2000,unit: '单位',valueFormatter ({ value }) {const reverseNumber = (value + '').split('').reverse()let valueStr = ''while (reverseNumber.length) {const seg = reverseNumber.splice(0, 3).join('')valueStr += segif (seg.length === 3) valueStr += ','}return valueStr.split('').reverse().join('')}},provinceConfirmedCountBoardConfig: initProvinceConfirmedCountBoardConfig(),provinceDataList: [],trendDataList: [],confirmedCountList: [],top10ProvinceData: {provinceList: [],valueList: []},basicIncrTrendData: {dateList: [],importedIncrDataList: [],currentConfirmedIncrDataList: []},confirmSingleBarChartData: {dateList: [],currentConfirmedCountList: [],confirmedCountList: []},rate: {curedRate: 0,deadRate: 0},areaData: {},mapDataList: []}},methods: {queryBasicData () {let self = Overall().then((res) => {if (!res.success) {console.log('错误:' + res.info)return}self.basicData = res.dataself.setBasicData(res.data)})},queryProvinceDataList () {let self = ProvinceDataList().then((res) => {if (!res.success) {// TODO 错误处理...console.log('错误:' + res.info)return}self.provinceDataList = res.dataself.setAreaChartData(res.data)// 设置累计排名数据self.setProvinceRankingData(res.data)// 设置各省累计确诊轮播表格数据self.setProvinceComfirmedCountBoardData(res.data)// 设置地图数据self.setMapData(res.data)})},queryTrendDataList () {let self = DailyList().then((res) => {if (!res.success) {// TODO 错误处理...console.log('错误:' + res.info)dDataList = res.data// 重置图表数据self.setBasicIncrTrendData(res.data)})},setProvinceRankingData (areaList) {let provinceList = []let dataValueList = []for (let i = 0; i < 10; i++) {provinceList.push(areaList[i].provinceLabel)dataValueList.push(areaList[i].confirmedCount)}let data = {provinceList: provinceList,valueList: p10ProvinceData = data},setBasicIncrTrendData (data) {let dateList = []let currentConfirmedIncrList = []let importedIncrList = []let sevenDayDateList = []// 仅显示一周条数据let confirmedCountList = []let curedCountList = []// 仅获取7条数据let count = 7let noInFectDataList = []for (let i = data.currentConfirmedIncrList.length - 1; i >= 0; i--) {dateList.push(data.currentConfirmedIncrList[i][0])currentConfirmedIncrList.push(data.currentConfirmedIncrList[i][1])}for (let i = data.importedIncrList.length - 1; i >= 0; i--) {importedIncrList.push(data.importedIncrList[i][1])}for (let i = InFectCountList.length - 1; i >= 0; i--) {noInFectDataList.InFectCountList[i][1])}for (let i = count; i >= 0; i--) {if (confirmedCountList.length >= count) {break}sevenDayDateList.firmedCountList[i][0])confirmedCountList.firmedCountList[i][1])}for (let i = count; i >= 0; i--) {if (curedCountList.length >= count) {break}curedCountList.push(data.curedCountList[i][1])}this.basicIncrTrendData = {dateList: dateList,importedIncrDataList: importedIncrList,currentConfirmedIncrDataList: currentConfirmedIncrList,noInFectDataList: firmSingleBarChartData = {dateList: sevenDayDateList,curedCountList: curedCountList,confirmedCountList: confirmedCountList}},setProvinceComfirmedCountBoardData (areaList) {let resultList = areaList.map(item => {return [item.provinceLabel, firmedCount, item.curedCount, item.deadCount]})// 重新生成,否则无法刷新状态this.provinceConfirmedCountBoardConfig = initProvinceConfirmedCountBoardConfig(resultList)},setAreaChartData (areaList) {let confirmedCountList = []let provinceList = []let curedCountList = []let deadCountList = []areaList.forEach(item => {provinceList.push(item.provinceLabel)confirmedCountList.firmedCount)curedCountList.push(item.curedCount)deadCountList.push(item.deadCount)})this.areaData = {provinceList: provinceList,confirmedCountList: confirmedCountList,curedCountList: curedCountList,deadCountList: deadCountList}},setMapData (dataList) {let list = dataList.map(item => {return {name: item.provinceLabel,value: firmedCount}})this.mapDataList = list},provinceTableDialogShowHandler () {this.provinceTableDialogVisible = true},provinceTableDialogClose () {this.provinceTableDialogVisible = false},aboutDialogShowHandler () {this.aboutDialogVisible = true},aboutDialogClose () {this.aboutDialogVisible = false},setBasicData (data) {// 重新生成,否则视图不更新let config = initBasicConfig(data)this.defaultDataConfig = config// 处理治愈率和死亡率this.rate = {curedRate: data.curedRate / 100,deadRate: data.deadRate / 100}},startQueryData () {this.queryBasicData()this.queryProvinceDataList()this.queryTrendDataList()},initAllChart() {this.$refs.dataMap.initChart()this.$refs.cureRateChart.initChart()this.$firmedCountTrendChart.initChart()this.$pConfirmedCountRankChart.initChart()this.$firmSingleBarChart.initChart()this.$refs.basicProportionChart.initChart()}},mounted () {this.initAllChart()this.startQueryData()let self = this// 定义定时器,隔 5 秒刷新一次this.timer = setInterval(() => {self.startQueryData()}, 5000)},beforeDestroy() {clearInterval(this.timer)}
    }
    </script>
    <style>
    .container {position: relative;
    }
    h1 {font-size: 35px;font-weight: bold;padding: 20px;
    }
    .flex {display: flex;
    }
    .top-header {position: relative;margin-bottom: 10px;
    }
    .top-header-tip {font-size: 14px;position: absolute;padding: 20px 20px;text-align: right;top: 0;right: 0;
    }
    .title {min-width: 350px;
    }
    .chart-card {background: #0f142b;border-radius: 10px;margin: 0 20px;
    }
    .main-inner-map-wraper {height: 100%;margin: 0 20px;
    }
    .map {width: 99%;height: 840px;padding: 20px 10px 10px 10px;
    }
    .province-scroll-board-wrapper {padding-top: 10px;padding-bottom: 10px;
    }
    .chart-item-bottom-sep {margin-bottom: 20px;
    }
    .province-table-title {color: #fff;font-size: 16px;font-weight: bold;padding: 10px 10px 10px 20px;text-align: left;
    }
    .basic-incr-trend-chart-wrapper {padding-bottom: 10px;
    }
    .sub-title,
    .last-update-time,
    .province-scroll-board-wrapper ::v-deep .dv-scroll-board .header,
    .province-scroll-board-wrapper ::v-deep .dv-scroll-board .rows {font-size: 14px;
    }
    .province-scroll-board-wrapper ::v-deep .dv-scroll-board .rows {color: #bcbcbf;
    }
    .province-data-modal-title {color: #000;font-size: 20px;font-weight: bold;
    }
    .province-data-modal-update-time {color: #58585a;font-size: 16px;font-weight: normal;padding-top: 10px;display: block;
    }
    .cure-and-dead-rate-chart {display: flex;justify-content: space-around;
    }
    .top-basic-info {display: flex;
    }
    .dv-scroll-ranking-board .ranking-column .inside-column {background: linear-gradient(90deg, #29bfff, #a231ff, #0deccd, #29bfff);
    }
    .chart-item-container {margin: 0 10px;
    }
    .about-wraper {position: fixed;bottom: 20px;right: 20px;
    }
    </style>

    七、成品展示

 

 

 

 

 结束语

截至到 2022年 3 月,疫情仍未完全褪去,民众最为关心的是疫苗接种情况。本系统基于疫情数据显 示的基础上,增加疫苗数据显示功能。利用数据爬虫 技术完成数据的获取与下载,经数据处理后形成数据 集,数据可视化阶段利用 Python 语言的 Flask 框架、 Vue、ECharts可视化等可视化技术,对疫情数据以及疫苗数据进行数据可视化。经过对现有技术的分析,并在可 视化内容上做出创新。集可视化内容于一个页面中, 疫情数据与疫苗数据一目了然,用户可以从多方面,多角度,全方位直观的观察到疫情数据、疫情发展 趋势,以及疫苗接种情况。本系统的开发是用来帮助 民众充分了解全国各地的疫情情况、近期的疫情发展 趋势以及疫苗接种情况。

本文发布于:2024-02-04 11:12:01,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170705861955053.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:疫情   后端   系统   Flask   Vue
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23