简单的网页应用项目,客户提供了简单的Dashboard数据展示需求;

对于那些 PowerBI那些专业数据钻取、统计、分析展示平台,这个客户的需求真的算是很简单了;

但是 难者不会 会者不难... 只好赶鸭子上架 去找 网页 柱状图、饼图等控件来学习;

无意中,找到了 ECharts ,真的发现极其非常适合本人的开发需求,简单、轻量、以及不错的自定义和扩展性;

https://echarts.apache.org/zh/index.html

写个随笔记录下自己研究的过程,主要是结合自己的开发工具及开发环境;

开发工具: VS2019 开发环境: .net core 3.1 采用MVC架构;

实现目标:网页显示 饼图、柱状图 ,动态从后台调取数据到前台来展示。

虽然我知道 Echarts 实际上是JS 轻量级图表解决方案,最合适的应该不是.net core mvc来搭配...

但是不是一个项目赶到这了... 项目是 .net core mvc 做的,再去换java 时间精力也不够了... 就一条道走到黑吧... 

 

 

  

 

在VS2019中安装Echarts不是在NuGet里, 而是右键点击 wwwroot 再选择添加 -> 客户端库

 

 

 输入 echarts 会出现最新的 @4.8.0版本,下面的文件就先全选上吧...然后点 安装

 

在_Layout.cshtml 视图的head段,加入js :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - EchartTry</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
    <script src="~/echarts/echarts.min.js"></script>
</head>

然后把Home对应的视图改成: 

@{
    ViewData["Title"] = "Home Page";
}

    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <div class="container">
            <div class="row">
                <div class="col" id="left" style="width: 400px;height:400px;">

                </div>
                <div class="col" id="right" style="width: 400px;height:400px;">

                </div>
            </div>
            <div class="row">
                <div class="col" id="bottom" style="width: 800px;height:400px;">

                </div>
            </div>
        </div>
        <script type="text/javascript">
            var myleftChart = echarts.init(document.getElementById('left'));
            var myrightChart = echarts.init(document.getElementById('right'));
            var mybottomChart = echarts.init(document.getElementById('bottom'));

            var leftoption = {
                title: {
                    text: '生产情况'
                },
                legend: {
                    data: ['正常','异常']
                },
                series: [{
                    type: 'pie',
                    data: [{ name: '正常', value: 1080 }, { name: '异常', value: 220 }],
                    label:
                    {
                        formatter: '{b}:{c}\n{d}%'
                    }
                }]
            };

            var rightoption = {
                title: {
                    text: '产品型号比例'
                },
                legend: {
                    data: ['型号A', '型号B', '型号C', '型号D']
                },
                series: [{
                    type: 'pie',
                    data: [{ name: '型号A', value: 380 },
                        { name: '型号B', value: 100 },
                        { name: '型号C', value: 80 },
                        { name: '型号D', value: 400 }],
                    label:
                    {
                        formatter: '{b}:{c}\n{d}%'
                    }
                }]
            };

            var bottomoption = {
                title: {
                    text: 'ECharts 入门示例'
                },
                tooltip: {},
                legend: {
                    data: ['销量']
                },
                xAxis: {
                    data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
                },
                yAxis: {},
                series: [{
                    name: '销量',
                    type: 'bar',
                    data: [5, 20, 36, 10, 10, 20]
                }]
            };

            myleftChart.setOption(leftoption);
            myrightChart.setOption(rightoption);
            mybottomChart.setOption(bottomoption);
        </script>
    </div>

跑起来看看:

 

 哈,像那么回事。。。

下面要继续的研究工作:

1、一些需要的特殊显示要求的实现;

2、如何从后台动态调数据到前台;

3、第2个项目调数据时 需要ajax方式;

 

初步考虑思路:

1、增加一个WEB API 提供数据;

2、视图中通过ajax 调WEB API获取数据后,刷新图表;

