项目是是应用springmvc 框架
java,类,控制层
package com.school.web.controller.nini;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.school.business.StatisticsDurationCuManager;
import com.school.domain.StatisticsDurationCourse;
import com.school.util.PageRequest;
import com.school.util.Pageable;
import com.school.util.Paginator;
@Controller
@RequestMapping("/secure/course/statistics")
public class StatisticsDurationCuController extends AbstractSecureController {
@Autowired
private StatisticsDurationCuManager statisticsDurationCuManager;
/**
* 根据一门课程学员分组去统计时长。
*/
@RequestMapping("/{courseId}/duration")
public ModelAndView getStuOneCourseDur(@PathVariable String courseId, HttpServletRequest request) {
String schoolId = this.getSchoolId(request); // 网校ID
int page = ServletRequestUtils.getIntParameter(request, "page", 1); // 第几页
// 分页查询该课程的所有学员
Pageable pageable = new PageRequest(page, PAGE_SIZE);
Paginator<StatisticsDurationCourse> paginator = statisticsDurationCuManager.getDurationByCourse(schoolId,
courseId, pageable);
// 模版视图
ModelAndView mav = this.createCourseModelAndView(courseId, request);
mav.setViewName(getSecureViewDir(request) + "/courseStatistics/students");
String queryString = null;
mav.addObject("paginator", paginator);
mav.addObject("paginationHtml", paginator.toPaginationHtml(queryString));
return mav;
}
/**
* 根据一门课程学员分组去统计时长的详情。(分页)
*/
@RequestMapping("/{courseId}/duration/{userId}/detailed")
public ModelAndView getStuOneCourseDurDetail(@PathVariable String courseId, @PathVariable String userId,
HttpServletRequest request) {
String schoolId = this.getSchoolId(request); // 网校ID
String nickname = ServletRequestUtils.getStringParameter(request, "nickname", "");
String duration = ServletRequestUtils.getStringParameter(request, "duration", "");
String count = ServletRequestUtils.getStringParameter(request, "count", "");
int page = ServletRequestUtils.getIntParameter(request, "page", 1); // 第几页
// 分页查询
Pageable pageable = new PageRequest(page, PAGE_SIZE);
Paginator<StatisticsDurationCourse> paginator = statisticsDurationCuManager.getDurByCourseDetailPage(schoolId,
courseId, userId, pageable);
// 模版视图
ModelAndView mav = this.createCourseModelAndView(courseId, request);
mav.setViewName(getSecureViewDir(request) + "/courseStatistics/detailed");
String url = "/secure/course/statistics/" + courseId + "/duration/" + userId + "/detailed";
String queryString = null;
mav.addObject("paginator", paginator);
mav.addObject("paginationHtml", paginator.toPaginationHtml(url, queryString));
mav.addObject("nickname", nickname);
mav.addObject("courseId", courseId);
mav.addObject("userId", courseId);
mav.addObject("duration", duration);
mav.addObject("count", count);
return mav;
}
/**
* 根据一门课程学员分组去统计时长的详情。(不分页)
*/
@RequestMapping("/{courseId}/duration/{userId}/detailed/list")
public ModelAndView getStuOneCoDurDetailList(@PathVariable String courseId, @PathVariable String userId,
HttpServletRequest request) {
String schoolId = this.getSchoolId(request); // 网校ID
String nickname = ServletRequestUtils.getStringParameter(request, "nickname", "");
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurByCourseDetailed(schoolId,
courseId, userId);
// 模版视图
ModelAndView mav = this.createCourseModelAndView(courseId, request);
mav.setViewName(getSecureViewDir(request) + "/courseStatistics/detailed");
mav.addObject("durationList", durationList);
mav.addObject("nickname", nickname);
return mav;
}
/**
* 一门课程最近30天的时长统计
* @throws IOException
* @throws ParseException
*/
@RequestMapping("/{courseId}/duration/day")
public ModelAndView getCourseDurationDay(@PathVariable String courseId, HttpServletRequest request)
throws IOException, ParseException {
String schoolId = this.getSchoolId(request); // 网校ID
String type = ServletRequestUtils.getStringParameter(request, "type", "");
String startDate = ServletRequestUtils.getStringParameter(request, "startDate", "");
String endDate = ServletRequestUtils.getStringParameter(request, "endDate", "");
ModelAndView mav = this.createCourseModelAndView(courseId, request);
boolean selectmark = false;// 页面传过来的不合法的自定义的查询条件
if (StringUtils.isNotBlank(type)) {
if ("week".equals(type.trim())) {
// 按照时间的顺序,最近7天
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentTime = sdf.format(new Date());
String sevenDay = getPassDate(currentTime, 7);
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
schoolId, courseId, sevenDay, currentTime);
//补数据,没有记录的数据,一天没有产生数据,补一条0的数据
List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,7);
mav.addObject("durationList", durationListData);
// 报表所需要的折线图
List<String> dayList = new ArrayList<String>();
List<Integer> numberList = new ArrayList<Integer>();
List<Float> totalTimes = new ArrayList<Float>();
if (durationListData.size() > 0) {
for (int i = durationListData.size(); i >0; i--) {
StatisticsDurationCourse sdc = new StatisticsDurationCourse();
sdc = durationListData.get(i-1);
String dateString=sdf.format(sdc.getDate());
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(dateString));
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
String dayX = month + "月" + day + "日";
numberList.add(sdc.getNumber());
totalTimes.add(sdc.getTotalDuration()*60);
dayList.add(dayX);
}
}
// 转为json数组
String numberListStr = writeListToJsonArray(numberList);
String dayListStr = writeListToJsonArray(dayList);
String totalTimesStr = writeListToJsonArray(totalTimes);
mav.addObject("numberList", numberListStr);// 次数
mav.addObject("totalTimes", totalTimesStr);// 时长
mav.addObject("dayList", dayListStr);// 时间
mav.addObject("timeMark", "week");// 查询条件说明
} else if ("month".equals(type.trim())) {
// 最近30天
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentTime = sdf.format(new Date());
String thirtyDay = getPassDate(currentTime, 30);
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
schoolId, courseId, thirtyDay, currentTime);
//补数据,没有记录的数据,一天没有产生数据,补一条0的数据
List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,30);
mav.addObject("durationList", durationListData);
// 报表所需要的折线图
List<String> dayList = new ArrayList<String>();
List<Integer> numberList = new ArrayList<Integer>();
List<Float> totalTimes = new ArrayList<Float>();
if (durationListData.size() > 0) {
for (int i = durationListData.size(); i >0; i--) {
StatisticsDurationCourse sdc = new StatisticsDurationCourse();
sdc = durationListData.get(i-1);
Calendar cal = Calendar.getInstance();
cal.setTime(sdc.getDate());
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
String dayX = month + "月" + day + "日";
numberList.add(sdc.getNumber());
totalTimes.add(sdc.getTotalDuration() * 60);
dayList.add(dayX);
}
}
// 转为json数组
String numberListStr = writeListToJsonArray(numberList);
String dayListStr = writeListToJsonArray(dayList);
String totalTimesStr = writeListToJsonArray(totalTimes);
mav.addObject("numberList", numberListStr);// 次数
mav.addObject("totalTimes", totalTimesStr);// 时长
mav.addObject("dayList", dayListStr);// 时间
mav.addObject("timeMark", "month");// 查询条件说明
} else if ("time".equals(type.trim())) {
// 自由选择时间
// 时间段小于30天
// 结束时间超过当前时间
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse(startDate);
Date d2 = sdf.parse(endDate);
Date now = new Date();
long daysNows = (d2.getTime() - now.getTime() + 1000000) / (3600 * 24 * 1000);
if (daysNows > 0) {
// 结束时间超过当前时间,吧当前时间的值给结束时间
endDate = sdf.format(now);
}
long daysBetween = (d2.getTime() - d1.getTime() + 1000000) / (3600 * 24 * 1000);
//System.out.println("1987-01-01 与 2010-01-01 相隔 "+daysBetween+" 天");
// 两个自定义时间之间必须小于31天
if ((daysBetween + 1) <= 31 && (daysBetween + 1) >= 1) {
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
schoolId, courseId, startDate, endDate);
//补数据,没有记录的数据,一天没有产生数据,补一条0的数据
int intervalDay=(int) daysBetween+1;
List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,intervalDay);
mav.addObject("durationList", durationListData);
// 报表所需要的折线图
List<String> dayList = new ArrayList<String>();
List<Integer> numberList = new ArrayList<Integer>();
List<Float> totalTimes = new ArrayList<Float>();
if (durationListData.size() > 0) {
for (int i = durationListData.size(); i >0; i--) {
StatisticsDurationCourse sdc = new StatisticsDurationCourse();
sdc = durationListData.get(i-1);
Calendar cal = Calendar.getInstance();
cal.setTime(sdc.getDate());
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
String dayX = month + "月" + day + "日";
numberList.add(sdc.getNumber());
totalTimes.add(sdc.getTotalDuration()*60);
dayList.add(dayX);
}
}
// 转为json数组
String numberListStr = writeListToJsonArray(numberList);
String dayListStr = writeListToJsonArray(dayList);
String totalTimesStr = writeListToJsonArray(totalTimes);
mav.addObject("numberList", numberListStr);// 次数
mav.addObject("totalTimes", totalTimesStr);// 时长
mav.addObject("dayList", dayListStr);// 时间
mav.addObject("timeMark", "time");// 查询条件说明
mav.addObject("startDate", startDate);// 开始时间
mav.addObject("endDate", endDate);// 结束时间
} else {
//超过31天,按照7天来搜索
selectmark=true;
}
}else {
//查询时间条件为空
selectmark = true;
}
}//if time
}//type是否为空
if(selectmark){
// 两个时间之间超过31天 ,按照7天来统计
// 按照时间的顺序,最近7天
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentTime = sdf.format(new Date());
String sevenDay = getPassDate(currentTime, 7);
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationByTime(
schoolId, courseId, sevenDay, currentTime);
//补数据,没有记录的数据,一天没有产生数据,补一条0的数据
List<StatisticsDurationCourse> durationListData = addNullDayData(durationList,7);
mav.addObject("durationList", durationListData);
// 报表所需要的折线图
List<String> dayList = new ArrayList<String>();
List<Integer> numberList = new ArrayList<Integer>();
List<Float> totalTimes = new ArrayList<Float>();
if (durationListData.size() > 0) {
for (int i = durationListData.size(); i >0; i--) {
StatisticsDurationCourse sdc = new StatisticsDurationCourse();
sdc = durationListData.get(i-1);
String dateString=sdf.format(sdc.getDate());
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(dateString));
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
String dayX = month + "月" + day + "日";
numberList.add(sdc.getNumber());
totalTimes.add(sdc.getTotalDuration()*60);
dayList.add(dayX);
}
}
// 转为json数组
String numberListStr = writeListToJsonArray(numberList);
String dayListStr = writeListToJsonArray(dayList);
String totalTimesStr = writeListToJsonArray(totalTimes);
mav.addObject("numberList", numberListStr);// 次数
mav.addObject("totalTimes", totalTimesStr);// 时长
mav.addObject("dayList", dayListStr);// 时间
mav.addObject("timeMark", "week");// 查询条件说明
}
mav.setViewName(getSecureViewDir(request) + "/courseStatistics/count");
return mav;
}
/**
* 一门课程一个月的每一天的时长统计
*/
@RequestMapping("/{courseId}/duration/month")
public ModelAndView getCourseDurationMonth(@PathVariable String courseId, HttpServletRequest request) {
String schoolId = this.getSchoolId(request); // 网校ID
String time = ServletRequestUtils.getStringParameter(request, "time", "");//
ModelAndView mav = this.createCourseModelAndView(courseId, request);
if (StringUtils.isBlank(time)) {
// 统计当前月份的
Calendar cal = Calendar.getInstance();
int month = cal.get(Calendar.MONTH) + 1;
int year = cal.get(Calendar.YEAR);
// int day = cal.get(Calendar.DAY_OF_MONTH);
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationMonth(schoolId,
courseId, year, month);
mav.addObject("durationList", durationList);
} else {
// 统计上一个月的
Calendar cal = Calendar.getInstance();
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
// int day = cal.get(Calendar.DAY_OF_MONTH);
List<StatisticsDurationCourse> durationList = statisticsDurationCuManager.getDurationMonth(schoolId,
courseId, year, month);
mav.addObject("durationList", durationList);
}
mav.setViewName(getSecureViewDir(request) + "/courseStatistics/durationByDay");
return mav;
}
// list转为json数组
public String writeListToJsonArray(List list) throws IOException {
OutputStream out = new ByteArrayOutputStream();
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, list);
byte[] data = ((ByteArrayOutputStream) out).toByteArray();
// System.out.println(new String(data));
String result = new String(data, "UTF-8");
return result;
}
/**
* 根据输入的日期字符串 和 提前天数 ,
* 获得 指定日期提前几天的日期对象
* @param dateString 日期对象 ,格式如 1-31-1900
* @param lazyDays 倒推的天数
* @return 指定日期倒推指定天数后的日期对象
* @throws ParseException
*/
public String getPassDate(String dateString, int beforeDays) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date inputDate = dateFormat.parse(dateString);
Calendar cal = Calendar.getInstance();
cal.setTime(inputDate);
int inputDayOfYear = cal.get(Calendar.DAY_OF_YEAR);
cal.set(Calendar.DAY_OF_YEAR, inputDayOfYear - beforeDays);
String dateTime = dateFormat.format(cal.getTime());
return dateTime;
}
//补数据,没有记录的数据,一天没有产生数据,补一条0的数据
public List<StatisticsDurationCourse> addNullDayData(List<StatisticsDurationCourse> durationList,int len) throws ParseException {
List<StatisticsDurationCourse> durationListSort = new ArrayList<StatisticsDurationCourse>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if(durationList.size()>0){
for(int j=0;j<len;j++){
//找出空的时间,补数据
String currentTime2 = sdf.format(new Date());
String recentlyDay = getPassDate(currentTime2, j);//最近7天的时间
boolean addmark=true;
for (int i = 0; i < durationList.size(); i++) {
StatisticsDurationCourse sdc = new StatisticsDurationCourse();
sdc = durationList.get(i);
String dateString=sdf.format(sdc.getDate());
if(recentlyDay.equals(dateString)){
//记录里有最近7天其中一天的数据
durationListSort.add(sdc);
addmark=false;
break;
}
}
if(addmark){
//记录里没有最近7天中任何一天的数据
StatisticsDurationCourse sdcNo = new StatisticsDurationCourse();
sdcNo.setDate(sdf.parse(recentlyDay));
sdcNo.setNumber(0);
sdcNo.setTotalDuration(0);
durationListSort.add(sdcNo);
}
}
}
return durationListSort;
}
}
页面是使用freemarker
<#-- 页头 -->
<#assign pageTitle="课程统计">
<#include "/default/commons/header.ftl">
<style>
.searchDate{
margin:10px auto -10px;
}
.inputLabel{
line-height:30px;
}
.form-radio{
margin-top:-2px;
}
.name-font{
font-size:18px;
text-indent:2em;
margin-top:20px;
}
.terminal{
margin-top:10px;
}
#draw{
width:95%;
height:400px;
margin:0 auto;
}
.table-th{
background-color: #4B4B4B;
color:#e2e2e2;
}
.warnning{
padding:5px 15px;
}
</style>
<div id="content-container" class="container">
<#-- 课程管理相关页面的顶部模版 -->
<#include "../course/manage/topSection.ftl">
<div class="row">
<div class="col-md-3">
<#-- 左侧导航 -->
<#assign sidebarNav="duration">
<#include "../course/manage/sidebar.ftl">
</div>
<div class="col-md-9">
<div class="panel panel-default panel-col">
<!--右侧内容-->
<div class="well well-sm" style="width:90%; margin-top:20px;margin-left:auto;margin-right:auto;text-align:center;">
<form id="statistics-search" class="form-inline" action="/secure/course/statistics/${course.courseId}/duration/day" method="get">
<div class="form-group">
<input class="form-control" type="text" id="startDate" name="startDate" value="" placeholder="起始时间">
</div>
<span>--</span>
<div class="form-group">
<input class="form-control" type="text" id="endDate" name="endDate" value="" placeholder="结束时间">
</div>
<span>--</span>
<div class="form-group">
<select class="form-control" name="type" id="markType">
<option value="week">最近7天</option>
<option value="month">最近30天</option>
<option value="time">自定义时间</option>
</select>
</div>
<button class="btn btn-primary">统计</button>
</form>
</div>
<!--统计日期选择-->
<div class="name-font">
« <span id="courseName">${(course.title)!''}</span>» 统计
<span id="markText" style="float:right;margin-right:40px;"></span>
</div>
<div id="draw">
</div>
<!--折线图-->
<div class="table-view" style="width:90%;margin:auto;">
<table class="table table-hover" id="tongji" style="text-align:center;">
<thead class="table-th">
<th style="text-align:center;">日期</th>
<th style="text-align:center;">观看次数(次)</th>
<th style="text-align:center;">观看时长(分钟)</th>
</thead>
<tbody>
<#if durationList?has_content>
<#list durationList as item>
<tr>
<td>${(item.date)?string("yyyy-MM-dd")}</td>
<td>${(item.number)!''}</td>
<td>${((item.totalDuration)*60)?string("0.##")}</td>
</tr>
</#list>
<#else>
<span> 暂时还没数据! </span>
</#if>
</tbody>
</table>
</div>
<!--数据列表-->
<input type="hidden" id="timeMark" value="${(timeMark)!''}" />
</div>
</div>
</div>
<#--页脚开始 -->
<#include "/default/commons/footerBegin.ftl">
<script type="text/javascript" src="/resources/echart/esl.js"></script>
<script type="text/javascript" src="/resources/datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript">
// 路径配置
require.config({
paths:{
'echarts' : '/resources/echart/echarts',
'echarts/chart/bar' : '/resources/echart/echarts'
}
});
// 使用
require(
[
'echarts',
'echarts/chart/bar' // 使用柱状图就加载bar模块,按需加载
],
function (ec) {
// 基于准备好的dom,初始化echarts图表
var myChart = ec.init(document.getElementById('draw'));
var jsonNum=${numberList};
var jsonTime=${totalTimes};
var jsonDay=${dayList};
option = {
tooltip : {
trigger: 'axis'
},
legend: {
data:['观看次数','观看时长']
},
toolbox: {
show : true,
feature : {
magicType : {show: false, type: ['line']}
}
},
calculable : true,
xAxis : [
{
type : 'category',
boundaryGap : true,
name: '月份',
data : jsonDay
}
],
yAxis : [
{
type : 'value',
name: '分钟/次数'
}
],
series : [
{
name:'观看次数',
type:'line',
stack: '次',
data:jsonNum
},
{
name:'观看时长',
type:'line',
stack: '分钟',
data:jsonTime
}
]
};
// 为echarts对象加载数据
myChart.setOption(option);
}
);
</script>
<script>
$(document).ready(function(){
var timeMark="${timeMark}";
$("#markType").val(timeMark);
if("time"==timeMark){
var startDate="${startDate}";
var endDate="${endDate}";
var textStr=startDate+"----"+endDate+"的观看情况";
$("#markText").text(textStr);
}
});
$("#startDate").datetimepicker({
weekStart: 1,
todayBtn: 1,
autoclose: 1,
todayHighlight: 1,
startView: 2,
minView: 2,
forceParse: 0,
format:"yyyy-mm-dd"
});
$("#endDate").datetimepicker({
weekStart: 1,
todayBtn: 1,
autoclose: 1,
todayHighlight: 1,
startView: 2,
minView: 2,
forceParse: 0,
format:"yyyy-mm-dd"
});
</script>
<#--页脚页脚页脚-->
<#include "/default/commons/footerEnd.ftl">
运行效果图: