前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java快一年时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。

首先给各位粉丝朋友们道个歉,在2022年上半年中,我因为参加实习、做毕设和写论文,以及毕业答辩等诸多原因,不得不停更之前的博客系列,不过现在我忙完后就又回来了,后续将会给大家分享更多的编程干货。

最近这段时间我会将在毕设项目的编写过程中所遇到的问题以及解决问题的方法进行总结,整理成这个 SpringBoot+LayUI前后端分离项目实战系列

特别提醒:如果对 SpringBoot+LayUI前后端分离项目实战系列感兴趣的,可以阅读本系列往期博客:
上一篇:SpringBoot+LayUI模板引擎+MybatisPlus 前后端分离 实现系统公告通知

今天分享的问题是:如何使用SpringBoot框架LayUI框架MybatisPlus框架Echarts图表来实现数据统计功能,具体解决方案如下,请各位小伙伴们耐心观看:

1.SpringBoot后端主要实现代码

1.1 主要的VO视图对象

主要包括BarVO(柱状图的视图对象)、PieVO(饼状图的视图对象)、UserCountVo(角色数量视图对象)、GenderCountVo(性别数量视图对象)和 AgeCountVo(年龄数量视图对象)

1.1.1 柱状图视图对象BarVo的实现代码

package com.rz.sport_manager.entity.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.List;/*** @ClassName BarVO* @Description 柱状图的视图对象* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
// 由横向数据变成一个纵向数据, 即名称和数量分开
public class BarVO implements Serializable {/*** 存储柱状图名称的List集合*/private List<String> names;/*** 存储柱状图数量的List集合*/private List<Integer> values;}

1.1.2 饼状图视图对象PieVO的实现代码

package com.rz.sport_manager.entity.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @ClassName BarVO* @Description 柱状图的视图对象* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
public class PieVO {/*** 饼状图的数量*/private Integer value;/*** 饼状图的名称*/private String name;}

1.1.3 角色数量视图对象UserCountVo的实现代码

package com.rz.sport_manager.entity.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @ClassName UserCountVo* @Description 各角色用户数量视图对象* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
public class UserCountVo implements Serializable {/*** 角色名称*/private String roleName;/*** 用户数量*/private Integer userCount;}

1.1.4 性别数量视图对象GenderCountVo的实现代码

package com.rz.sport_manager.entity.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @ClassName GenderCountVo* @Description 性别数量视图对象* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
public class GenderCountVo implements Serializable {/*** 性别*/private String genderName;/*** 用户数量*/private Integer userCount;}

1.1.5 年龄数量视图对象AgeCountVo的实现代码

package com.rz.sport_manager.entity.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @ClassName AgeCountVo* @Description 各年龄段用户数量视图对象* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
public class AgeCountVo implements Serializable {/*** 年龄段*/private String ageLevel;/*** 用户数量*/private Integer userCount;}

1.2 UserInfoMapper接口实现代码和UserInfoMapper.xml映射文件

1.2.1 UserInfoMapper接口实现代码

package com.rz.sport_manager.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.rz.sport_manager.entity.vo.AgeCountVo;
import com.rz.sport_manager.entity.vo.GenderCountVo;
import com.rz.sport_manager.entity.vo.UserCountVo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;import java.util.List;/*** @ClassName UserInfoMapper* @Description 用户信息表 Mapper 接口* @Author 狂奔の蜗牛rz* @Date 2022/04/25*/
// 使用@Repository注解, 将其注册为Dao层, 交由Spring容器统一管理
@Repository
// 使用@Mapper注解, 将该接口注册为Mapper接口
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {/*** 获取各角色的用户数量的数据集合* @return List<UserCountVo> 泛型为AUserCountVo的List集合*/public List<UserCountVo> getRoleUserCountList();/*** 获取各性别的用户数量的数据集合* @return List<GenderCountVo> 泛型为GenderCountVo的List集合*/public List<GenderCountVo> getUserGenderCountList();/*** 获取各年龄段的用户数量的数据集合* @return List<AgeCountVo> 泛型为AgeCountVo的List集合*/public List<AgeCountVo> getUserAgeCountList();}

1.2.2 UserInfoMapper.xml映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rz.sport_manager.mapper.UserInfoMapper"><!-- 获取各角色的用户数量的数据集合 --><select id="getRoleUserCountList" resultMap="userCountMap">select ri.role_name as role_name,count(ui.user_id) as user_count from sport_manager01.user_info uileft join sport_manager01.role_info ri on ri.role_id = ui.role_idwhere ui.deleted = 0 and ri.status = 1 and ri.deleted = 0 group by ui.role_id</select><!-- 获取各性别的用户数量的数据集合 --><select id="getUserGenderCountList" resultMap="genderCountMap">select (case ui.gender when 0 then '女' when 1 then '男' else 'null' end) as gender_name,count(ui.user_id) as user_count from sport_manager01.user_info uiwhere ui.deleted = 0 group by ui.gender</select><!-- 获取各年龄段的用户数量的数据集合(注意: 使用"字段值 < 指定值"时,"<"会被当做"标签左括号", 从而报出"Tag name expected"),只需改变括号方向, 即"指定值 > 字段值"--><select id="getUserAgeCountList" resultMap="ageCountMap">select (case when cast(substring(birthday,1,4) as signed) >= 1960 and 1970 > cast(substring(birthday,1,4) as signed) then '60后'when cast(substring(birthday,1,4) as signed) >= 1970 and 1980 > cast(substring(birthday,1,4) as signed) then '70后'when cast(substring(birthday,1,4) as signed) >= 1980 and 1990 > cast(substring(birthday,1,4) as signed) then '80后'when cast(substring(birthday,1,4) as signed) >= 1990 and 2000 > cast(substring(birthday,1,4) as signed) then '90后'when cast(substring(birthday,1,4) as signed) >= 2000 then '00后'else '未知' end) as age_level, count(user_id) as user_count from sport_manager01.user_infowhere deleted = 0 group by age_level</select><!-- 各角色用户数量的结果集映射 --><resultMap id="userCountMap" type="com.rz.sport_manager.entity.vo.UserCountVo"><!-- 使用result设置相关属性,只需显式定义不一致的字段和属性property:Java实体类中的对应属性;column:对应数据库中的字段名如果一个数据库字段使用别名,其他字段也要使用别名 --><result property="roleName" column="role_name"/><result property="userCount" column="user_count"/></resultMap><!-- 各性别用户数量的结果集映射 --><resultMap id="genderCountMap" type="com.rz.sport_manager.entity.vo.GenderCountVo"><!-- 使用result设置相关属性,只需显式定义不一致的字段和属性property:Java实体类中的对应属性;column:对应数据库中的字段名如果一个数据库字段使用别名,其他字段也要使用别名 --><result property="genderName" column="gender_name"/><result property="userCount" column="user_count"/></resultMap><!-- 各年龄段用户数量的结果集映射 --><resultMap id="ageCountMap" type="com.rz.sport_manager.entity.vo.AgeCountVo"><!-- 使用result设置相关属性,只需显式定义不一致的字段和属性property:Java实体类中的对应属性;column:对应数据库中的字段名如果一个数据库字段使用别名,其他字段也要使用别名 --><result property="ageLevel" column="age_level"/><result property="userCount" column="user_count"/></resultMap></mapper>

1.3 UserInfoService服务层接口和其实现类的主要实现代码

1.3.1UserInfoService服务层接口实现代码