3、先做 柱状图 ,以月份为输入条件,然后横坐标显示月份内的每一天的生产产量;

第一步,先定义一个模型

    public class SummaryData
    {
        public string title { get; set; }
        public string[] categories { get; set; }
        public int[] data { get; set; }
    }

 

第二步:加一个WEB API控制器,就用默认名字 ValuesController

 就通过日期来模拟出一个月的产量数据(用随机数代替...正常的应该是去数据库取数据)

     [HttpGet]
        public ActionResult<SummaryData> Get()
        {
            return GetMonthlyData(null);
        }

        [HttpGet("{id}")]
        public ActionResult<SummaryData> Get(DateTime id)
        {                       
            return GetMonthlyData(id);
        }

        private SummaryData GetMonthlyData(DateTime? month)
        {
            var newData = new SummaryData();
            DateTime chartMonth;
            if (month == null)
            {
                chartMonth = DateTime.Today;
            }
            else
            {
                chartMonth = (DateTime)month;
            }
            newData.title = chartMonth.Year + "" + chartMonth.Month + "月 每日生产量";
            int days = DateTime.DaysInMonth(chartMonth.Year, chartMonth.Month);
            newData.categories = new string[days];
            newData.data = new int[days];
            for (int i = 1; i <= days; i++)
            {
                newData.categories[i - 1] = i.ToString().PadLeft(2, '0');
                newData.data[i - 1] = GetRandomNumber(50, 400);
            }
            return newData;
        }
        private int GetRandomNumber(int min, int max)
        {
            int rtn = 0;
            Random r = new Random();
            byte[] buffer = Guid.NewGuid().ToByteArray();
            int iSeed = BitConverter.ToInt32(buffer, 0);
            r = new Random(iSeed);
            rtn = r.Next(min, max + 1);
            return rtn;
        }

Home视图改下:

@{
    ViewData["Title"] = "Home Page";
}

    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <div class="container">
            <div>
                <input type="month" id="inputdate" onchange="refresh(this.value)" value="@ViewData["SearchDate"]"  />          
            </div>
            <div class="row">
                <div class="col" id="left" style="width: 800px;height:400px;">

                </div>
                <div class="col" id="right" style="width: 800px;height:400px;">

                </div>
            </div>
            <div class="row">
                <div class="col" id="bottom" style="width: 1600px;height:400px;">

                </div>
            </div>
        </div>
        <script type="text/javascript">
            var myleftChart = echarts.init(document.getElementById('left'));
            var myrightChart = echarts.init(document.getElementById('right'));
            var mybottomChart = echarts.init(document.getElementById('bottom'));
            var leftoption = {
                title: {
                    text: '生产情况'
                },
                legend: {
                    data: ['正常','异常']
                },
                series: [{
                    type: 'pie',
                    data: [{ name: '正常', value: 1080 }, { name: '异常', value: 220 }],
                    label:
                    {
                        formatter: '{b}:{c}\n{d}%'
                    }
                }]
            };
            var rightoption = {
                title: {
                    text: '产品型号比例'
                },
                legend: {
                    data: ['型号A', '型号B', '型号C', '型号D']
                },
                series: [{
                    type: 'pie',
                    data: [{ name: '型号A', value: 380 },
                        { name: '型号B', value: 100 },
                        { name: '型号C', value: 80 },
                        { name: '型号D', value: 400 }],
                    label:
                    {
                        formatter: '{b}:{c}\n{d}%'
                    }
                }]
            };

            var bottomoption = {
                title: {
                    text: ''
                },
                tooltip: {},
                legend: {
                    data: ['']
                },
                xAxis: {
                    data: []
                },
                yAxis: {},
                series: [{
                    name: '',
                    type: 'bar',
                    data: []
                }]
            };

            myleftChart.setOption(leftoption);
            myrightChart.setOption(rightoption);
            mybottomChart.setOption(bottomoption);

            window.onload = function () {
                $.ajax({
                    url: "/api/values/",
                    type: "get",
                    dataType: "json",
                    success: function (data) {
                        mybottomChart.hideLoading();
                        mybottomChart.setOption({
                            title: {
                                text: data.title
                            },
                            legend: {
                                data: ['产量']
                            },
                            xAxis: {
                                data: data.categories
                            },
                            yAxis: {},
                            series: [{
                                // 根据名字对应到相应的系列
                                name: '产量',
                                data: data.data
                            }]
                        });
                    }
                });
            }           

            function refresh(month) {
                mybottomChart.showLoading();
                $.ajax({
                    url: "/api/values/" + month,
                    type: "get",
                    dataType: "json",
                    success: function (data) {
                        mybottomChart.hideLoading();
                        mybottomChart.setOption({
                            title: {
                                text: data.title
                            },
                            legend: {
                                data: ['产量']
                            },
                            xAxis: {
                                data: data.categories
                            },
                            yAxis: {},
                            series: [{
                                // 根据名字对应到相应的系列
                                name: '产量',
                                data: data.data
                            }]
                        });
                    }
                });
            };            
        </script>
    </div>

