首先给大家推荐echarts官网:里面什么柱状图,折线图,饼状图都有。
https://echarts.apache.org/examples/zh/index.html 可以去下载对应的echarts样式。
1.效果图如下:
我这边是根据开始时间,结束时间,用户选择三个下拉来查询饼状图的数据的。2.引入前端样式:(前端主要是bootstrap的样式。可以去官网下载哈)
3.前端代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Dashboard</title>
<link rel="stylesheet" href="../static/assets/css/bootstrap.min.css">
<script src="../static/jquery/jquery-3.2.1.min.js"></script>
<script src="../static/bootstrap/js/bootstrap.js"></script>
<script src="../static/js/echarts.min.js"></script>
</head>
<body>
<div style="margin-left:10px;">
<div class="form-group" style="width:280px;margin-top:40px; position:absolute; ">
<label class="control-label mb-1">开始时间</label>
<input id="startDateTime" name="startDateTime" type="date" class="form-control" value="" onchange="checkDate(this)">
</div>
<div class="form-group" style="width:280px;margin-top:40px;margin-left:350px; position:absolute;">
<label class="control-label mb-1">结束时间</label>
<input id="endDateTime" name="endDateTime" type="date" class="form-control" value="" onchange="checkDate(this)">
</div>
<div class="form-group" style="width:280px;margin-top:40px;margin-left:700px; position:absolute;">
<label class="control-label mb-1">用户选择</label>
<select id="userNameId" name="type" class="form-control"></select>
</div>
<div class="form-group" style="width:280px;margin-top:63px; margin-left:1050px;position:absolute;">
<button type="submit" class="btn btn-primary" onclick="refresh()" style="width:80px;">查询</button>
</div>
</div>
<div id="main_pie" style="height:600px; width: 850px;margin-top:250px;margin-left:200px;position:absolute;"></div>
<script>
$(function() {
//一进入页面就加载用户选择的下拉框的数据
onUserNameList();
});
//用来检验开始时间不能大于结束时间
function checkDate(date){
var startDate = $("#startDateTime").val();
var endDate = $("#endDateTime").val();
if(startDate.length>0 && endDate.length>0){
var startDateTemp = startDate.split("-");
var endDateTemp = endDate.split("-");
var allStartDate = new Date(startDateTemp[0], startDateTemp[1], startDateTemp[2]);
var allEndDate = new Date(endDateTemp[0], endDateTemp[1], endDateTemp[2]);
if(allStartDate.getTime()>allEndDate.getTime()){
alert("开始时间不能大于结束时间,请重新选择");
date.value='';
return false;
}else {
return true;
}
}
}
//获取下拉框得数据
function onUserNameList(){
$.ajax({
url : "/dashboard/getUserList",
dataType : 'json',
type : 'GET',
success : function(dataInfo) {
var dataOptions = '<option value="">请选择或搜索查询</option>';
$('#userNameId').html(dataOptions);
if(dataInfo.length>0){
for(var i = 0; i < dataInfo.length; i++){
dataOptions +="<option value='"+dataInfo[i].id+"'>"+dataInfo[i].userName+ "</option>";
//用户id:dataInfo[i].id
//用户名称:dataInfo[i].userName
//id和userName必须要和后台接口传过来的名称保持一致。否则前端打印就是undefined的
$('#userNameId').html(dataOptions);//拼接到JSP页面
}
}else{
alert("数据为空");
}
}
});
}
//查询按钮事件
function refresh(){
//获取下拉框选中的用户id
var userId = $('#userNameId').children('option:selected').val();
var jsonData = {};
jsonData.startTime = $("#startDateTime").val();
jsonData.endTime = $("#endDateTime").val();
jsonData.userId = userId;
//调用展示饼状图的方法
echartsPieFuncOne(jsonData);
}
var echartsPieFuncOne = function(jsonData){
$.ajax({
url : "/dashboard/getBar",
dataType : 'json',
type : 'GET',
//async : false,
data: jsonData,//代表传给后端的三个值。startTime,endTime,userId
success : function(data) {
var json = data;
var jsonPieNameX = json.jsonPieRuleNameX;
var jsonPieY = json.jsonPieCountY;
var pieAllCount = json.pieAllCount;
//饼状图的图例名称:jsonPieRuleNameX
//饼状图的data数据:jsonPieCountY
//饼状图错误的总和:pieAllCount
//jsonPieRuleNameX,jsonPieCountY,pieAllCount必须要和后端传过来的map的key是一样。否则前端出现undefined
echartsCommonPie(jsonPieNameX, jsonPieY, pieAllCount);
}
});
}
//饼状图
function echartsCommonPie(jsonPieNameX, jsonPieY,pieAllCount){
var jsonPieX = jsonPieNameX;
var jsonPieY = jsonPieY;
var pieAllCount = pieAllCount;
var myChart = echarts.init(document.getElementById('main_pie'));
//myChart.clear();//清空画布,可以加,也可以不加。
var option = {
title : {
//subtext: '错误总个数:'+pieAllCount,
text: '错误分布数量图(错误总个数:'+pieAllCount+')',
x:'center',
y:'bottom',
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient: 'vertical',
x:'right',
y:'top',
itemWidth: 23, // 设置图例图形的宽
itemHeight: 10, // 设置图例图形的高
data:jsonPieX
},
toolbox: {
show : true,
feature : {
magicType : {
type: ['pie', 'funnel'],
option: {
funnel: {
x: '25%',
width: '50%',
funnelAlign: 'left',
max: 1548
}
}
},
}
},
calculable : true,
series: [
{
name: '错误分布数量',
type: 'pie',
radius: '55%',
//radius: ["40%", "60%"],
center: ['25%', '60%'],
data:jsonPieY,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
label: { //去掉指示线
normal: {
show: false,
position: 'inside',
formatter:"{b}:{d}%"
}
},
}
],
};
// 为echarts对象加载数据
myChart.setOption(option);
}
</script>
</body>
</html>
4.后端代码:
A.controller层代码
@RequestMapping(value = "/getUserList")
@ResponseBody
public List<UserVo> getUserList() {
return dashBoardService.getUserList();
}
@RequestMapping(value = "/getBar")
@ResponseBody
public Map<String, Object> getBar(@RequestParam(value = "userId", required = false) int userId,
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime) {
Map<String, Object> jsonMap = new HashMap<>();
if(startTime!=null && startTime!="") {
startTime = startTime.replaceAll("-", "/");
}
if(endTime!=null && endTime!="") {
endTime = endTime.replaceAll("-", "/");
}
//根据userId查询所有的用户
UserVo vo = userService.getUserInfoById(userId);
//饼状图
List<String> listPieRuleNameX = new ArrayList<>();
List<Map<String, Object>> listPieCountY = new ArrayList<>();
Map<String, Integer> mapPieName = dashBoardService.getEchartsPieCount(vo.getUserName(), startTime, endTime);
int pieAllCount = 0;
for (String pieName : mapPieName.keySet()) {
Map<String, Object> mps=new HashMap<String, Object>();
mps.put("value", mapPieName.get(pieName));
mps.put("name", pieName);
listPieRuleNameX.add(pieName);
listPieCountY.add(mps);
//错误总个数
int temp = mapPieName.get(pieName);
pieAllCount+=temp;
}
jsonMap.put("jsonPieRuleNameX", listPieRuleNameX);
jsonMap.put("jsonPieCountY", listPieCountY);
jsonMap.put("pieAllCount", pieAllCount);
return jsonMap;
}
B.service层代码
public List<UserVo> getUserList() {
return userDao.getUserList();
}
public Map<String, Integer> getEchartsPieCount(String userName, String startTime, String endTime){
Map<String, Integer> allPCBNameMap = getAllPCBNameMap();
List<String> dashBoardList = dashBoardDao.getEachCountByTime(userName, startTime, endTime);
for (String d : dashBoardList) {
//String arrCount = d.getErrorEachCount();
String[] arr = d.split(";");
Map<String, Integer> newMap = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
String[] ruleArr = arr[i].split(":");
newMap.put(ruleArr[0], Integer.parseInt(ruleArr[1]));
}
newMap.forEach((key,value) -> allPCBNameMap.merge(key,value,Integer::sum));//合并两个map,key相同value相加
}
return allPCBNameMap;
}
C.dao层代码
//代表表名
private String projectsTable = "projects";
private String userTable = "sys_user";
//得到所有用户信息
public List<UserVo> getUserList() {
ArrayList<UserVo> list = new ArrayList<>();
StringBuffer sf = new StringBuffer();
sf.append("SELECT id,user_name FROM " + userTable );
SqlRowSet rs = jt.queryForRowSet(sf.toString(), new Object[] { }, new int[] { });
while (rs.next()){
UserVo userVo = new UserVo();
userVo.setId(rs.getInt("id"));
userVo.setUserName(rs.getString("user_name"));
list.add(userVo);
}
return list;
}
public List<String> getEachCountByTime(String userName, String startTime, String endTime) {
List<String> voList = new ArrayList<>();
StringBuffer sf = new StringBuffer();
sf.append("SELECT error_each_count FROM " + projectsTable);
sf.append(" WHERE 1 = 1 ");
sf.append(" AND user_name = ?");
sf.append(" AND date_time >= '"+startTime+"'");
sf.append(" AND date_time <= '"+endTime+"'");
SqlRowSet rs = jt.queryForRowSet(sf.toString(), new Object[] { userName }, new int[] { Types.VARCHAR } );
while (rs.next()){
String errorEachCount = rs.getString("error_each_count");
voList.add(errorEachCount);
}
return voList;
}
注意:后端接口 /dashboard/getBar 返回的数据格式:
1. jsonMap的数据格式才是传值到前端,展示饼状图的数据.
2. 代表饼状图的图例名称:jsonPieRuleNameX,也就是jsonMap的key
3. 代表饼状图的data数据:jsonPieCountY,也就是jsonMap的key
jsonPieRuleNameX和jsonPieCountY传过去的格式必须要统一否则饼状图数据加载不出来。
因为我用的框架是springboot,可以根据自己的框架自己更改后端的方法。
5.数据库表结构:
总结:以上就是我的思路。纯属个人见解,记录一下以防万一。如果您有更好的解决方式,欢迎留言指教。