echarts、higncharts折線圖或柱狀圖顯示數據為0的點


echarts、higncharts折線圖或柱狀圖只需要后端傳到前端一段json數據,接送數據的x軸與y周有對應數據,折線圖或柱狀圖就會渲染出這數據。

比如,x軸表示美每天日期,y軸表示數量。他們的數據都在數據庫里存着。如下圖:

它們的數據存放數據庫中,x軸為每周的周一,並且代表當前周的違規次數或人數。由於3月25日到3月31日那周和4月8日到4月14日那周都沒人違規,所以數據庫中並沒有這兩周的任何數據,所以后端從數據庫拿到數據並傳到前端,渲染出來的圖就如上兩圖了。

若要那兩周就算沒數據也想展示到圖里面,如下兩張圖:

解決辦法如下:

后端:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import web
import json
import time
import datetime
from common.util.login_required import login_required
from common.config.DatabaseConfig import mysql_db

# 
urls = (
    "/visualviolationno***", "VisualViolat***",  # 可視化頁面
    "/visualviolationno***", "VisualViolat***",  # 柱狀圖1數據處理
    "/visualviolationno***", "VisualViolat***",  # 折線圖2數據處理
    "/visualviolationno***", "VisualViolat***",  # 餅狀圖3數據處理
    "/visualviolationno***", "VisualViolat***",  # 柱狀圖4數據處理
)

render = web.template.render('templates')
app = web.application(urls, globals())


# 可視化頁面
class VisualViolationNotification(object):
    def GET(self):
        render = web.template.render('templates')
        return render.violationnotification()


# 柱狀圖1數據處理
class VisualViolationNot***(object):
    def GET(self):
        data_web = web.input()
        data_name = data_web.i1.encode("gbk")
        date_min = data_web.get('i2')
        date_max = data_web.get('i3')
        if len(date_min) == 7 and len(date_max) == 7:

            sql = "select count(*) count,division from week_violation where substring(date_min,1,7) <= '" + date_max + "' and substring(date_min,1,7) >= '" + date_min + "' group by division"
        else:
            sql = "select count(*) count,division from week_violation where date_min >= '" + date_min + "' and date_max <= '" + date_max + "'  group by division"


        ret = mysql_db.query(sql)
        ret = list(ret)
        list_out = []
        list_count = []
        list_division = []
        for i in ret:
            count = i.get("count")
            list_count.append(count)
            division = i.get("division")
            list_division.append(division)
        list_out.append(list_division)
        list_out.append(list_count)
        return json.dumps(list_out)


# 折線圖2數據處理
class VisualViolationNotificationData2(object):
    def GET(self):
        data_web = web.input()
        data_name = data_web.i1.encode("gbk")
        date_min = data_web.get('i2')
        date_max = data_web.get('i3')
        if len(date_min) == 7 and len(date_max) == 7:
            flag = ''
            sql = "select count(*) count,month_min date_min from week_violation where substring(date_min,1,7) <= '" + date_max + "' and substring(date_min,1,7) >= '" + date_min + "' group by month_min"
            ret = mysql_db.query(sql)
            ret = list(ret)
            list1 = []
            total_x = []
            total_y = []
            for tot in ret:
                total_x.append(str(tot.get("date_min")))
                total_y.append(tot.get("count"))
            list1.append(total_x)
            list1.append(total_y)
            list1.append(flag)
            list1 = json.dumps(list1)

        else:
            flag = ''
            sql = "select count(*) count,date_min from week_violation where date_min >= '" + date_min + "' and date_max <= '" + date_max + "' group by date_min"
            ret = mysql_db.query(sql)
            ret = list(ret)
            list1 = []
            total_x = []
            total_y = []
            for tot in ret:
                total_x.append(str(tot.get("date_min")))
                total_y.append(tot.get("count"))
            list1.append(total_x)
            list1.append(total_y)
            list1.append(flag)

            date_min = date_min.encode("utf-8")
            date_min = datetime.datetime.strptime(date_min, "%Y-%m-%d")
            date_max = datetime.datetime.strptime(date_max, "%Y-%m-%d")


            work = workDays(date_min, date_max)
            ret = list(work.workDays())
            l1 = []
            for i in range(len(ret)):
                if i % 2 == 0:
                    l1.append(ret[i].strftime("%Y-%m-%d"))

            for i in l1:
                if i not in list1[0]:
                    list1[1].insert(l1.index(i), 0)
            list1[0] = l1
            list1 = json.dumps(list1)

        return list1


