纳税服务系统【统计图Fusionchart】

需求

咱们在投诉模块中还有一个功能没有实现:javascript

统计:根据年度将相应年度的每月的投诉数进行统计,并以图表的形式展现在页面中;在页面中能够选择查看当前年度及其前4年的投诉数。在页面中能够选择不一样的年度,而后页面展现该年度的曲线统计图。php

咱们到目前为止是没有学过任何的统计图的工具的,那么咱们要怎么解决这个功能呢???咱们有另外的组件来把统计图显示出来:FusionChartshtml

FusionCharts 是使用javascript 实现统计图表的js组件;其官网地址:http://www.fusioncharts.com。前端

具体的是怎么操做的能够看官方文档,咱们以项目的需求来完成对应的功能就好了。java


FusionCharts使用

FusionCharts安装

首先,咱们要把对应的JS文档加入到咱们的项目中:ajax

  • “fusioncharts.js”
  • “fusioncharts.charts.js”
  • 和相关主题文件复制到项目的js/fusioncharts文件夹。

引入Demo

咱们只要根据修改Demo的值就能够实现出咱们想要的效果了。sql

<!DOCTYPE HTML>
<html>
<head>
    <%@include file="/common/header.jsp" %>
    <title>年度投诉统计图</title>
    <script type="text/javascript" src="${basePath}js/fusioncharts.js"></script>
    <script type="text/javascript" src="${basePath}js/fusioncharts.charts.js"></script>
    <script type="text/javascript" src="${basePath}js/themes/fusioncharts.theme.fint.js"></script>
    <script> FusionCharts.ready(function () { var revenueChart = new FusionCharts({ "type": "column2d", "renderAt": "chartContainer", "width": "500", "height": "300", "dataFormat": "json", "dataSource": { "chart": { "caption": "Monthly revenue for last year", "subCaption": "Harry's SuperMart", "xAxisName": "Month", "yAxisName": "Revenues (In USD)", "theme": "fint" }, "data": [ { "label": "Jan", "value": "420000" }, { "label": "Feb", "value": "810000" }, { "label": "Mar", "value": "720000" }, { "label": "Apr", "value": "550000" }, { "label": "May", "value": "910000" }, { "label": "Jun", "value": "510000" }, { "label": "Jul", "value": "680000" }, { "label": "Aug", "value": "620000" }, { "label": "Sep", "value": "610000" }, { "label": "Oct", "value": "490000" }, { "label": "Nov", "value": "900000" }, { "label": "Dec", "value": "730000" } ] } }); revenueChart.render(); }) </script>
</head>


<body>
<br>
<s:select id="year" list="{2015}" onchange="doAnnualStatistic()"></s:select>
<br>
<div id="chartContainer"></div>
</body>
</html>

需求分析

再次回到咱们的需求原型图,咱们看看是怎么样的:数据库

这里写图片描述

根据不一样的年份,就显示出不一样的统计图数据…..这明显就用到了ajax技术。 所以能够肯定下来,咱们的前端就是用ajax进行交互,渲染出对应的统计图的。编程

咱们的后端就是根据不一样的年份,去获取不一样的年份每月的数据,返回给浏览器json

前端分析

咱们的需求是得让咱们显示近5年的统计图…因而下拉框是咱们近5年的….

咱们虽然是能够把option中的数据写死,可是呢,若是过了一年的话,那么咱们的数据是不会同步的。当我在2017年写的时候,到2018年,页面显示仍是2017年的数据….因此这明显是不合理的….

要想近5年是动态产生的,就不可以把数据写死….因而咱们能够在JSP页面上获得当前年的值,根据当前年就很是容易推出近5年的数据了…

因而咱们又可使用到Calendar这个日历类了…

在JSP页面获得当前年的数据,并装载到list集合中

Calendar calendar = Calendar.getInstance();

    //获得当前年的值
    int  year = calendar.get(Calendar.YEAR);

    //把年份用一个集合装载
    List yearList = new ArrayList();

    //获取近5年的值
    for(int i =0; i<5; i++) {
        yearList.add(i, year--);
    }
    request.setAttribute("yearList", yearList);
    request.setAttribute("year", year);