package com.rz.sport_manager.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.rz.sport_manager.entity.vo.BarVO;
import com.rz.sport_manager.entity.vo.PieVO;import java.util.List;/*** @ClassName UserInfoService* @Description 用户信息表 Service层接口* @Author 狂奔de蜗牛rz* @Date 2022/04/25*/
public interface UserInfoService extends IService<UserInfo> {/*** 获取各角色的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/public BarVO getRoleUserCountBarList();/*** 获取各性别的用户数量的饼状图数据集合* @return List<PieVO> 泛型为PieVO的List集合*/public List<PieVO> getUserGenderCountPieList();/*** 获取各年龄阶段的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/public BarVO getUserAgeCountBarList();}

1.3.2 UserInfoServiceImpl服务层接口实现类的实现代码

package com.rz.sport_manager.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rz.sport_manager.entity.vo.*;
import com.rz.sport_manager.mapper.UserInfoMapper;
import com.rz.sport_manager.service.UserInfoService;
import com.rz.sport_manager.utils.JsonResult;import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;/*** @ClassName UserInfoServiceImpl* @Description 用户信息表 Service层接口实现类* @Author 狂奔de蜗牛rz* @Date 2022/04/25*/// 使用@Service注解, 将该类注册为Service层, 交由Spring的IOC容器统一管理
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {// 通过类型自动装配UserInfoMapper接口@Autowiredprivate UserInfoMapper userInfoMapper;/*** 获取各角色的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/@Overridepublic BarVO getRoleUserCountBarList() {/* 1.首先纵向封装: 将角色名称和用户数量(一条条单行数据)存入userCountVoList集合中 */List<UserCountVo> userCountVoList = userInfoMapper.getRoleUserCountList();/* 2.然后横向封装: 将每个角色的名称和用户数量存入到两个单独的List集合中去 */// 创建一个List集合roleNames, 用于存储各角色名称List<String> roleNames = new ArrayList<>();// 创建一个List集合userCounts, 用于存储用户数量List<Integer> userCounts = new ArrayList<>();// 使用foreach遍历userCountVoList集合(存储角色名称和用户数量的List集合)for (UserCountVo userCountVo : userCountVoList) {// 将遍历出的角色名称和用户数量存入到其相对应的List集合中去roleNames.add(userCountVo.getRoleName());userCounts.add(userCountVo.getUserCount());}/* 3.将存储角色名称和用户数量的List集合分别封装到BarVO对象中 */// 创建BarVO(柱状图视图对象)BarVO barVO = new BarVO();// 设置柱状图的名称(对应存储角色名称的List集合)barVO.setNames(roleNames);// 设置柱状图的数量(对应存储用户数量的List集合)barVO.setValues(userCounts);// 将barVO(视图对象)进行返回return barVO;}/*** 获取各性别的用户数量的饼状图数据集合* @return List<PieVO> 泛型为PieVO的List集合*/@Overridepublic List<PieVO> getUserGenderCountPieList() {// 获取genderCountVoList集合(用于存储各性别用户数量的List集合)List<GenderCountVo> genderCountVoList = userInfoMapper.getUserGenderCountList();// 获取pieVOList集合(用于存储PieVO(饼状图视图对象)的List集合)List<PieVO> pieVOList = new ArrayList<PieVO>();// 使用foreach遍历genderCountVoList(存储性别名称和用户数量的List集合)for (GenderCountVo genderCountVo : genderCountVoList) {// 创建PieVO(饼状图视图对象)PieVO pieVO = new PieVO();// 设置饼状图的名称(对应用户数量)pieVO.setValue(genderCountVo.getUserCount());// 设置饼状图的数量(对应性别名称)pieVO.setName(genderCountVo.getGenderName());// 将pieVO(饼状图视图对象)添加到pieVOList(用于存储PieVO(饼状图视图对象)的List集合)中去pieVOList.add(pieVO);}// 将pieVOList集合进行返回return pieVOList;}/*** 获取各年龄阶段的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/@Overridepublic BarVO getUserAgeCountBarList() {/* 1.首先纵向封装: 将年龄阶段和用户数量(一条条单行数据)存入ageCountVoList集合中 */List<AgeCountVo> ageCountVoList = userInfoMapper.getUserAgeCountList();/* 2.然后横向封装: 将各个年龄阶段和用户数量存入到两个单独的List集合中去 */// 创建一个List集合ageLevels, 用于存储年龄阶段List<String> ageLevels = new ArrayList<>();// 创建一个List集合userCounts, 用于存储用户数量List<Integer> userCounts = new ArrayList<>();// 使用foreach遍历ageCountVoList集合(存储年龄阶段和用户数量的List集合)for (AgeCountVo ageCountVo : ageCountVoList) {// 将遍历出的年龄阶段和用户数量存入到其相对应的List集合中去ageLevels.add(ageCountVo.getAgeLevel());userCounts.add(ageCountVo.getUserCount());}/* 3.将存储年龄阶段和用户数量的List集合分别封装到BarVO对象中 */// 创建BarVO(柱状图视图对象)BarVO barVO = new BarVO();// 设置柱状图的名称(对应存储年龄阶段的List集合)barVO.setNames(ageLevels);// 设置柱状图的数量(对应存储用户数量的List集合)barVO.setValues(userCounts);// 将barVO(视图对象)进行返回return barVO;}}

1.3 SportInfoController控制层的实现代码

package com.rz.sport_manager.controller;import com.rz.sport_manager.entity.vo.BarVO;
import com.rz.sport_manager.entity.vo.PieVO;
import com.rz.sport_manager.service.UserInfoService;
import com.rz.sport_manager.utils.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName UserInfoController* @Description 用户信息表 前端控制器* @Author 狂奔de蜗牛rz* @Date 2022/04/25*/
//使用@Controller注解, 使当前类实现Controller接口, 并交由Spring容器统一管理
@Controller
//使用@RequestMapping注解, 设置get类型的请求映射路径
@RequestMapping("/sport_manager/user_info")
public class UserInfoController {// 通过类型自动装配UserInfoService接口@Autowiredprivate UserInfoService userInfoService;/*** 获取各角色的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/// 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型@GetMapping("/getRoleUserCountBarList")// 使用@ResponseBody注解, 把控制视图方法返回到请求页面上@ResponseBodypublic BarVO getRoleUserCountBarList() {// 返回值为调用userInfoService接口的getRoleUserCountBarList方法, 获取各角色的用户数量的柱状图数据集合return userInfoService.getRoleUserCountBarList();}/*** 获取各性别的用户数量的饼状图数据集合* @return List<PieVO> 泛型为PieVO的List集合*/// 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型@GetMapping("/getUserGenderCountPieList")// 使用@ResponseBody注解, 把控制视图方法返回到请求页面上@ResponseBodypublic List<PieVO> getUserGenderCountPieList() {// 返回值为调用applyInfoService接口的getUserGenderCountPieList方法, 获取各性别的用户数量的饼状图数据集合return userInfoService.getUserGenderCountPieList();}/*** 获取各年龄阶段的用户数量的柱状图数据集合* @return BarVO 饼状图的视图对象*/// 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型@GetMapping("/getUserAgeCountBarList")// 使用@ResponseBody注解, 把控制视图方法返回到请求页面上@ResponseBodypublic BarVO getUserAgeCountBarList() {// 返回值为调用userInfoService接口的getUserAgeCountBarList方法, 获取各年龄阶段的用户数量的柱状图数据集合return userInfoService.getUserAgeCountBarList();}}

2.LayUI前端主要实现代码

2.1 数据统计的前端主要实现代码

<style>.welcome .layui-card {border:1px solid #f2f2f2;border-radius:5px;}.welcome .icon {margin-right:10px;color:#1aa094;}.welcome .icon-blue {color:#1e9fff !important;}.welcome .icon-tip {color:#ff5722 !important;}.welcome .layuimini-qiuck-module {text-align:center;margin-top:10px}.welcome .layuimini-qiuck-module a i {display:inline-block;width:100%;height:60px;line-height:60px;text-align:center;border-radius:2px;font-size:30px;background-color:#F8F8F8;color:#333;transition:all .3s;-webkit-transition:all .3s;}.welcome .layuimini-qiuck-module a cite {position:relative;top:2px;display:block;color:#666;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:14px;}.welcome .welcome-module {width:100%;min-height:78px;}.welcome .panel {background-color:#fff;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.welcome .panel-body {padding:10px;height:80px;}.welcome .panel-title {margin-top:2px;margin-bottom:0;font-size:14px;color:inherit}.welcome .label {display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;margin-top:.3em;}.welcome .main_btn > p {height:40px;}.welcome .layui-bg-number {background-color:#F8F8F8;}.welcome .layuimini-notice:hover {background:#f6f6f6;}.welcome .layuimini-notice {padding:7px 16px;clear:both;font-size:12px !important;cursor:pointer;position:relative;transition:background 0.2s ease-in-out;}.welcome .layuimini-notice-title {padding-right:70px !important;text-overflow:ellipsis !important;overflow:hidden !important;white-space:nowrap !important;}.welcome .layuimini-notice-title {line-height:28px;font-size:14px;}.welcome .layuimini-notice-extra {position:absolute;top:50%;margin-top:-8px;right:16px;display:inline-block;height:16px;color:#999;}
</style>
<div class="layuimini-container layuimini-page-anim"><div class="layuimini-main welcome"><div class="layui-row layui-col-space20"><div class="layui-col-md12"><div class="layui-row layui-col-space15"><!-- 左侧区域: 数据统计和数据图表 --><div class="layui-col-md6"><!-- 左侧下部区域: 数据图表 --><div class="layui-card layui-col-md12"><!-- 数据图表标题 --><div class="layui-card-header"><i class="fa fa-bar-chart icon"></i>数据统计</div><!-- 数据图表tab页 --><div class="layui-tab layui-tab-card"><ul class="layui-tab-title"><!-- 当前选中的tab页 --><li class="layui-this my-tab">各角色用户数量统计</li><li class="my-tab">各性别用户数量统计</li><li class="my-tab">各年龄段用户数量统计</li></ul><!-- 数据图表tab页的显示内容 --><div class="layui-tab-content" style="min-height: 260px;"><!-- 当前tab页的显示内容 --><div class="layui-tab-item layui-show"><!-- 各个角色的用户数量柱图 --><div id="role-count-bar" style="width: 100%;min-height:260px"></div></div><div class="layui-tab-item"><!-- 各个性别的用户数量饼图 --><div id="user-gender-pie" style="width: 100%;min-height:260px"></div></div><div class="layui-tab-item"><!-- 各个年龄段的用户数量柱图 --><div id="age-count-bar" style="width: 100%;min-height:260px"></div></div></div></div></div></div>    </div></div></div></div>
</div>
<script>/* 加载jquery和echarts等实例 */layui.use(['jquery','echarts'], function () {// 获取jquery对象var $ = layui.jquery,// 获取echarts对象echarts = layui.echarts;/*** 加载echarts图表*/$(function () {// 加载各角色用户数量柱状图roleCountBar();// 加载各性别用户数量饼状图userGenderPie();// 加载各年龄段用户数量柱状图ageCountBar();/*** 各角色用户数量柱状图*/function roleCountBar() {// 获取id对应的dom元素,初始化echarts实例let myChart = echarts.init(document.getElementById('role-count-bar'));// 清除echarts实例myChart.clear();// 监听click点击事件$(".my-tab").click(function (e) {// 延迟0.3ssetTimeout(function () {// 重新加载宽高myChart.resize();}, 300);});/* 编写各角色用户数量柱状图数据的ajax请求 */$.ajax({// 请求方式为GETtype: 'GET',// 数据接口:请求发送到相应的controllerurl: "http://localhost:8080/sport_manager/user_info/getRoleUserCountBarList",// 数据类型为json格式dataType: 'json',// 内容类型为jsoncontentType: 'application/json',// 开启异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)async: true,/* 处理请求的回调函数 */success: function (data) {/* 设置echarts图表相关配置 */let option = {// 柱状图柱子鼠标悬浮的提示tooltip: {// 设置为浅灰color: 'rgb(255,255,255,.6)',width: '10%',trigger: 'axis',axisPointer: {type: 'shadow'}},// 柱状图背景网格grid: {left: '0%',top: '10px',right: '0%',bottom: '4%',containLabel: true},// 柱状图的x轴xAxis: [{// 类型为种类type: 'category',// 数据来源为后端获取的角色名称data: data.names,// x轴上的线条axisLine: {show: true,lineStyle: {// 设置X轴线条颜色为象牙黑color: "rgb(88,87,86)",width: 1,type: "solid"},},axisTick: {show: false,},// X轴下方文字axisLabel: {interval: 0,// rotate:50,show: true,splitNumber: 15,textStyle: {color: "rgb(88,87,86)",fontSize: '16',},},}],// 柱状图的Y轴yAxis: [{// 类型为valuetype: 'value',// Y轴左侧的文本axisLabel: {//formatter: '{value} %'show: true,textStyle: {color: "rgb(88,87,86)",fontSize: '12',},},axisTick: {show: false,},// Y轴上的线条axisLine: {show: true,lineStyle: {color: "rgb(88,87,86)",width: 1,type: "solid"},},// Y轴上的分割线splitLine: {lineStyle: {color: "rgb(211,211,211)",}}}],// 柱状图中的柱子series: [{// 类型为bartype: 'bar',// 数据来源为后端获取的用户数量data: data.values,// 柱子宽度barWidth: '20%',// 柱子的风格itemStyle: {normal: {// 柱子的颜色color: '#2f89cf',opacity: 1,// 柱子的圆角边框barBorderRadius: 5,}}}]};// 使用刚指定的配置项和数据显示图表myChart.setOption(option);// 监听echarts图标表调整大小事件window.addEventListener("resize", function () {myChart.resize();});}});}/*** 各性别用户数量饼状图*/function userGenderPie() {// 获取id对应的dom元素,初始化echarts实例let myChart = echarts.init(document.getElementById('user-gender-pie'));// 清除echarts实例myChart.clear();// 监听click点击事件$(".my-tab").click(function (e) {// 延迟0.3ssetTimeout(function () {// 重新加载宽高myChart.resize();}, 300);});/* 编写各性别用户数量的饼状图数据的ajax请求 */$.ajax({// 请求方式为GETtype: 'GET',// 数据接口:请求发送到相应的controllerurl: "http://localhost:8080/sport_manager/user_info/getUserGenderCountPieList",// 数据类型为json格式dataType: 'json',// 内容类型为jsoncontentType: 'application/json',// 开启异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)async: true,/* 处理请求的回调函数 */success: function (data) {/* 设置echarts图表相关配置 */let option = {// 设置饼图上方的标题样式title: [{text: '男女性别占比',left: 'center',textStyle: {color: 'rgb(88,87,86)',fontSize: '16'}}],// 设置鼠标悬浮后的提示样式tooltip: {trigger: 'item',formatter: "{a} <br/>{b}: {c} ({d}%)",// 参数p为当前鼠标的位置position: function (p) {return [p[0] + 10, p[1] - 10];}},// 设置饼图下方每个区域的分院名称legend: {// 距离顶部的距离top: '80%',// 每个子项的宽度itemWidth: 10,// 每个子项的高度itemHeight: 10,// 数据来源为来自后端的分院名称data: data.name,textStyle: {color: 'rgb(88,87,86)',fontSize: '16',}},// 设置饼图的相关样式series: [{name: "用户数量",// 类型为pie(即饼图)type: 'pie',// 位置居中center: ['50%', '42%'],// 圆角边框radius: ['40%', '60%'],// 每个区域的颜色color: ['rgb(255,20,147)','rgb(30,144,255)'],// 是否展示标签label: {show: false},// 是否展示标签线labelLine: {show: false},// 数据来源为来自后端的分院角色和用户数量data: data}]};// 使用刚指定的配置项和数据显示图表myChart.setOption(option);// 监听echarts图标表调整大小事件window.addEventListener("resize", function () {myChart.resize();});}})}/*** 各年龄阶段用户数量柱状图*/function ageCountBar() {// 获取id对应的dom元素,初始化echarts实例let myChart = echarts.init(document.getElementById('age-count-bar'));// 清除echarts实例myChart.clear();// 监听click点击事件$(".my-tab").click(function (e) {// 延迟0.3ssetTimeout(function () {// 重新加载宽高myChart.resize();}, 300);});/* 编写各年龄阶段用户数量的柱状图数据的ajax请求 */$.ajax({// 请求方式为GETtype: 'GET',// 数据接口:请求发送到相应的controllerurl: "http://localhost:8080/sport_manager/user_info/getUserAgeCountBarList",// 数据类型为json格式dataType: 'json',// 内容类型为jsoncontentType: 'application/json',// 开启异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)async: true,/* 处理请求的回调函数 */success: function (data) {/* 设置echarts图表相关配置 */let option = {// 柱状图柱子鼠标悬浮的提示tooltip: {// 设置为浅灰color: 'rgb(255,255,255,.6)',width: '10%',trigger: 'axis',axisPointer: {type: 'shadow'}},// 柱状图背景网格grid: {left: '0%',top: '10px',right: '0%',bottom: '4%',containLabel: true},// 柱状图的x轴xAxis: [{// 类型为种类type: 'category',// 数据来源为后端获取的年龄阶段data: data.names,// x轴上的线条axisLine: {show: true,lineStyle: {// 设置X轴线条颜色为象牙黑color: "rgb(88,87,86)",width: 1,type: "solid"},},axisTick: {show: false,},// X轴下方文字axisLabel: {interval: 0,// rotate:50,show: true,splitNumber: 15,textStyle: {color: "rgb(88,87,86)",fontSize: '16',},},}],// 柱状图的Y轴yAxis: [{// 类型为valuetype: 'value',// Y轴左侧的文本axisLabel: {show: true,textStyle: {color: "rgb(88,87,86)",fontSize: '12',},},axisTick: {show: false,},// Y轴上的线条axisLine: {show: true,lineStyle: {color: "rgb(88,87,86)",width: 1,type: "solid"},},// Y轴上的分割线splitLine: {lineStyle: {color: "rgb(211,211,211)",}}}],// 柱状图中的柱子series: [{// 类型为bartype: 'bar',// 数据来源为后端获取的用户数量data: data.values,// 柱子宽度barWidth: '20%',// 柱子的风格itemStyle: {normal: {// 柱子的颜色color: '#2f89cf',opacity: 1,// 柱子的圆角边框barBorderRadius: 5,}}}]};// 使用刚指定的配置项和数据显示图表myChart.setOption(option);// 监听echarts图标表调整大小事件window.addEventListener("resize", function () {myChart.resize();});}});}});});
</script>

2.2 数据统计的前端页面显示效果

2.2.1 各角色用户数量统计

2.2.2 各性别用户数量统计

2.2.3 各年龄段用户数量统计


以上就是如何使用SpringBoot框架LayUI框架MybatisPlus框架Echarts图表来实现数据统计功能的所有分享内容了。欢迎各位小伙伴讨论和学习,觉得还不错的不妨给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!

SpringBoot+LayUI+MybatisPlus+Echarts图表 前后端分离 实现数据统计功能相关推荐

  1. SpringBoot+LayUI+MybatisPlus 前后端分离 实现排名统计功能

    前言: 小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java快一年时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师. 首先给各位粉丝朋友 ...

  2. 基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统

    一.基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统 基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统,主要分为用户端和管理端两个模块. ...

  3. 视频教程-基于springboot2.x+layui+shiro+redis整合前后端分离的权限管理系统-Java

    基于springboot2.x+layui+shiro+redis整合前后端分离的权限管理系统 拥有八年的Java项目开发经验,擅长Java.vue.SpringBoot.springCloud.sp ...

  4. Springboot+vue 社团管理系统(前后端分离)

    Springboot+vue 社团管理系统(前后端分离) zero.项目功能设计图 一.数据库设计(项目准备) 1.建表 2.表目录 二.前端编写(vue) 1.搭建Vue框架 2.放入静态资源(as ...

  5. 计算机毕业设计-springboot企业考勤管理系统(前后端分离)员工考勤管理系统-公司日常管理系统java代码

    计算机毕业设计-springboot企业考勤管理系统(前后端分离)员工考勤管理系统-公司日常管理系统java代码 注意:该项目只展示部分功能,如需了解,联系咨询即可. 作者:IT跃迁谷 1.开发环境 ...

  6. 毕设:基于SpringBoot+Vue 实现云音乐(前后端分离)

    文章目录 一.简介 2.项目介绍 二.功能 2.功能介绍 三.核心技术 1.系统架构图 2.技术选型 五.运行 3.截图 前端界面 后台管理界面 总结 1.完整工程 2.其他 一.简介 2.项目介绍 ...

  7. Ruo-Yi前后端分离的数据过滤

    Ruo-Yi前后端分离的数据过滤 若依官网的介绍:http://doc.ruoyi.vip/ruoyi/document/htsc.html#%E6%95%B0%E6%8D%AE%E6%9D%83%E ...

  8. 前后端分离实现在线记账功能,前端使用vue,后端使用springmvc

    前后端分离实现在线记账功能 前端采用vue 后端采用springmvc 前端目录 后端目录 运行结果 双击单元格可以对每一项内容进行修改

  9. Django前后端分离实现登录验证码功能

    Django前后端分离实现登录验证码功能 当下最流行最热门的开发方式当属前后端分离开发,分工也更加明确与专注,前端也是越来越难,几天不学习就跟不上节奏,一个月不学习可以好不夸张的说,你已经不适合这个行 ...

最新文章

  1. angular的路由
  2. 数据列表DataList模板之实例
  3. GPUImage API 文档之GPUImagePicture类
  4. 出让执行权:Task.Yield, Dispathcer.Yield
  5. PHP文件系统-文件上传类
  6. 最全三大框架整合(使用映射)——Emp.hbm.xml
  7. 4000元性价比主机
  8. 一元线性回归中loss值的变化分析
  9. Typecho安装后后台界面和文章链接均为404错误的解决方法
  10. mysql sysbench 1.0.X
  11. 运动控制卡培训--运动控制卡疑问解答l
  12. 手机vnc远程控制软件,2步完成手机vnc远程控制软件的安装和使用
  13. 路由器桥接成功后,仍然没有网络
  14. 如何群发邮件?群发邮件让发收件人互相不知道?邮箱群发邮件技巧
  15. 可定制代理软件——privoxy
  16. python处理PPOCRLabel标注的数据用于LPRNet与Yolo的训练
  17. 浙江大学计算机学院2019推免,浙江大学控制科学与工程学院2019年推免夏令营信息通知...
  18. Java学习--day02---运算,一些重要的程序
  19. SSM框架中Dao层,Mapper层,controller层,service层,model层,entity层都有什么作用
  20. ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库

热门文章

  1. 揽月摘星 | 第 13 届金鼠标数字营销大赛得奖名单出炉,知家斩获 5 项大奖
  2. Android studio成品 记账本(附带文档)
  3. Android 仿QQ登录动态背景
  4. python版FlappyBird代码解析
  5. 学生信息管理系统 C++实现
  6. NDN命名网络工作机制和优点
  7. 苹果6plus一直没信号服务器,苹果6sPlus信号弱或者无服务解决方法
  8. 笔记本显示dns服务器,笔记本电脑显示无线网DNS设置错误该怎么解决
  9. 程序员美工和真正的游戏美工是两个世界的人
  10. 20145212《Java程序程序设计》课程总结