# 餅狀圖3數據處理
class VisualViolationNotificationData3(object):
    def GET(self):
        data_web = web.input()
        data_name = data_web.i1.encode("gbk")
        date_min = data_web.get('i2')
        date_max = data_web.get('i3')
        if len(date_min) == 7 and len(date_max) == 7:
            sql = "select count(*) count,division from week_violation where substring(date_min,1,7) <= '" + date_max + "' and substring(date_min,1,7) >= '" + date_min + "' group by division"

        else:
            sql = "select count(*) count,division from week_violation where date_min >= '" + date_min + "' and date_max <= '" + date_max + "' group by division"

        ret = mysql_db.query(sql)
        ret = list(ret)

        list1 = []
        for i in ret:
            dict = {}
            dict['y'] = i.get("count")
            dict['name'] = i.get("division")
            list1.append(dict)
        return json.dumps(list1)


# 柱狀圖4數據處理
class VisualViolationNotificationData4(object):
    def GET(self):

        data_web = web.input()
        data_name = data_web.i1.encode("gbk")
        #date_min = data_web.i2.encode("gbk")
        #date_max = data_web.i3.encode("gbk")
        date_min = data_web.get('i2')
        date_max = data_web.get('i3')

        if len(date_min) == 7 and len(date_max) == 7:
            flag = ''
            sql = "select count(distinct num) count,month_min date_min from week_violation where substring(date_min,1,7) <= '" + date_max + "' and substring(date_min,1,7) >= '" + date_min + "' group by month_min"
            with mysql_db.transaction():
                ret = mysql_db.query(sql)
            ret = list(ret)
            list_out = []
            list_count = []
            list_division = []
            for i in ret:
                count = i.get("count")
                list_count.append(count)
                date_min = i.get("date_min")
                list_division.append(str(date_min))

            list_out.append(list_division)
            list_out.append(list_count)
            list_out.append(flag)
        else:
            flag = ''
            sql = "select count(distinct num) count,date_min from week_violation where date_min >= '" +date_min + "' and date_max <= '" + date_max + "' group by date_min"
            with mysql_db.transaction():
                ret = mysql_db.query(sql)
            ret = list(ret)
            list_out = []
            list_count = []
            list_division = []
            for i in ret:
                count = i.get("count")
                list_count.append(count)
                date_min1 = i.get("date_min")
                list_division.append(str(date_min1))

            list_out.append(list_division)
            list_out.append(list_count)
            list_out.append(flag)

            date_min = date_min.encode("utf-8")
            date_min = datetime.datetime.strptime(date_min, "%Y-%m-%d")
            date_max = datetime.datetime.strptime(date_max, "%Y-%m-%d")

            work = workDays(date_min, date_max)
            ret = list(work.workDays())
            l1 = []
            for i in range(len(ret)):
                if i % 2 == 0:
                    l1.append(ret[i].strftime("%Y-%m-%d"))
            for i in l1:
                if i not in list_out[0]:
                    list_out[1].insert(l1.index(i), 0)
            list_out[0] = l1

        return json.dumps(list_out)


