十八、WEB项目开发之统计报表“eCharts”

(一)背景介绍
  关于如何使用“eCharts”,这里我不做讲解,只概略讲一下,以后如何使用这一类工具的核心思想。
  其实像“eCharts”这种开源构件,已经封装的很完善了,我们大多在本地使用的时候,配置项设置好之后,就可以正常使用了,而在配置项中,一些数据源是需要我们从和后台查询的,而这部分数据又是融合在配置项中的,如何将后台查询到的数据填充到配置项中,这才是关键。本文就以“eCharts”为例,说一说如何将后台查询到的数据填充到配置项中。

(二)案例
  要想正常使用“eCharts”,我们必须配置好他的配置项,比如“eCharts”中的折线图堆叠中需要的配置项如下所示:

option = {
    title: {
        text: '折线图堆叠'
    },
    tooltip: {
        trigger: 'axis'
    },
    legend: {
        data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
    },
    grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true
    },
    toolbox: {
        feature: {
            saveAsImage: {}
        }
    },
    xAxis: {
        type: 'category',
        boundaryGap: false,
        data: ['周一','周二','周三','周四','周五','周六','周日']
    },
    yAxis: {
        type: 'value'
    },
    series: [
        {
            name:'邮件营销',
            type:'line',
            stack: '总量',
            data:[120, 132, 101, 134, 90, 230, 210]
        },
        {
            name:'联盟广告',
            type:'line',
            stack: '总量',
            data:[220, 182, 191, 234, 290, 330, 310]
        }
    ]
};

  而这里legend.data、xAxis.data、series.name和series.data是需要我们从后台查询数据来填充的。如何填充就是我们接下需要做的。

  解决这个问题的关键就在于在JS文件中“eCharts”配置项后使用:

    //深度拷贝
    $.extend(true,option,response.option);

  通过深度拷贝,将需要的数据填充进“option”,而拷贝的源,也就是上面的“response.option”就是我们需要通过Ajax请求,从后台获取的。
  后台返回的数据格式必须保证和“option”配置项相同,这样才能保证进行深度拷贝。所以我们在后台需要做的就是构建Option对象,将后台需要返回的legend.data、xAxis.data、series.name和series.data全部放进“response.option”中,代码如下:

//“option”配置项之legend属性
public class Legend implements Serializable {
    private List data;

    public List getData() {
        return data;
    }

    public void setData(List data) {
        this.data = data;
    }
}
//“option”配置项之xAxis属性
public class XAxis implements Serializable {
    private List data;

    public List getData() {
        return data;
    }

    public void setData(List data) {
        this.data = data;
    }
}
//“option”配置项之series属性中的单个数据
public class Serie implements Serializable {
    private String name;
    private String type = "line";
    private String stack;
    private List data;
}
//“option”配置项
public class Option implements Serializable {
    /**
     * 1、这里面成员变量名都必须和echarts的option属性中的变量名保持一致,这样才能保证拷贝成功
     * 2、各个成员变量对象包含哪些数据,根据echarts需要的数据需求,进行合理定制
     *     比如:option属性中的xAxis变量,我们在js中已经规定好了type和boundaryGap,所以我们这里只需要提供data属性即可
     */

    private Legend legend;
    private XAxis xAxis;
    private List series;
}

  通过Option对象,就将这些数据全部整合成一个对象了。接下来我们去获取数据,然后构造Option对象,部分代码如下:

@Override
    public Option constructOption(List<SalesStatistics> salesStatisticsList) {
        /*
         * Set:保证类别唯一(不会重复)
         * TreeSet:保证每次取出来的顺序是一样的(HashSet每次取出来的顺序都可能不一样)
         */
        Set<String> nameSet = new TreeSet<>();
        /*
         * 分析:因为同一类别不同时间段的数据需要组成一个集合,所以我们需要构建(“类别+时间”,数值)这样一个键值对,
         *       这样我们在构建整个数据集的时候,就可以通过“类别+时间”来确定有没有值,没有的用“0”补上
         */
        HashMap<String, String> datas = new HashMap<>();

        for (SalesStatistics salesStatistics : salesStatisticsList){
            String name = salesStatistics.getBusinessCategory();
            String hour = salesStatistics.getHour();
            Integer value = salesStatistics.getSalesNum();
            //构建类别名数据集
            nameSet.add(name);

            //构建(“类别+时间”,数值)Map集
            datas.put(name+hour, String.valueOf(value));
        }
        Option option = new Option();
        Legend legend = new Legend();
        XAxis xAxis = new XAxis();
        List<Serie> series = new ArrayList<>();

        //构造legend属性
        List<String> nameList = new ArrayList<>();
        nameList.addAll(nameSet);
        legend.setData(nameList);
        option.setLegend(legend);

        //构造xAxis属性
        List<String> hours = new ArrayList<>();
        for (int i=0; i<=23; i++){
            //格式化数据,不足两位,用0补齐
            hours.add(String.format("%02d", i));
        }
        xAxis.setData(hours);
        option.setxAxis(xAxis);

        //构造series属性

        //要求:同一个类别的组成一组数据,数据为空的,用0补齐

        /*
         * 问题:为什么先遍历name,再遍历hour?
         * 原因:这样就保证name相同的数值,能够合并到一个Serie对象中
         */
        for (String name : nameSet){
            Serie serie = new Serie();
            List<String> values = new ArrayList<>();
            for (String hour : hours){
                serie.setName(name);
                serie.setStack("总量");
                serie.setType("line");
                values.add(datas.get(name + hour) == null ? "0" : datas.get(name + hour));
            }
            serie.setData(values);
            series.add(serie);
        }
        option.setSeries(series);
        return option;
    }

你可能感兴趣的:(web项目开发)