前端页面dashboard.html的代码如下:
{% extends "base.html" %}
{% block body %}
<div class="content-wrapper" data-menu="overview dashboard">
<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">看板</h1>
</div><!-- /.col -->
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#">总览</a></li>
<li class="breadcrumb-item active">看板</li>
</ol>
</div><!-- /.col -->
</div><!-- /.row -->
</div><!-- /.container-fluid -->
</div>
<!-- /.content-header -->
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<!-- Small boxes (Stat box) -->
<div class="row">
<div class="col-lg-3 col-6">
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3>{{info['total'] }}</h3>
<p>当前设备数量</p>
</div>
<div class="icon">
<i class="ion ion-bag"></i>
</div>
<a href="/ids" target="_blank" class="small-box-footer">详情 <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-6">
<!-- small box -->
{% set last = info['last1H'].tail(1) %}
<div class="small-box bg-success">
<div class="inner">
<h3>{{info['last1H'].shape[0] }}
<sub style="font-size: 20px">{{last.index[0].strftime('%H:%M')}}</sub>
</h3>
<p>最近一小时</p>
</div>
<div class="icon">
<i class="ion ion-stats-bars"></i>
</div>
<a href="/hour" target="_blank" class="small-box-footer">详情 <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-6">
<!-- small box -->
{% set last = info['last1D'].tail(1) %}
<div class="small-box bg-warning">
<div class="inner">
<h3>{{info['last1D'].shape[0] }}
<sub style="font-size: 20px">{{last.index[0].strftime('%m-%d')}}</sub>
</h3>
<p>最近一天</p>
</div>
<div class="icon">
<i class="ion ion-person-add"></i>
</div>
<a href="/day" target="_blank" class="small-box-footer">详情 <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-3 col-6">
<!-- small box -->
{% set last = info['last1M'].tail(1) %}
<div class="small-box bg-danger">
<div class="inner">
<h3>{{info['last1M'].shape[0] }}
<sub style="font-size: 20px">{{last.index[0].strftime('%Y-%m')}}</sub></h3>
<p>最近一月</p>
</div>
<div class="icon">
<i class="ion ion-pie-graph"></i>
</div>
<!-- <a href="/days" target="_blank" class="small-box-footer">详情 <i class="fas fa-arrow-circle-right"></i></a>-->
</div>
</div>
<!-- ./col -->
</div>
<!-- /.row -->
<!-- Main row -->
<div class="row">
<!-- Left col -->
<section class="col-lg-7 connectedSortable">
<!-- Custom tabs (Charts with tabs)-->
<div class="card">
<div class="card-header d-flex p-0">
<h3 class="card-title p-3">
<i class="fas fa-chart-pie mr-1"></i>
最近30天
</h3>
<ul class="nav nav-pills ml-auto p-2">
<li class="nav-item">
<a class="nav-link active" href="#amount-chart" data-toggle="tab">每日数据量</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#temperature-chart" data-toggle="tab">温度值分布</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#pressure-chart" data-toggle="tab">压力值分布</a>
</li>
</ul>
</div><!-- /.card-header -->
<div class="card-body">
<div class="tab-content p-0">
<!-- Morris chart - Sales -->
<div class="chart tab-pane active" id="amount-chart" style="position: relative; height: 300px;">
<canvas id="amount-chart-canvas" height="300" style="height: 300px;"></canvas>
</div>
<div class="chart tab-pane" id="temperature-chart" style="position: relative; height: 300px;">
<canvas id="temperature-chart-canvas" height="300" style="height: 300px;"></canvas>
</div>
<div class="chart tab-pane" id="pressure-chart" style="position: relative; height: 300px;">
<canvas id="pressure-chart-canvas" height="300" style="height: 300px;"></canvas>
</div>
</div>
</div><!-- /.card-body -->
</div>
<!-- /.card -->
<!--/.direct-chat -->
<!-- /.card -->
</section>
<!-- /.Left col -->
<!-- right col (We are only adding the ID to make the widgets sortable)-->
<section class="col-lg-5 connectedSortable">
<!-- Map card -->
<!-- /.card -->
<!-- solid sales graph -->
<div class="card bg-gradient-info">
<div class="card-header border-0">
<h3 class="card-title">
<i class="fas fa-th mr-1"></i>
每月掉线次数
</h3>
<!--
<div class="card-tools">
<button type="button" class="btn bg-info btn-sm" data-card-widget="collapse">
<i class="fas fa-minus"></i>
</button>
<button type="button" class="btn bg-info btn-sm" data-card-widget="remove">
<i class="fas fa-times"></i>
</button>
</div>
-->
</div>
<div class="card-body">
<canvas class="chart" id="line-chart" style="height: 250px;"></canvas>
</div>
<!-- /.card-body -->
{% set i=info['deltaG'].to_dict() %}
{% set c=sum(i.values())/100.0 %}
<div class="card-footer bg-transparent">
<div class="row">
<div class="col-4 text-center">
<input type="text" class="knob" data-readonly="true" value="{{i.get('A',0)/c}}" data-width="60" data-height="60" data-fgColor="#39CCCC">
<div class="text-white">15分钟</div>
</div>
<!-- ./col -->
<div class="col-4 text-center">
<input type="text" class="knob" data-readonly="true" value="{{i.get('B',0)/c}}" data-width="60" data-height="60" data-fgColor="#39CCCC">
<div class="text-white">1小时</div>
</div>
<!-- ./col -->
<div class="col-4 text-center">
<input type="text" class="knob" data-readonly="true" value="{{i.get('C',0)/c}}" data-width="60" data-height="60" data-fgColor="#39CCCC">
<div class="text-white">1小时以上</div>
</div>
<!-- ./col -->
</div>
<!-- /.row -->
</div>
<!-- /.card-footer -->
</div>
<!-- /.card -->
<!-- /.card -->
</section>
<!-- right col -->
</div>
{%if (len(ids)==1) & (ids!=[]) %}
<div class="row">
<!-- /.col-md-6 -->
<div class="col-lg-12">
<div class="card">
<div class="card-header border-0">
<div class="d-flex justify-content-between">
<h3 class="card-title">根据小时汇总</h3>
<a href="javascript:void(0);">View Report</a>
</div>
</div>
<div class="card-body">
<!--
<div class="d-flex">
<p class="d-flex flex-column">
<span class="text-bold text-lg">$18,230.00</span>
<span>Sales Over Time</span>
</p>
<p class="ml-auto d-flex flex-column text-right">
<span class="text-success">
<i class="fas fa-arrow-up"></i> 33.1%
</span>
<span class="text-muted">Since last month</span>
</p>
-->
</div>
<!-- /.d-flex -->
<div class="position-relative mb-4">
<canvas id="hour-chart" height="200"></canvas>
</div>
<div class="d-flex flex-row justify-content-end">
<span class="mr-2">
<i class="fas fa-square text-primary"></i> 平均值
</span>
<span>
<i class="fas fa-square text-gray"></i> 中值
</span>
</div>
</div>
</div>
</div>
{%end%}
<!-- /.row (main row) -->
</div><!-- /.container-fluid -->
</section>
<!-- /.content -->
</div>
{% set g=info['last1M'].groupby(info['last1M'].index.strftime('%Y-%m-%d')).count().ID %}
<input id="amountChartLabels" type="hidden" value="{%raw g.index.to_list()%}">
<input id="amountChartValues" type="hidden" value="{% raw g.values.tolist() %}">
{% import numpy as np %}
{% set rangeA=np.array([0,2000]) %}
{% set rangeB=np.array([0,10,20,30]) %}
{% set dfA=info['last1M'].iloc[(info['last1M'].DevUnit==1).values] %}
{% set dfB=info['last1M'].iloc[(info['last1M'].DevUnit==2).values] %}
{% set indexA=rangeA.searchsorted(dfA.DevData.values) %}
{% set indexB=rangeB.searchsorted(dfB.DevData.values) %}
{% set gA=dfA.DevData.groupby(indexA).count() %}
{% set gB=dfB.DevData.groupby(indexB).count() %}
{% set gA=gA.rename({0:'0',1:'0-2000',2:'>2000'}) %}
{% set gB=gB.rename({0:'0',1:'0-10',2:'10-20',3:'20-30',4:'>30'}) %}
{% set g1=info['g1'] %}
<input id="pressureChartLabels" type="hidden" value="{%raw gA.index.to_list()%}">
<input id="pressureChartValues" type="hidden" value="{% raw gA.values.tolist() %}">
<input id="temperatureChartLabels" type="hidden" value="{%raw gB.index.to_list()%}">
<input id="temperatureChartValues" type="hidden" value="{% raw gB.values.tolist() %}">
<input id="monthDeltaChartLabels" type="hidden" value="{% raw info['deltaMG'].index.to_list() %}">
<input id="monthDeltaChartValues" type="hidden" value="{% raw info['deltaMG'].values.tolist() %}">
<input id="hourChartLabels1" type="hidden" value="{% raw (g1.mean().index).astype('int16').to_list()%}">
<input id="hourChartValues1" type="hidden" value="{% raw g1.mean().values.tolist() %}">
<input id="hourChartLabels1" type="hidden" value="{% raw (g1.median().index).astype('int16').to_list()%}">
<input id="hourChartValues2" type="hidden" value="{% raw g1.median().values.tolist() %}">
{% end %}
{% block script %}
<script src="static/js/dashboard.js"></script>
{% end %}
前端页面对应的dashboard.js的代码如下:
$(function () {
if ($('#pressureChartLabels').val() == "[]") {
$('#pressure-chart').hide();
$('[href="#pressure-chart"]').parent().hide();
}
if ($('#temperatureChartLabels').val() == "[]") {
$('#temperature-chart').hide();
$('[href="#temperature-chart"]').parent().hide();
}
'use strict'
// Make the dashboard widgets sortable Using jquery UI
$('.connectedSortable').sortable({
placeholder: 'sort-highlight',
connectWith: '.connectedSortable',
handle: '.card-header, .nav-tabs',
forcePlaceholderSize: true,
zIndex: 999999
})
$('.connectedSortable .card-header, .connectedSortable .nav-tabs-custom').css('cursor', 'move')
/* jQueryKnob */
$('.knob').knob()
/* Chart.js Charts */
// Sales chart
var amountChartCanvas = document.getElementById('amount-chart-canvas').getContext('2d');
//$('#revenue-chart').get(0).getContext('2d');
var amountChartData = {
labels: eval($("#amountChartLabels").val()),
datasets: [
{
label: '单日数据量',
backgroundColor: 'rgba(60,141,188,0.9)',
borderColor: 'rgba(60,141,188,0.8)',
pointRadius: false,
pointColor: '#3b8bba',
pointStrokeColor: 'rgba(60,141,188,1)',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(60,141,188,1)',
data: eval($("#amountChartValues").val())
}
]
}
var amountChartOptions = {
maintainAspectRatio: false,
responsive: true,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: false,
}
}],
yAxes: [{
gridLines: {
display: false,
}
}]
}
}
// This will get the first returned node in the jQuery collection.
var amountChart = new Chart(amountChartCanvas, {
type: 'line',
data: amountChartData,
options: amountChartOptions
})
// Donut Chart
var pieChartCanvas1 = $('#temperature-chart-canvas').get(0).getContext('2d')
var pieData1 = {
labels: eval($("#temperatureChartLabels").val()),
datasets: [
{
data: eval($("#temperatureChartValues").val()),
backgroundColor: ['#f56954', '#00a65a', '#f39c12', '#60f554', '#b916a6'],
}
]
}
var pieOptions1 = {
legend: {
display: true
},
maintainAspectRatio: false,
responsive: true,
}
//Create pie or douhnut chart
// You can switch between pie and douhnut using the method below.
var pieChart1 = new Chart(pieChartCanvas1, {
type: 'doughnut',
data: pieData1,
options: pieOptions1
});
// Donut Chart
var pieChartCanvas2 = $('#pressure-chart-canvas').get(0).getContext('2d')
var pieData2 = {
labels: eval($("#pressureChartLabels").val()),
datasets: [
{
data: eval($("#pressureChartValues").val()),
backgroundColor: ['#f56954', '#00a65a', '#f39c12', '#60f554', '#b916a6'],
}
]
}
var pieOptions2 = {
legend: {
display: true
},
maintainAspectRatio: false,
responsive: true,
}
//Create pie or douhnut chart
// You can switch between pie and douhnut using the method below.
var pieChart2 = new Chart(pieChartCanvas2, {
type: 'doughnut',
data: pieData2,
options: pieOptions2
});
var monthDeltaGraphChartCanvas = $('#line-chart').get(0).getContext('2d');
//$('#revenue-chart').get(0).getContext('2d');
var monthDeltaGraphChartData = {
labels: eval($("#monthDeltaChartLabels").val()),
datasets: [
{
label: '掉线次数',
fill: false,
borderWidth: 2,
lineTension: 0,
spanGaps: true,
borderColor: '#efefef',
pointRadius: 3,
pointHoverRadius: 7,
pointColor: '#efefef',
pointBackgroundColor: '#efefef',
data: eval($("#monthDeltaChartValues").val())
}
]
}
var monthDeltaGraphChartOptions = {
maintainAspectRatio: false,
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [{
ticks: {
fontColor: '#efefef',
},
gridLines: {
display: false,
color: '#efefef',
drawBorder: false,
}
}],
yAxes: [{
ticks: {
stepSize: 500,
fontColor: '#efefef',
},
gridLines: {
display: true,
color: '#efefef',
drawBorder: false,
}
}]
}
}
// This will get the first returned node in the jQuery collection.
var monthDeltaGraphChart = new Chart(monthDeltaGraphChartCanvas, {
type: 'line',
data: monthDeltaGraphChartData,
options: monthDeltaGraphChartOptions
})
var ticksStyle = {
fontColor: '#495057',
fontStyle: 'bold'
}
var mode = 'index'
var intersect = true
var $hourChart = $('#hour-chart')
var hourChart = new Chart($hourChart, {
type: 'bar',
data: {
labels: eval($("#hourChartLabels1").val()),
datasets: [
{
backgroundColor: '#007bff',
borderColor: '#007bff',
data: eval($("#hourChartValues1").val())
},
{
backgroundColor: '#ced4da',
borderColor: '#ced4da',
data: eval($("#hourChartValues2").val())
}
]
},
options: {
maintainAspectRatio: false,
tooltips: {
mode: mode,
intersect: intersect
},
hover: {
mode: mode,
intersect: intersect
},
legend: {
display: false
},
scales: {
yAxes: [{
// display: false,
gridLines: {
display: true,
lineWidth: '4px',
color: 'rgba(0, 0, 0, .2)',
zeroLineColor: 'transparent'
},
ticks: $.extend({
beginAtZero: true,
// Include a dollar sign in the ticks
callback: function (value, index, values) {
if (value >= 1000) {
value /= 1000
value += 'k'
}
return value
}
}, ticksStyle)
}],
xAxes: [{
display: true,
gridLines: {
display: false
},
ticks: ticksStyle
}]
}
}
})
})
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。