# 計算兩個日期之間的周
class workDays():
    def __init__(self, start_date, end_date, days_off=None):
        """days_off:休息日,默認周六日, 以0(星期一)開始,到6(星期天)結束, 傳入tupple
        沒有包含法定節假日,
        """
        self.start_date = start_date
        self.end_date = end_date
        self.days_off = days_off
        if self.start_date > self.end_date:
            self.start_date, self.end_date = self.end_date, self.start_date
        if days_off is None:
            self.days_off = 1,2,3,4,5
        # 每周工作日列表
        self.days_work = [x for x in range(7) if x not in self.days_off]

    def workDays(self):
        """實現工作日的 iter, 從start_date 到 end_date , 如果在工作日內,yield 日期
        """
        # 還沒排除法定節假日
        tag_date = self.start_date
        while True:
            if tag_date > self.end_date:
                break
            if tag_date.weekday() in self.days_work:
                yield tag_date
            tag_date += datetime.timedelta(days=1)

    def daysCount(self):
        """工作日統計,返回數字"""
        return len(list(self.workDays()))

    def weeksCount(self, day_start=0):
        """統計所有跨越的周數,返回數字
        默認周從星期一開始計算
        """
        day_nextweek = self.start_date
        while True:
            if day_nextweek.weekday() == day_start:
                break
            day_nextweek += datetime.timedelta(days=1)
        # 區間在一周內
        if day_nextweek > self.end_date:
            return 1
        weeks = ((self.end_date - day_nextweek).days + 1) / 7
        weeks = int(weeks)
        if ((self.end_date - day_nextweek).days + 1) % 7:
            weeks += 1
        if self.start_date < day_nextweek:
            weeks += 1
        return weeks
#
# date_min = datetime.datetime(2019,1,7)
# date_max = datetime.datetime(2019,2,18)
#
# work = workDays(date_min,date_max)
#
# ret = list(work.workDays())
# # print ret
# l1 = []
# l2 = []
# for i in range(len(ret)):
#     if i % 2 == 0:
#         l1.append(ret[i].strftime("%Y-%m-%d"))
#
# b = ['2019-01-07', '2019-01-21', '2019-01-28', '2019-02-11']
# c = [1,2,3,4]
# print b
# print l1
# for i in l1:
#     if i not in b:
#         c.insert(l1.index(i),0)
# print c

前端

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
    <meta http-equiv="Cache-Control" content="no-siteapp"/>
    <!--[if lt IE 9]>
    <script type="text/javascript" src="../static/ui/lib/html5shiv.js"></script>
    <script type="text/javascript" src="../static/ui/lib/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="../static/ui/static/h-ui/css/H-ui.min.css"/>
    <link rel="stylesheet" type="text/css" href="../static/ui/static/h-ui.admin/css/H-ui.admin.css"/>
    <link rel="stylesheet" type="text/css" href="../static/ui/lib/Hui-iconfont/1.0.8/iconfont.css"/>
    <link rel="stylesheet" type="text/css" href="../static/ui/static/h-ui.admin/skin/default/skin.css" id="skin"/>
    <link rel="stylesheet" type="text/css" href="../static/ui/static/h-ui.admin/css/style.css"/>
    <!--[if IE 6]>
    <script type="text/javascript" src="../static/ui/lib/DD_belatedPNG_0.0.8a-min.js"></script>
    <script>DD_belatedPNG.fix('*');</script>
    <![endif]-->
    <title></title>
</head>
<body>

<div>
<span class="" id="month" style="margin-left: 500px; margin-top: 20px;">
    日期范圍
    <input type="text" id="datemin" class="Wdate startTime input-text" name="startTime" style="width:120px;"
           value="2018-01"
           onfocus="WdatePicker({dateFmt:'yyyy-MM',isShowClear:false,isShowToday:false,isShowOK:false,readOnly:true,maxDate:'#F{$$dp.$$D(\'datemax\')}',onpicked:pickedSdate})"/>
    -
    <input type="text" id="datemax" class="Wdate endTime input-text" name="endTime" style="width:120px;"
           value="2018-12"
           onfocus="WdatePicker({dateFmt:'yyyy-MM',isShowClear:false,isShowToday:false,isShowOK:false,readOnly:true,minDate:'#F{$$dp.$$D(\'datemin\')}',startDate:'#F{$$dp.$$D(\'datemin\',{d:+1})}',onpicked:pickedSdate})"/>
    <span id="data-name" class="hide"></span>

    <button type="button" class="btn btn-success radius" id="tijiao" name=""><i class="Hui-iconfont">&#xe665;</i> 搜索
    </button>