在Struts的select标签中把这个集合迭代出来

<s:select id="year" list="#request.yearList" onchange="doAnnualStatistic()"></s:select>

下面是咱们的效果:

这里写图片描述


接着,咱们发现FusionCharts这个组件,想要把数据显示在统计图表中,咱们的JSON数据的格式是须要这样的

这里写图片描述

还有值得注意的地方是,一进入页面中须要加载当前年度的投诉统计数

<script> //页面一加载就执行方法 $(function () { doAnnualStatistic(); }); //根据年份获取投诉数 function doAnnualStatistic() { //获取当前年份 var $year = $("#year option:selected").val(); //一进来,若是没有选择任何的年数,就显示当前年份的 if($year=="" || $year==undefined) { $year = "${year}"; } //二、统计年度投诉数据并展现图表 $.ajax({ url: "${basePath}complain/complain_getAnnualStatisticData.action", type: "post", dataType: "json", data: {"year",$year}, success: function (backData) { if(backData!=null && backData!=""){ var revenueChart = new FusionCharts({ "type": "line", "renderAt": "chartContainer", "width": "600", "height": "400", "dataFormat": "json", "dataSource": { "chart": { "caption": "年度统计投诉数", "xAxisName": "月 份", "yAxisName": "投 诉 数", "theme": "fint" }, "data":backData.chartData } }); revenueChart.render(); } }, error:function () { alert("统计投诉数失败!"); } }); } </script>

后端分析

咱们的后端就是根据年份,获取对应的值,返回一个JSON格式给浏览器,那就好了…

可是呢,咱们还有其余的细节须要考虑:今年是2017年7月,可是在查询年度投诉数是要把整个年的信息查询出来,8-12月的投诉数确定是没有的。那么咱们会将还没到的时间设置成“”,若是在2016年的某月是没有投诉数的,咱们应该将其替换成0,而不是“”….

在action中,咱们得获取到用户传递过来的年份,咱们调用service、dao层的方法获取该年度对应每月的投诉数,转换成JSON格式输出就好了。

咱们知道前端须要的JSON格式是一个对象数组,最终目的就是数组:Struts2框架在最后解析的时候,会把集合解析成是数组。对象数组在java编程语言就是List集合中嵌套着Map集合。

在后端中,还有一个难点,就是咱们的SQL语句该怎么写????咱们要从数据库查询的是该年份每月的投诉数….

经过该年而查询每月,咱们能够很快地想到要用到分组查询。可是还有一个问题,咱们在进行分组查询的时候,若是表中是没有1月或2月等数组的话,分组查询出来的数据是没有这些月份的。而咱们的统计图是须要全部月份的数据的。咋看一下,咱们是须要把查询出来的数据作循环判断,得看看有没有该月份,若是没有该月份还得把数据填充进去。。还得判断该月份是否是本年度的….这样想一下就以为麻烦了……

select month(comp_time) as '月份',count(*) '总数' from complain where year(comp_time)=? group by month(comp_time)

这里写图片描述


再次回到前面分析的,若是本年度的月份尚未到,那么将该月的数据设置为“”,若是是其余年份的的月份查出的数据为null,那么咱们应该把这些月份的投诉数设置为0而不是”“…..

可是呢,咱们如今有一个办法,能够在查询的时候,无论该月份有没有数据,都得显示出来….这就是左外链接

因而咱们本身手动生成一张拥有12个月份的数据表,跟咱们的投诉表进行左外链接…

这里写图片描述

select imonth, count(comp_id) from t_month left join complain on imonth=month(comp_time) and year(comp_time)=2017 group by imonth order by imonth;

这里写图片描述

上面的sql语句的查询效率是有点低的,咱们改造一下,改为是子查询:

select imonth,c2 from t_month left join (select month(comp_time) c1, count(comp_id) c2 from complain where year(comp_time)=? group by month(comp_time)) t on imonth = c1 order by imonth;

代码实现

dao层根据年份查询出每月份的投诉数据

