納稅服務系統【統計圖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("統計投訴數失敗!");
                }
            });
        }
相關文章
相關標籤/搜索