</span>


    <span class="text-c hide" id="week" style="margin-left: 500px; margin-top: 20px;">
       日期范圍
        <input type="text"
               onfocus="WdatePicker({ maxDate:'#F{$$dp.$$D(\'datemax1\')||\'%y-%M-%d\'}',disabledDays:[0,2,3,4,5,6]})"
               id="datemin1"
               class="input-text Wdate" style="width:120px;">
        -
        <input type="text"
               onfocus="WdatePicker({ minDate:'#F{$$dp.$$D(\'datemin1\')}',maxDate:'%y-%M-%d',disabledDays:[1,2,3,4,5,6]})"
               id="datemax1"
               class="input-text Wdate" style="width:120px;">

        <button type="button" class="btn btn-success radius" id="tijiao1" name=""><i class="Hui-iconfont">&#xe665;</i> 搜索
        </button>
</span>

    <span style="margin-top: 20px;">
    <button id="flag" value="month"></button>
    <a href="javascript: void month()" id="button_month" class="">
    <button class="btn btn-success radius" type="button">月查詢</button></a>
        <a href="javascript: void week()" id="button_week" class="hide">
    <button class="btn btn-success radius" type="button">周查詢</button></a>
</span>

</div>
<!--視圖-->
<div class="page-container">
    <div id="container1" style="width: 50%; float: left"></div>
    <div id="container2" style="width: 50%; float: left;"></div>
    <div id="container3" style="width: 50%; float: left;"></div>
    <div id="container4" style="width: 50%; float: left;"></div>
</div>
<!--_footer 作為公共模版分離出去-->
<script type="text/javascript" src="../static/ui/lib/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="../static/ui/lib/layer/2.4/layer.js"></script>
<script type="text/javascript" src="../static/ui/static/h-ui/js/H-ui.min.js"></script>
<script type="text/javascript" src="../static/ui/static/h-ui.admin/js/H-ui.admin.js"></script>
<!--/_footer 作為公共模版分離出去-->