Run起来看看效果:

 

 

 

下一步:在月度每日的柱状图上点击后,再显示一个当日的分时柱状图; 

在Home视图增加一个Div 放入 月柱状图的下面:

            <div class="row">
                <div class="col" id="bottom" style="width: 1600px;height:400px;">

                </div>
            </div>
            <div class="row">
                <div class="col" id="dailybar" style="width: 1600px;height:400px;">

                </div>
            </div>        

然后在JS语句后面继续增加以下代码:

var mydailybarChart = echarts.init(document.getElementById('dailybar'));

var dailybaroption = {
                title: {
                    text: ''
                },
                tooltip: {},
                legend: {
                    data: ['']
                },
                xAxis: {
                    data: []
                },
                yAxis: {},
                series: [{
                    name: '',
                    type: 'bar',
                    data: []
                }]
            };

mydailybarChart.setOption(dailybaroption);

mybottomChart.on('click', function (params) {
                mydailybarChart.showLoading();
                $.ajax({
                    url: "/api/DailyDatas/" + inputdate.value + "?selectindex=" + params.dataIndex,
                    type: "get",
                    dataType: "json",
                    success: function (data) {
                        mydailybarChart.hideLoading();
                        mydailybarChart.setOption({
                            title: {
                                text: data.title
                            },
                            legend: {
                                data: ['产量']
                            },
                            xAxis: {
                                data: data.categories
                            },
                            yAxis: {},
                            series: [{
                                // 根据名字对应到相应的系列
                                name: '产量',
                                data: data.data
                            }]
                        });
                    }
                });
            });

增加一个DailyDatas 的WEB API控制器:

   public class DailyDatasController : ControllerBase
    {

        [HttpGet("{id}")]
        public ActionResult<SummaryData> Get(string id, [FromQuery] int selectindex)
        {
            DateTime dt_Select = DateTime.Parse(id + "-" + (selectindex + 1) + " 00:00:00");

            return GetDailyData(dt_Select);
        }
        private SummaryData GetDailyData(DateTime day)
        {
            var newData = new SummaryData();           
            newData.title = day.ToString("yyyy-MM-dd") + " 小时生产量";
            
            newData.categories = new string[10];
            newData.data = new int[10];
            for (int i = 8; i <= 17; i++)
            {
                newData.categories[i - 8] = i.ToString().PadLeft(2, '0') + ":00";
                newData.data[i - 8] = GetRandomNumber(10, 50);
            }
            return newData;
        }

        private int GetRandomNumber(int min, int max)
        {
            int rtn = 0;
            Random r = new Random();
            byte[] buffer = Guid.NewGuid().ToByteArray();
            int iSeed = BitConverter.ToInt32(buffer, 0);
            r = new Random(iSeed);
            rtn = r.Next(min, max + 1);
            return rtn;
        }
    }