纳税服务系统【统计图Fusionchart】
需求
我们在投诉模块中还有一个功能没有实现:
统计:根据年度将相应年度的每个月的投诉数进行统计,并以图表的形式展示在页面中;在页面中可以选择查看当前年度及其前4年的投诉数。在页面中可以选择不同的年度,然后页面展示该年度的曲线统计图。
我们到目前为止是没有学过任何的统计图的工具的,那么我们要怎么解决这个功能呢???我们有另外的组件来把统计图显示出来:FusionCharts
FusionCharts 是使用javascript 实现统计图表的js组件;其官网地址:http://www.fusioncharts.com。
具体的是怎么操作的可以看官方文档,我们以项目的需求来完成对应的功能就行了。
FusionCharts使用
FusionCharts安装
首先,我们要把对应的JS文档加入到我们的项目中:
- “fusioncharts.js”
- “fusioncharts.charts.js”
- 和相关主题文件复制到项目的js/fusioncharts文件夹。
引入Demo
我们只要根据修改Demo的值就可以实现出我们想要的效果了。
<!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进行交互,渲染出对应的统计图的。
我们的后端就是根据不同的年份,去获取不同的年份每个月的数据,返回给浏览器…
前端分析
我们的需求是得让我们显示近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}";
            }
            //2、统计年度投诉数据并展示图表
            $.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}";
            }
            //2、统计年度投诉数据并展示图表
            $.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("统计投诉数失败!");
                }
            });
        }纳税服务系统【统计图Fusionchart】的更多相关文章
- 纳税服务系统【信息发布管理、Ueditor、异步信息交互】
		需求分析 我们现在来到了纳税服务系统的信息发布管理模块,首先我们跟着原型图来进行需求分析把: 一些普通的CRUD,值得一做的就是状态之间的切换了.停用和发布切换. 值得注意的是:在信息内容中,它可以带 ... 
- 纳税服务系统【异常处理、抽取BaseAction】
		前言 本博文主要讲解在项目中异常是怎么处理的.一般我们都不会直接把后台异常信息返回给用户,用户是看不懂的.让用户看见一大串的错误代码,这是不合理的.因此我们需要对报错进行处理. 我们在开发的时候是使用 ... 
- 纳税服务系统【自动受理,Quartz任务调度】
		需求 回到我们的需求: 自动投诉受理:在每个月月底最后一天对本月之前的投诉进行自动处理:将投诉信息的状态改为 已失效.在后台管理中不能对该类型投诉进行回复. 这个需求需求我们要怎么弄呢????要在每个 ... 
- 纳税服务系统【抽取BaseService、条件查询】
		抽取BaseService 到目前为止,我们已经写了三个模块的开发了.我们已经抽取过了BaseAction.BaseDao,我们这次来看看我们的Service接口. UserService /** * ... 
- 纳税服务系统【用户模块之使用POI导入excel、导出excel】
		前言 再次回到我们的用户模块上,我们发现还有两个功能没有完成: 对于将网页中的数据导入或导出到excel文件中,我们是完全没有学习过的.但是呢,在Java中操作excel是相对常用的,因此也有组件供我 ... 
- IT服务系统组成
		软件+硬件+数据 + 运维人员 = IT服务系统 车 司机 乘客 修车 = 车模式 效率 系统 用户 业务 运维 = 信息化 效率 如果司机不会开车,没有人会修车就不会有车轮上的世界 同样没有人会运维 ... 
- 01——Solr学习之全文检索服务系统的基础认识
		一.为什么要用Solr,Solr是个什么东西? 1.1.Solr是个开源的搜索服务器 1.2.我们用Solr主要实现搜索功能,一般的网站首页都会有一个大大的搜索框,用来搜索此网站上的商品啊什么的,如下 ... 
- 基于Spring Boot、Spring Cloud、Docker的微服务系统架构实践
		由于最近公司业务需要,需要搭建基于Spring Cloud的微服务系统.遍访各大搜索引擎,发现国内资料少之又少,也难怪,国内Dubbo正统治着天下.但是,一个技术总有它的瓶颈,Dubbo也有它捉襟见肘 ... 
- SpringCloud(9)使用Spring Cloud OAuth2保护微服务系统
		一.简介 OAth2是一个标准的授权协议. 在认证与授权的过程中,主要包含以下3种角色. 服务提供方 Authorization Server. 资源持有者 Resource Server. 客户端 ... 
随机推荐
- jQuery选择器使用习惯
			http://www.cnblogs.com/fredlau/archive/2009/03/19/1416327.html 
- jdbc电话本项目
			整体思路:在登陆之后才能查看自己的电话本,电话本中包含用户名,联系人名字,电话,性别,分类: 1.登陆注册页面--数据库User表,注册登陆使用 2.电话本的前段显示,用表格和表单, 3.创建存取的电 ... 
- 【Centos7】卸载OpenJDK
			一般情况下,centos会自带OpenJDK,Hadoop的运行环境要求自己配置JRE,但在home下配置好了JRE后,使用java -version仍然看到OpenJDK,原因是系统根据$PATH路 ... 
- 如何理解 Python 的赋值逻辑
			摘要: 如果你学过 C 语言,那么当你初见 Python 时可能会觉得 Python 的赋值方式略有诡异:好像差不多,但又好像哪里有点不太对劲. 本文比较并解释了这种赋值逻辑上的差异.回答了为什么需要 ... 
- TensorFlow框架(1)之Computational Graph详解
			1. Getting Start 1.1 import TensorFlow应用程序需要引入编程架包,才能访问TensorFlow的类.方法和符号.如下所示的方法: import tensorflow ... 
- Hibernate注解-类级别注解
- XWPFDocument创建和读取Office Word文档基础篇(一)
			注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDo ... 
- selenium系列------元素定位套路
			selenium定位分为上三门,平三门,下三门, id,name,linktext上三门, class ,css,js平三门, xpath,tag名,复数定位(定位一组然后选index元素). 
- 分布式memcached-虚拟节点
			1.通过memcached服务器下的不同端口来达到模拟多台服务器的效果 2.假设现在有三台memcached服务器,本地分别使用11211,11212,11213三个端口来模拟 ①打开端口 ②连接端口 ... 
- Ibatis insert语句插入null引发的错误
			公司使用的orm框架为ibatis,其中默认的insert语句一直都是这样写的: <insert id="insert" parameterClass="activ ... 