<!--請在下方寫此頁面業務相關的腳本-->
<script type="text/javascript" src="../static/ui/lib/hcharts/Highcharts/5.0.6/js/highcharts.js"></script>
<script type="text/javascript" src="../static/ui/lib/hcharts/Highcharts/5.0.6/js/modules/exporting.js"></script>
<script type="text/javascript" src="../static/ui/lib/hcharts/Highcharts/5.0.6/js/highcharts-3d.js"></script>
<script type="text/javascript" src="../static/ui/lib/My97DatePicker/4.8/WdatePicker.js"></script>
<script type="text/javascript" src="../static/ui/lib/datatables/1.10.0/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="../static/ui/lib/jquery.contextmenu/jquery.contextmenu.r2.js"></script>
<script type="text/javascript" src="../static/ui/lib/laypage/1.2/laypage.js"></script>
<script type="text/javascript">

    function month() {
        $$("#month").toggleClass("hide");
        $$("#week").toggleClass("hide");
        $$("#button_month").toggleClass("hide");
        $$("#button_week").toggleClass("hide");
        $$("#flag").val("week");
    }

    function week() {
        $$("#month").toggleClass("hide");
        $$("#week").toggleClass("hide");
        $$("#button_month").toggleClass("hide");
        $$("#button_week").toggleClass("hide");
        $$("#flag").val("month");
    }


    // 只讓日期插件顯示年和月份
    $$(function () {
        //日期顯示當月
        (function () {
            var date = new Date();
            date.setMonth(date.getMonth() - 6);
            var date_zero = date.toLocaleDateString().split("/");
            console.log(date_zero);
            var mydate_min = (date_zero[0] < 10 ? "0" + date_zero[0] : date_zero[0]).toString() + "-" + (date_zero[1] < 10 ? "0" + date_zero[1] : date_zero[1]).toString();

            date.setMonth(date.getMonth() + 5);
            var date_none = date.toLocaleDateString().split("/");
            var mydate_max = (date_none[0] < 10 ? "0" + date_none[0] : date_none[0]).toString() + "-" + (date_none[1] < 10 ? "0" + date_none[1] : date_none[1]).toString();
            console.log(mydate_max);

            // var year_min = "2018";
            // var year_max = "2018";
            // // var month = date.getMonth() + 1;
            // var month_min = "1";
            // var month_max = "12";
            // month_min = (month_min < 10 ? "0" + month_min : month_min);
            // month_max = (month_max < 10 ? "0" + month_max : month_max);
            // var mydate_min = (year_min.toString() + '-' + month_min.toString());
            // var mydate_max = (year_max.toString() + '-' + month_max.toString());
            $$('.startTime').val(mydate_min);
            $$('.endTime').val(mydate_max);


            // 當前庫的名稱
            var data_name = "******";


            // 處罰搜索框時間
            $$('#tijiao').click(function () {

                // 重新加載
                func1();

            });
            // 處罰搜索框時間
            $$('#tijiao1').click(function () {

                // 重新加載
                func1();

            });


            // 視圖函數
            $$(
                func1()
            );


            function func1() {
                // 獲取當前日期搜索框日期
                var data_min = $$("#datemin").val();
                var data_max = $$("#datemax").val();


                if ($$("#flag").val() == "month") {
                    data_min = $$("#datemin").val();
                    data_max = $$("#datemax").val();


                }

                if ($$("#flag").val() == "week") {
                    data_min = $$("#datemin1").val();
                    data_max = $$("#datemax1").val();
                }


                // 次數-部門 柱狀圖
                $$.ajax({
                    url: "***",
                    type: "GET",
                    data: {"i1": data_name, "i2": data_min, "i3": data_max},
                    success: function (data) {
                        var data = JSON.parse(data);
                        var data_x = data[0];
                        var data_y = data[1];
                        // Set up the chart
                        $$('#container1').highcharts({
                            chart: {
                                type: 'column'
                            },
                            title: {
                                text: data_min + '' + data_max + ' 各部門違規人次'
                            },
                            subtitle: {
                                text: '人次/部門'
                            },
                            xAxis: {
                                categories: data_x
                            },
                            yAxis: {
                                min: 0,
                                title: {
                                    text: '違規人次'
                                }
                            },
                            tooltip: {
                                headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
                                pointFormat: '<tr><td style="color:{series.color};padding:0">共有</td>' +
                                    '<td style="padding:0"><b>{point.y:.1f} 次</b></td></tr>',
                                footerFormat: '</table>',
                                shared: true,
                                useHTML: true
                            },
                            plotOptions: {
                                column: {
                                    pointPadding: 0.2,
                                    borderWidth: 0,
                                    dataLabels: {enabled: true}
                                }
                            },
                            series: [{
                                name: '各部門',
                                data: data_y

                            }]
                        });


                    }
                });

                // 次數-部門 餅狀圖
                $$.ajax({
                    url: "***",
                    type: "GET",
                    data: {"i1": data_name, "i2": data_min, "i3": data_max},
                    success: function (data) {
                        var data = JSON.parse(data);
                        $$('#container2').highcharts({
                            chart: {
                                plotBackgroundColor: null,
                                plotBorderWidth: null,
                                plotShadow: false
                            },
                            title: {
                                text: data_min + '' + data_max + ' 各部門違規人次占比'
                            },
                            tooltip: {
                                pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
                            },
                            plotOptions: {
                                pie: {
                                    allowPointSelect: true,
                                    cursor: 'pointer',
                                    dataLabels: {
                                        enabled: true,
                                        color: '#000000',
                                        connectorColor: '#000000',
                                        format: '<b>{point.name}</b>: {point.percentage:.1f} %'
                                    }
                                }
                            },
                            series: [{
                                type: 'pie',
                                name: '占比',
                                data: data
                            }]
                        });


                    }
                });


                // 次數-月份 折線圖
                $$.ajax({
                    url: "***",
                    type: "GET",
                    data: {"i1": data_name, "i2": data_min, "i3": data_max},
                    success: function (data) {
                        var data = JSON.parse(data);
                        var data_x = data[0];
                        var data_y = data[1];
                        var date_type = data[2];
                        $$('#container3').highcharts({
                            chart: {
                                zoomType: 'xy',
                                spacingRight: 20
                            },
                            title: {
                                text: data_min + '' + data_max + ' 各個' + date_type + '違規人次'
                            },
                            subtitle: {
                                text: document.ontouchstart === undefined ?
                                    '人次/' + date_type :
                                    '人次/' + date_type
                            },
                            xAxis: {
                                type: 'linear',
                                categories: data_x,
                                title: {
                                    text: '' + date_type
                                }
                            },
                            yAxis: {
                                title: {
                                    text: '違規人次'
                                }
                            },
                            tooltip: {
                                shared: true
                            },
                            legend: {
                                enabled: false,
                                align: 'center',
                                verticalAlign: 'middle'
                            },
                            plotOptions: {
                                line: {
                                    dataLabels: {
                                        enabled: true
                                    }
                                },
                                area: {
                                    fillColor: {
                                        linearGradient: {x1: 0, y1: 0, x2: 0, y2: 1},
                                        stops: [
                                            [0, Highcharts.getOptions().colors[0]],
                                            [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
                                        ]
                                    },
                                    lineWidth: 1,
                                    marker: {
                                        enabled: false
                                    },
                                    shadow: false,
                                    states: {
                                        hover: {
                                            lineWidth: 1
                                        }
                                    },
                                    threshold: null
                                },

                            },
                            series: [{
                                name: "人次",
                                data: data_y
                            }]
                        });
                    }
                });

                // 人數-月份 柱狀
                $$.ajax({
                    url: "***",
                    type: "GET",
                    data: {"i1": data_name, "i2": data_min, "i3": data_max},
                    success: function (data) {
                        var data = JSON.parse(data);
                        var data_x = data[0];
                        var data_y = data[1];
                        var date_type = data[2];

                        // Set up the chart
                        $$('#container4').highcharts({
                            chart: {
                                type: 'column'
                            },
                            title: {
                                text: data_min + '' + data_max + ' 各個' + date_type + '違規人數'
                            },
                            subtitle: {
                                text: '人數/' + date_type
                            },
                            xAxis: {
                                categories: data_x
                            },
                            yAxis: {
                                min: 0,
                                title: {
                                    text: '違規人數'
                                }
                            },
                            tooltip: {
                                headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
                                pointFormat: '<tr><td style="color:{series.color};padding:0">本' + date_type + '共</td>' +
                                    '<td style="padding:0"><b>{point.y:.1f} 次</b></td></tr>',
                                footerFormat: '</table>',
                                shared: true,
                                useHTML: true
                            },
                            plotOptions: {
                                column: {
                                    pointPadding: 0.2,
                                    borderWidth: 0,
                                    dataLabels: {enabled: true}
                                }
                            },
                            series: [{
                                name: '' + date_type,
                                data: data_y

                            }]
                        });


                    }
                });


            }
        })();
    });

    //獲取選中的值
    function pickedSdate() {
        var _val = this.value,
            _name = this.name;
        if (_name == 'startTime') {
            $$('.sTime').text(_val);
        } else if (_name == 'endTime') {
            $$('.eTime').text(_val);
        }
        //執行統一搜索
    }

</script>
</body>
</html>

注意:以上后端使用web.py框架和前端使用H-ui框架,認真看並不難

數據庫類型如下:

id      名字    賬戶           違規內容             所屬周周一        所屬周周日           部門             所屬月份
1540 張* ****** 內勤請假登陸堡壘機 2019-02-25 2019-03-03 核心系統開發部 2019-02
1541    李*    ******    堡壘機違規操作          2019-03-11       2019-03-17        核心系統開發部      2019-03

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM