基于SpringMVC +前台页面基于bootstrap 的 echats+jquery.slider 堆积图

实现要点
1、基于jquery.slider 动态设置series,数据基于前台动态渲染。
2、legend的动态创建。


效果图:


基于SpringMVC +前台页面基于bootstrap 的 echats+jquery.slider 堆积图
文章图片




JSP页面源码:
【基于SpringMVC +前台页面基于bootstrap 的 echats+jquery.slider 堆积图】

APP统计| 神州专车 - 锐客网 /*以下样式重写slider的样式*/ .slider-selection{background:#e48d0c; } .slider-track{background-image: linear-gradient(to bottom,#BABABA 0,#BABABA 100%); } .slider-handle{width:10px; }查询条件
用户成分分析: 当天至7天前新增
用户新鲜度


freshness.js源码:
/** * 用户新鲜度模块 * @author 石冬冬 * @date 2016/12/1 */ var Freshness = { Cts:{ charts:{ render:null, viewData:null, totals:[] }, limit:[0,31], rs:null }, /** * 初始化 */ init:function(){ this.initEvts(); this.initVals(); this.initSlideBar(false); this.initData(); this.renderCharts(); }, /** * 初始化事件 */ initEvts:function(){ var _this = Freshness; $('#btnQuery').off().live('click',function(){ _this.initData(); _this.renderCharts(); }); //选项卡切换 $('a[eleType=tab]').off().live('click',function(){ var dataType = $(this).attr('dataType'); $('#dataType').val(dataType); _this.initData(); _this.renderCharts(); }); $('#slideBarCheckbox').off().live('click',function(){ var checked = $(this).attr('checked'); var enabled = checked=='checked'; _this.initSlideBar(enabled); }); }, /** * 初始化相关元素的值 */ initVals:function(){ var appVersion = $('#appVersionList').val(); if(appVersion){ appVersion = eval('('+appVersion+')'); loadData(appVersion); } }, /** * 初始化标尺滚动条 * @param enabled * API:http://demo.htmleaf.com/1502/201502041438/index.html * http://blog.csdn.net/u011127019/article/details/52992654 */ initSlideBar:function(enabled){ var _this = Freshness; //初始化配置项 $("#slideBar").slider({ handle:'round', min:0, max:31, step:1, value:[0,31], tooltip_split:true, formatter: function(value) { var start = value[0]; var end = value[1]; if(start==0){ start = '当天'; }else{ start+='天前'; } if(end==31){ end = '31天+前'; }else{ end+='天前'; } var tips = start+'至'+end+'新增'; if(value && $.isArray(value) && value.length==2){ $('#slideBarTips').text(tips); } return value; } }); //监听滑动事件 $("#slideBar").on("change", function() { var value = https://www.it610.com/article/this.value.split(","); if(value){ _this.Cts.limit=value; _this.renderCharts(); //刷新加载echarts } }); //根据可用多选框设置控件是否可用 if(enabled){ $('#slideBarTips').show(); $("#slideBar").slider("enable"); }else{ $('#slideBarTips').hide(); $("#slideBar").slider("setValue",[0,31]); $("#slideBar").slider("disable"); _this.Cts.limit=[0,31]; _this.renderCharts(); //刷新加载echarts } }, /** * 初始化报表 * @param args 对象 * @param xAxisData x坐标数组 */ initCharts:function(args,xAxisData){ var dataType = $('#dataType').val(); var _yAxis = [ { type : 'value', boundaryGap : false } ]; if(dataType=='BFB'){ _yAxis = [ { type : 'value', max:'100', axisLabel: { show: true, interval: 'auto', formatter: '{value} %' }, boundaryGap : false } ]; } var _this = Freshness; var series = args.seriesData; var legendData = https://www.it610.com/article/args.legendData; var myChart = echarts.init(document.getElementById("chart_div"), 'line'); this.Cts.charts.render = myChart; var option = { title : { }, tooltip : { trigger: 'axis', formatter:function (params,ticket,callback) { var tips = ''; if(dataType=='JDZ'){ var seriesName = params.seriesName; var value = https://www.it610.com/article/params.value; var name = params.name; var total = _this.findTotal(name); var ratio = 0; if(total!=0){ ratio = ((value / total)*100).toFixed(2); } tips = name +'

在' + seriesName + '新增(占当日活跃比):
'+ value + '('+ratio+'%)' + '

当日全部活跃:'+total; } if(dataType=='BFB'){ var seriesName = params.seriesName; var name = params.name; var total = _this.findTotal(name); var value = https://www.it610.com/article/params.value; value = value/100*total; var ratio = 0; if(total!=0){ ratio = ((value / total)*100).toFixed(2); } tips = name +'

在' + seriesName + '新增(占当日活跃比):
'+ value + '('+ratio+'%)' + '

当日全部活跃:'+total; } return tips; } }, legend: { show:false, width:'80%', padding: [5,100,5,100], itemGap: 10, data : legendData }, dataZoom:{}, toolbox: { show : true, feature : { mark : {show: false}, dataView : {show: true, readOnly: false}, magicType: {show: true, type: ['line','bar','stack', 'tiled']}, restore : {show: true}, saveAsImage : {show: true} } }, calculable : true, xAxis : [{ type:'category', interval:0, boundaryGap:false, data:xAxisData }], yAxis : _yAxis, series : series }; myChart.setOption(option); }, /** * 根据series的datas构建seriesData和legendData * @param datas */ initSeries:function(datas){ var _this = Freshness; var limit = _this.Cts.limit; console.log('limit=%s',JSON.stringify(limit)); var from = Number(limit[0]) ; var to = Number(limit[1]); var legendData = https://www.it610.com/article/[]; var series = []; for(var i=to; i>=from; i--){ var name = i+'天前'; if(i==0){ name = '当天'; } if(i==31){ name = '30+天前'; } legendData.push(name); var vo = { name: name, type: 'line', stack:'1', tooltip : { show : true, trigger: 'item' }, areaStyle: {normal: {}}, data: datas[i] }; series.push(vo); } return { seriesData:series, legendData:legendData }; }, /** * 初始化数据 */ initData:function(){ var params = $('#searchForm').serialize(); var _this = Freshness; $.ajax({ type : "post", url : BATH_PATH + "retentionAnalysis/loadForFreshness", data: params, dataType : "json", async : false, error : function(xhr, status, err) { //alert(err); }, success : function(rs) { _this.Cts.rs = rs; } }); }, /** * 根据容量构建二维数组 * @returns {Array} 二维数组 */ initArrays:function(){ var capacity = 31; var arrays = []; for(var i = 0; i<=capacity; i++){ arrays.push([]); } return arrays; }, /** * 根据xAxisName 查询对应的 活跃总数 * @param xAxisName */ findTotal:function(xAxisName){ var totals = this.Cts.charts.totals; var total = 0; if(totals){ $.each(totals,function(index){ //console.log('key=%s,val=%s',totals[index].key,val); if(totals[index].key == xAxisName){ total = totals[index].total; return; } }); } return total; }, /** * 渲染Charts * @param rs */ renderCharts:function(){ var _this = Freshness; var rs = _this.Cts.rs; var dataType = $('#dataType').val(); var xAxisData = https://www.it610.com/article/[]; var datas = this.initArrays(); var totals = []; if(rs){ var data = rs.dataMap; //======================绝对值============================= if(dataType=='JDZ'){ $.each(data,function(key,vo){ xAxisData.push(key); totals.push({key:key,total:vo.total}); //console.log('key=%s,total=%s',key,vo.total); $.each(vo.groupMap,function(index,val){ datas[index].push(val); }); }); //console.info("arrays=%s",JSON.stringify(datas)); } //======================百分比============================= if(dataType=='BFB'){ $.each(data,function(key,vo){ xAxisData.push(key); var total = vo.total; totals.push({key:key,total:total}); //console.log('key=%s,total=%s',key,vo.total); $.each(vo.groupMap,function(index,val){ var percent = (val==0)?0:((val/total)*100).toFixed(2); datas[index].push(percent); }); }); }} //console.log('totals=%s',JSON.stringify(totals)); _this.Cts.charts.totals = totals; //console.log('totals=%s',JSON.stringify(_this.Cts.charts.totals)); var args = _this.initSeries(datas); _this.initCharts(args,xAxisData); } }; Freshness.init();


Controller
package com.ucar.appcount.web.controller; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.ucar.appcount.common.Common; import com.ucar.appcount.common.vo.SearchObject; import com.ucar.appcount.service.AdminManagerServiceNew; import com.ucar.appcount.service.RetentionAnalysisService; import com.zuche.framework.utils.StringUtils; /** * 留存分析 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-28 下午6:53:41 */ @Controller @RequestMapping("retentionAnalysis") public class RetentionAnalysisController { private static final Logger logger = Logger.getLogger(RetentionAnalysisController.class); @Autowired private AdminManagerServiceNew adminManagerServiceNew; @Autowired private RetentionAnalysisService retentionAnalysisService; private final String PAGE_PREFIX = "retention/"; /** * 留存用户|页面 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-28 下午7:01:07 * @param model * @param searchObj * @return */ @RequestMapping("retention") public String retention(Model model,SearchObject searchObj){ try { List appChannel = adminManagerServiceNew.getAppChannel(); List appVersion = adminManagerServiceNew.getAppVersion(); String timeType = searchObj.getTimeType(); String columnTitleSuffix = "天后"; if(StringUtils.isEmpty(timeType)){ timeType = Common.DATATYPE.DAY; } initSearchObj(searchObj); if(Common.DATATYPE.DAY.equals(timeType)){ model.addAttribute("columns", RetentionAnalysisService.ReportTitle.DAILY); columnTitleSuffix = "天后"; } if(Common.DATATYPE.WEEK.equals(timeType)){ model.addAttribute("columns", RetentionAnalysisService.ReportTitle.WEEK); columnTitleSuffix = "周后"; } if(Common.DATATYPE.MONTH.equals(timeType)){ model.addAttribute("columns", RetentionAnalysisService.ReportTitle.MONTH); columnTitleSuffix = "月后"; } model.addAttribute("columnTitleSuffix", columnTitleSuffix); model.addAttribute("searchObj", searchObj); model.addAttribute("appChannel",appChannel); model.addAttribute("appVersion", appVersion); } catch (Exception e) { logger.error("留存用户初始化异常",e); } return PAGE_PREFIX.concat("retention"); } /** * 用户新鲜度 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-12-1 下午2:00:31 * @param model * @param searchObj * @return */ @RequestMapping("freshness") public String freshness(Model model,SearchObject searchObj){ try { List appChannel = adminManagerServiceNew.getAppChannel(); List appVersion = adminManagerServiceNew.getAppVersion(); String timeType = searchObj.getTimeType(); if(StringUtils.isEmpty(timeType)){ timeType = Common.DATATYPE.DAY; } SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); //开始时间为空则取三个月前 if(StringUtils.isBlank(searchObj.getBeginTime())){ Calendar calendar=Calendar.getInstance(); calendar.add(Calendar.MONTH,-1); searchObj.setBeginTime(sdf.format(calendar.getTime())); } if(StringUtils.isBlank(searchObj.getEndTime())){ Calendar calendar=Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR,-1); searchObj.setEndTime(sdf.format(calendar.getTime())); } searchObj.setDataType("JDZ"); //默认 绝对值 model.addAttribute("searchObj", searchObj); model.addAttribute("appChannel",appChannel); model.addAttribute("appVersion", appVersion); } catch (Exception e) { logger.error("留存用户初始化异常",e); } return PAGE_PREFIX.concat("freshness"); } /** * 留存用户 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-29 上午9:53:00 * @param searchObj * @return */ @RequestMapping("loadForRetention") @ResponseBody public Object loadForRetention(SearchObject searchObj){ Map dataMap = new HashMap(); if(!StringUtils.isBlank(searchObj.getTimeType())){ Map> result =this.retentionAnalysisService.retention(searchObj); dataMap.put("data", result); } return dataMap; } /** * 用户新鲜度 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-29 上午9:53:00 * @param searchObj * @return */ @RequestMapping("loadForFreshness") @ResponseBody public Object loadForFreshness(SearchObject searchObj){ return this.retentionAnalysisService.freshness(searchObj); }@RequestMapping("activeDegree") public String toActiveDegree(Model model,SearchObject searchObj){ List appChannel = adminManagerServiceNew.getAppChannel(); List appVersion = adminManagerServiceNew.getAppVersion(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); //开始时间为空则取三个月前 if(StringUtils.isBlank(searchObj.getBeginTime())){ Calendar calendar=Calendar.getInstance(); calendar.add(Calendar.MONTH,-1); searchObj.setBeginTime(sdf.format(calendar.getTime())); } if(StringUtils.isBlank(searchObj.getEndTime())){ Calendar calendar=Calendar.getInstance(); //calendar.add(Calendar.DAY_OF_YEAR,-1); searchObj.setEndTime(sdf.format(calendar.getTime())); } model.addAttribute("searchObj", searchObj); model.addAttribute("appChannel",appChannel); model.addAttribute("appVersion", appVersion); return PAGE_PREFIX+"/activeDegree"; }@RequestMapping("loadActiveDegree") @ResponseBody public Object loadActiveDegree(SearchObject searchObj){ initSearchObj(searchObj); Map> map=new HashMap>(); try { map=retentionAnalysisService.getActiveDegree(searchObj); } catch (ParseException e) { e.printStackTrace(); } return map; } @RequestMapping("loadActive15Degree") @ResponseBody public Object loadActive15Degree(SearchObject searchObj){ initSearchObj(searchObj); Map> map=new HashMap>(); try { map=retentionAnalysisService.getActive15Degree(searchObj); } catch (ParseException e) { e.printStackTrace(); } return map; } private void initSearchObj(SearchObject seachObj) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); //开始时间为空则取三个月前 if(StringUtils.isBlank(seachObj.getBeginTime())){ Calendar calendar=Calendar.getInstance(); calendar.add(Calendar.WEEK_OF_YEAR,-1); seachObj.setBeginTime(sdf.format(calendar.getTime())); } if(StringUtils.isBlank(seachObj.getEndTime())){ Calendar calendar=Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR,-1); seachObj.setEndTime(sdf.format(calendar.getTime())); }} }


Service
package com.ucar.appcount.service.impl; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.hadoop.hbase.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSON; import com.ucar.appcount.common.Common; import com.ucar.appcount.common.CommonUtils; import com.ucar.appcount.common.DateFormatUtil; import com.ucar.appcount.common.vo.RetentionFreshnessVo; import com.ucar.appcount.common.vo.SearchObject; import com.ucar.appcount.component.SearchComponent; import com.ucar.appcount.hbase.service.DevActive15DegreeTabServiceNew; import com.ucar.appcount.hbase.service.DevActiveDegreeTabServiceNew; import com.ucar.appcount.hbase.service.impl.BaseOperator; import com.ucar.appcount.service.DevUserServiceNew; import com.ucar.appcount.service.RetentionAnalysisDailyTabService; import com.ucar.appcount.service.RetentionAnalysisMonthTabService; import com.ucar.appcount.service.RetentionAnalysisService; import com.ucar.appcount.service.RetentionAnalysisWeekTabService; import com.ucar.appcount.service.RetentionFreshnessDailyTabService; import com.zuche.framework.nosql.hbase098.vo.Column; import com.zuche.framework.nosql.hbase098.vo.RowVo; import com.zuche.framework.utils.StringUtils; @Service public class RetentionAnalysisServiceImpl extends BaseOperator implements RetentionAnalysisService { private static final Logger logger = LoggerFactory.getLogger(RetentionAnalysisServiceImpl.class); @Autowired private SearchComponent searchComponent; @Autowired private RetentionAnalysisDailyTabService retentionAnalysisDailyTabService; @Autowired private RetentionAnalysisWeekTabService retentionAnalysisWeekTabService; @Autowired private RetentionAnalysisMonthTabService retentionAnalysisMonthTabService; @Autowired private RetentionFreshnessDailyTabService retentionFreshnessDailyTabService; @Autowired private DevActiveDegreeTabServiceNew activeDegreeTabService; @Autowired private DevActive15DegreeTabServiceNew active15DegreeTabService; @Autowired private DevUserServiceNew devUserServiceNew; @Override public List queryRowVoList(SearchObject searchObj,String filterList){ List rs = Collections.emptyList(); String timeType= searchObj.getTimeType(); if(Common.DATATYPE.DAY.equals(timeType)){ rs = this.retentionAnalysisDailyTabService.queryRetentionRows(searchObj, filterList); } if(Common.DATATYPE.WEEK.equals(timeType)){ rs = this.retentionAnalysisWeekTabService.queryRetentionRows(searchObj, filterList); } if(Common.DATATYPE.MONTH.equals(timeType)){ rs = this.retentionAnalysisMonthTabService.queryRetentionRows(searchObj, filterList); } return rs; } @Override public Map> retention(SearchObject searchObj) { Map> dataMap = new LinkedHashMap>(); try { String timeType= searchObj.getTimeType(); final boolean byDay = Common.DATATYPE.DAY.equals(timeType); final boolean byWeek = Common.DATATYPE.WEEK.equals(timeType); final boolean byMonth = Common.DATATYPE.MONTH.equals(timeType); /*****************************************************************/ /** * 如果是按月统计:对开始时间 和 结束时间 逻辑控制 * 开始时间如果非开始时间当月的第一天,需要重置为下个月的第一天。 * 结束时间如果非结束时间当月的第一条,需要重置为上个月的第一天。 */ /*****************************************************************/ RetentionHandler.resetSearchTimeForByMonth(byMonth,searchObj); if(byMonth){ Date start = DateFormatUtil.convertToDate(searchObj.getBeginTime(), DateFormatUtil.FORMAT_DATE_DISPLAY); Date end = DateFormatUtil.convertToDate(searchObj.getEndTime(), DateFormatUtil.FORMAT_DATE_DISPLAY); if(start.getTime()!=end.getTime()&&!end.after(start)){ return dataMap; } } //1、构建查询结果Map this.searchComponent.initDataMapForRetention(dataMap,searchObj); String filterList = this.searchComponent.initFilterList(searchObj); //2、获取新增用户Map Map userAddMap = this.devUserServiceNew.getNewUserNum(searchObj); //2.1、按时间装载新增用户数 Set> entrySet = dataMap.entrySet(); for(Entry> entry : entrySet){ String dataKey = entry.getKey(); if(userAddMap.containsKey(dataKey)){ Map columnMap = entry.getValue(); Double addUsers = Double.valueOf(userAddMap.get(dataKey).doubleValue()); columnMap.put(0, addUsers); } } /*****************************************************************/ /** * rowkey特殊规则说明:新增日期#APP类型#APP版本#下载渠道#统计日期 * 按天:(20161125#M_android#600340#360shoujizhushou#20161128) * 按周:(20161128#M_android#600340#360shoujizhushou#20161130) * 按月:(20161101#M_android#600340#360shoujizhushou#20161201) */ /*****************************************************************/ //3、获取留存用户 List rs = this.queryRowVoList(searchObj, filterList); for(RowVo row : rs){ String key = row.getRowKey(); //新增日期 String rowKey = row.getRowKey(); String tjrq = rowKey.substring(rowKey.lastIndexOf("#")+1); key = key.substring(0,key.indexOf("#",0)); key = CommonUtils.handlerTime(key, timeType); tjrq = CommonUtils.handlerTime(tjrq, timeType); //统计日期 if(byWeek){//按周统计,把日期都转换成这个星期的第一天 key = DateFormatUtil.getFirstDayOfWeek(key); key = key + "~" + DateFormatUtil.getLastDayOfWeek(key); } int days = 0; //天数 if(byDay||byWeek){ days=Long.valueOf(DateFormatUtil.getTwoDateDifference(key,tjrq)).intValue(); }else{ String s=key.concat("-01"); String e=tjrq.concat("-01"); days=Long.valueOf(DateFormatUtil.getTwoDateDifference(s,e)).intValue(); } List columns = row.getColumns(); Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count"))); if(dataMap.containsKey(key)){ Map columnMap = dataMap.get(key); int columnIndex = RetentionHandler.getColumnIndexForRetention(timeType, days); //获取时间类型(天/周/月)对列索引 Double retention = columnMap.get(columnIndex); logger.error("留存用户载入:retention={},columnMap={}",retention,columnMap); if(null!=columnMap && null!=retention){ columnMap.put(columnIndex, count+retention); } dataMap.put(key, columnMap); } } logger.error("留存用户加载数据:dataMap={}",JSON.toJSONString(dataMap)); } catch (Exception e) { logger.error("留存用户加载数据异常:dataMap={}",JSON.toJSONString(dataMap),e); } return dataMap; } @Override public Map freshness(SearchObject searchObj){ Map resultMap = new HashMap(); try { Map dataMap = new LinkedHashMap(); String timeType = searchObj.getTimeType(); Integer from = searchObj.getFrom(); Integer to = searchObj.getTo(); String filterList = this.searchComponent.initFilterList(searchObj); //2、获取用户新鲜度 List rs = this.retentionFreshnessDailyTabService.queryFreshnessRows(searchObj, filterList); for(RowVo row : rs){ String key = row.getRowKey(); //登录日期 String rowKey = row.getRowKey(); String xzrq = rowKey.substring(rowKey.lastIndexOf("#")+1); key = key.substring(0,key.indexOf("#",0)); key = CommonUtils.handlerTime(key, timeType); xzrq = CommonUtils.handlerTime(xzrq, timeType); //新增日期 List columns = row.getColumns(); Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count"))); if(dataMap.containsKey(key)){ RetentionFreshnessVo freshnessVo = dataMap.get(key); int orig = freshnessVo.getTotal(); freshnessVo.setTotal(orig + count); int duration = RetentionHandler.getColumnIndexForFreshness(key, xzrq,to); if(duration groupMap = freshnessVo.getGroupMap(); groupMap.put(duration, count + groupMap.get(duration)); dataMap.put(key, freshnessVo); }else{ RetentionFreshnessVo freshnessVo = new RetentionFreshnessVo(); Map groupMap = new LinkedHashMap(); for(int d=to; d>=from; d--){ groupMap.put(d, 0); } freshnessVo.setGroupMap(groupMap); dataMap.put(key, freshnessVo); } } logger.error("用户新鲜度加载数据:dataMap={}",JSON.toJSONString(dataMap)); resultMap.put("dataMap", dataMap); } catch (Exception e) { logger.error("用户新鲜度加载数据异常:dataMap={}",JSON.toJSONString(resultMap),e); } return resultMap; }/** * 获取用户活跃度数据 * * @param searchObj * @return */ @Override public Map> getActiveDegree(SearchObject searchObj) throws ParseException { Map> map=new LinkedHashMap>(); //20161113#M_android#600221#360shoujizhushou#2 String filterList = ".*"; if(!StringUtils.isEmpty(searchObj.getAppType())){ filterList += "#"+searchObj.getAppType(); }else{ filterList += "#.*"; } if(!StringUtils.isEmpty(searchObj.getAppVersion())){ filterList += "#"+searchObj.getAppVersion(); }else{ filterList += "#.*"; } if(!StringUtils.isEmpty(searchObj.getAppChannel())){ filterList += "#"+searchObj.getAppChannel()+".*"; }else{ filterList += "#.*"; }//20160828#M_android#600171#SGCM 01#1 searchObj.setTimeType(Common.DATATYPE.DAY); //结束时间默认加一天 SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd"); Calendar calendar = Calendar.getInstance(); calendar.setTime(dateFormat.parse(searchObj.getEndTime())); calendar.add(Calendar.DATE, 1); searchObj.setEndTime(dateFormat.format(calendar.getTime())); List activeList = activeDegreeTabService.getActiveDegree(searchObj, filterList); for(RowVo r : activeList){ String key = r.getRowKey(); Integer days=Integer.valueOf(key.substring(key.lastIndexOf("#") + 1)); key = key.substring(0, key.indexOf("#", 0)); key = CommonUtils.handlerTime(key, searchObj.getTimeType()); List columns = r.getColumns(); Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count"))); if(map.containsKey(key)){ if(map.get(key).containsKey(days)) { map.get(key).put(days, map.get(key).get(days)+count); }else{ map.get(key).put(days,count); } }else{ Map tempMap=new HashMap(); tempMap.put(days,count); map.put(key,tempMap); } }return map; }/** * 获取用户活跃度数据 * * @param searchObj * @return */ @Override public Map> getActive15Degree(SearchObject searchObj) throws ParseException { Map> map=new LinkedHashMap>(); //20161113#M_android#600221#360shoujizhushou#2 String filterList = ".*"; if(!StringUtils.isEmpty(searchObj.getAppType())){ filterList += "#"+searchObj.getAppType(); }else{ filterList += "#.*"; } if(!StringUtils.isEmpty(searchObj.getAppVersion())){ filterList += "#"+searchObj.getAppVersion(); }else{ filterList += "#.*"; } if(!StringUtils.isEmpty(searchObj.getAppChannel())){ filterList += "#"+searchObj.getAppChannel()+".*"; }else{ filterList += "#.*"; }//20160828#M_android#600171#SGCM 01#1 searchObj.setTimeType(Common.DATATYPE.DAY); //结束时间默认加一天 SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd"); Calendar calendar = Calendar.getInstance(); calendar.setTime(dateFormat.parse(searchObj.getEndTime())); calendar.add(Calendar.DATE,1); searchObj.setEndTime(dateFormat.format(calendar.getTime())); List activeList = active15DegreeTabService.getActiveDegree(searchObj, filterList); for(RowVo r : activeList){ String key = r.getRowKey(); key = key.substring(0, key.indexOf("#", 0)); key = CommonUtils.handlerTime(key, searchObj.getTimeType()); Integer days=Integer.valueOf(key.substring(key.lastIndexOf("#") + 1)); List columns = r.getColumns(); Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count"))); if(map.containsKey(key)){ if(map.get(key).containsKey(days)) { map.get(key).put(days, map.get(key).get(days)+count); }else{ map.get(key).put(days,count); } }else{ Map tempMap=new HashMap(); tempMap.put(days,count); map.put(key,tempMap); } }return map; }/** * 留存用户数据处理类 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-30 上午9:54:17 */ public static class RetentionHandler{ /** * 根据时间类型(日|周|月)获取对应列头对应的索引 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-11-29 下午3:48:35 * @param timeType 时间类型 * @param days 差异天数 * @return */ public static int getColumnIndexForRetention(String timeType,int days){ int columnIndex = 0; if(days==0){ return -1; } if(Common.DATATYPE.DAY.equals(timeType)){ if(days==0){ return -1; } if(days<7){ columnIndex = ReportTitle.DAILY[days-1]; }else if(days==14){ columnIndex = ReportTitle.DAILY[7]; }else if(days==30){ columnIndex = ReportTitle.DAILY[8]; } } if(Common.DATATYPE.WEEK.equals(timeType)){ int week = (days/7)-1; if(week<0){ return -1; } columnIndex = ReportTitle.WEEK[week]; } if(Common.DATATYPE.MONTH.equals(timeType)){ int month = (days/30)-1; if(month<0){ return -1; } columnIndex = ReportTitle.MONTH[month]; } return columnIndex; } /** * 用户新鲜度|获取登录日期与新增日期的差异天数 * @author 石冬冬-Heil Hilter(dd.shi02@zuche.com) * @date 2016-12-1 下午3:01:57 * @param dlrq 登录日期 * @param xzrq 新增日期 * @return */ public static int getColumnIndexForFreshness(String dlrq,String xzrq,Integer to){ int duration = 0; duration = Long.valueOf(DateFormatUtil.getTwoDateDifference(xzrq,dlrq)).intValue(); if(duration>=to){ return to; } return duration; } /*****************************************************************/ /** * 如果是按月统计:对开始时间 和 结束时间 逻辑控制 * 开始时间如果非开始时间当月的第一天,需要重置为下个月的第一天。 * 结束时间如果非结束时间当月的第一条,需要重置为上个月的第一天。 */ /*****************************************************************/ public static void resetSearchTimeForByMonth(boolean byMonth,SearchObject searchObj){ if(!byMonth){ return; } String beginTime = searchObj.getBeginTime(); String endTime = searchObj.getEndTime(); if(!StringUtils.isEmpty(beginTime)){ Calendar calendar = Calendar.getInstance(); calendar.setTime(DateFormatUtil.convertToDate(beginTime,DateFormatUtil.FORMAT_DATE_DISPLAY)); int today = calendar.get(Calendar.DAY_OF_MONTH); if(today!=1){ calendar.add(Calendar.MONTH, 1); calendar.set(Calendar.DAY_OF_MONTH, 1); String newTime = DateFormatUtil.convertDateToString(calendar.getTime(), DateFormatUtil.FORMAT_DATE_DISPLAY); searchObj.setBeginTime(newTime); } } if(!StringUtils.isEmpty(endTime)){ Calendar calendar = Calendar.getInstance(); calendar.setTime(DateFormatUtil.convertToDate(endTime,DateFormatUtil.FORMAT_DATE_DISPLAY)); int today = calendar.get(Calendar.DAY_OF_MONTH); boolean reset = false; //下面有些情况却要确认。。。。 if(today!=1){ calendar.add(Calendar.MONTH, -1); calendar.set(Calendar.DAY_OF_MONTH, 1); reset = true; }else{ int month = calendar.get(Calendar.MONTH); Calendar nowCalendar = Calendar.getInstance(); int currentMonth = nowCalendar.get(Calendar.MONTH); //非本月第一天时, if(month==currentMonth){ calendar.add(Calendar.MONTH, -1); reset = true; } } if(reset){ String newTime = DateFormatUtil.convertDateToString(calendar.getTime(), DateFormatUtil.FORMAT_DATE_DISPLAY); searchObj.setEndTime(newTime); } } }public static void main(String[] args) { //System.out.println(getColumnIndex(Common.DATATYPE.WEEK, 7)); System.out.println(RetentionAnalysisService.ReportTitle.MONTH_COLS); } } }





    推荐阅读