/** * * @param year 根据年获取数据 * @return 返回的是一个列表数组 */
    @Override
    public List<Object[]> getAnnualStatisticByYear(int year) {


        //拼接SQL语句
        StringBuffer buffer = new StringBuffer();
        buffer.append(" SELECT imonth,c2 ")
        .append(" FROM t_month")
        .append(" LEFT JOIN (SELECT month(comp_time) c1, count(comp_id) c2 FROM complain WHERE YEAR(comp_time)=? GROUP BY MONTH(comp_time)) t")
        .append(" ON imonth = c1")
        .append(" ORDER BY imonth;");
        SQLQuery sqlQuery = getSession().createSQLQuery(buffer.toString());
        sqlQuery.setParameter(0, year);

        List<Object[]> list = sqlQuery.list();
        return list;
    }

service层拿到Dao层的数据,判断是不是本年度的,若是是本年度的,那么尚未到的月份的数据就设置为”“,若是已通过的了月份,若是没有数据就设置为0.

返回一个List集合嵌套着Map集合,就能够给前台解析了。

@Override
    public List getAnnualStatisticByYear(int year) {

        List<Object[]> annualStatisticByYear = complainDao.getAnnualStatisticByYear(year);

        List<Map> returnList = new ArrayList<>();

        //获得本年度和本月份
        int curYear = Calendar.getInstance().get(Calendar.YEAR);
        //Calerdar月份从0开始,
        int curMonth = Calendar.getInstance().get(Calendar.MONTH)+1;

        //使用Map集合装载着数据
        Map<String,Object> map = null;
        for (Object[] objects : annualStatisticByYear) {
            map = new HashedMap();
            //获得月份
            Integer month = Integer.valueOf(objects[0] + "");
            map.put("label", month + "月");
            if (curYear == year) { //是本年度,那么看看月份是否大于本月份
                if (month > curMonth) {
                    //将数据设置为""
                    map.put("value", "");
                } else {
                    if (objects[1] != null) {
                        map.put("value", objects[1]);
                    } else {
                        map.put("value", "0");
                    }
                }
            }else {//不是本年度
                if (objects[1] != null) {
                    map.put("value", objects[1]);
                } else {
                    map.put("value", "0");
                }
            }
            returnList.add(map);
        }
        return returnList;
    }

action层把service层的数据封装到Map集合中,嵌套ajax解析Map集合,获得的就是对象数组了。

//返回JSON格式的数据,这里咱们就直接用Struts2框架来返回对应的数据就好了。
    public String getAnnualStatisticData() {

        //获取用户传递过来的年份
        String str_year = ServletActionContext.getRequest().getParameter("year");
        if (str_year != null) {
            int year = Integer.valueOf(str_year);
            //根据年份去获取每月的投诉数
            map.put("msg", "success");
            map.put("chartData", complainServiceImpl.getAnnualStatisticByYear(year));
        }
        return "getAnnualStatisticData";
    }

前台把年份提交给Action,解析出后台返回的数据,渲染成折线图….

function doAnnualStatistic() {
            //获取当前年份
            var $year = $("#year option:selected").val();

            //一进来,若是没有选择任何的年数,就显示当前年份的
            if($year=="" || $year==undefined) {
               $year = "${year}";
            }
            //二、统计年度投诉数据并展现图表
            $.ajax({
                url: "${basePath}complain/complain_getAnnualStatisticData.action",
                type: "post",
                dataType: "json",
                data: {"year":$year},
                success: function (backData) {
                    if(backData!=null && backData!=""){
                        var revenueChart = new FusionCharts({
                            "type": "line",
                            "renderAt": "chartContainer",
                            "width": "600",
                            "height": "400",
                            "dataFormat": "json",
                            "dataSource": {
                                "chart": {
                                    "caption": "年度统计投诉数",
                                    "xAxisName": "月 份",
                                    "yAxisName": "投 诉 数",
                                    "theme": "fint"
                                },
                                "data":backData.chartData
                            }
                        });
                        revenueChart.render();
                    }
                },
                error:function () {
                    alert("统计投诉数失败!");
                }
            });
        }
相关文章
相关标签/搜索