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

2023-05-16

前言

小伙伴们,大家好,我是狂奔の蜗牛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 ui
        left join sport_manager01.role_info ri on ri.role_id = ui.role_id
        where 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 ui
        where 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_info
        where 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接口
    @Autowired
    private UserInfoMapper userInfoMapper;
    
    /**
     * 获取各角色的用户数量的柱状图数据集合
     * @return BarVO 饼状图的视图对象
     */
    @Override
    public 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集合
     */
    @Override
    public 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 饼状图的视图对象
     */
    @Override
    public 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接口
    @Autowired
    private UserInfoService userInfoService;
    
    /**
     * 获取各角色的用户数量的柱状图数据集合
     * @return BarVO 饼状图的视图对象
     */
    // 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型
    @GetMapping("/getRoleUserCountBarList")
    // 使用@ResponseBody注解, 把控制视图方法返回到请求页面上
    @ResponseBody
    public BarVO getRoleUserCountBarList() {
        // 返回值为调用userInfoService接口的getRoleUserCountBarList方法, 获取各角色的用户数量的柱状图数据集合
        return userInfoService.getRoleUserCountBarList();
    }

    /**
     * 获取各性别的用户数量的饼状图数据集合
     * @return List<PieVO> 泛型为PieVO的List集合
     */
    // 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型
    @GetMapping("/getUserGenderCountPieList")
    // 使用@ResponseBody注解, 把控制视图方法返回到请求页面上
    @ResponseBody
    public List<PieVO> getUserGenderCountPieList() {
        // 返回值为调用applyInfoService接口的getUserGenderCountPieList方法, 获取各性别的用户数量的饼状图数据集合
        return userInfoService.getUserGenderCountPieList();
    }

    /**
     * 获取各年龄阶段的用户数量的柱状图数据集合
     * @return BarVO 饼状图的视图对象
     */
    // 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型
    @GetMapping("/getUserAgeCountBarList")
    // 使用@ResponseBody注解, 把控制视图方法返回到请求页面上
    @ResponseBody
    public 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.3s
                    setTimeout(function () {
                        // 重新加载宽高
                        myChart.resize();
                    }, 300);
                });

                /* 编写各角色用户数量柱状图数据的ajax请求 */
                $.ajax({
                    // 请求方式为GET
                    type: 'GET',
                    // 数据接口:请求发送到相应的controller
                    url: "http://localhost:8080/sport_manager/user_info/getRoleUserCountBarList",
                    // 数据类型为json格式
                    dataType: 'json',
                    // 内容类型为json
                    contentType: '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: [{
                                // 类型为value
                                type: '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: [{
                                // 类型为bar
                                type: '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.3s
                    setTimeout(function () {
                        // 重新加载宽高
                        myChart.resize();
                    }, 300);
                });

                /* 编写各性别用户数量的饼状图数据的ajax请求 */
                $.ajax({
                    // 请求方式为GET
                    type: 'GET',
                    // 数据接口:请求发送到相应的controller
                    url: "http://localhost:8080/sport_manager/user_info/getUserGenderCountPieList",
                    // 数据类型为json格式
                    dataType: 'json',
                    // 内容类型为json
                    contentType: '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.3s
                    setTimeout(function () {
                        // 重新加载宽高
                        myChart.resize();
                    }, 300);
                });

                /* 编写各年龄阶段用户数量的柱状图数据的ajax请求 */
                $.ajax({
                    // 请求方式为GET
                    type: 'GET',
                    // 数据接口:请求发送到相应的controller
                    url: "http://localhost:8080/sport_manager/user_info/getUserAgeCountBarList",
                    // 数据类型为json格式
                    dataType: 'json',
                    // 内容类型为json
                    contentType: '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: [{
                                // 类型为value
                                type: '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: [{
                                // 类型为bar
                                type: '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图表来实现数据统计功能的所有分享内容了。欢迎各位小伙伴讨论和学习,觉得还不错的不妨给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Shell函数参数

    在shell中调用函数时 xff0c 可以向其传递参数 xff0c 其中常用的特殊变量如下表所示 xff1a 函数参数 含义 传递到脚本或函数的参数个数 n 1表示第一个参数 xff0c 2表示第二个参数 注意 xff0c 当n gt 61
  • Dockerfile

    Dockerfile Dockerfile是一种文本文件 xff0c 用于定义如何构建Docker镜像 它包含一系列的指令 xff0c 告诉Docker引擎如何在容器中构建和运行应用程序 Dockerfile指令分类 xff1a 基础镜像指
  • thonny中文版|python编辑

    由于人工智能的兴起 xff0c python语言成了最受欢迎的编程语言 xff0c 为此小编给广大新手用户带来了thonny编辑器 xff0c 这是一款相当优秀的python初学者专用编程学习工具 该软件基于python内置图形库tkint
  • 如何限制HTML中select标签option可见选项数目

    如何限制HTML中select标签option可见选项数目 在使用select标签的时候 xff0c 如果option选项太多 xff0c 会造成下拉列表变得很长 xff08 浏览器默认20条 xff09 如果想控制select中的opti
  • 如何解决win7休眠后自动唤醒的现象

    http jingyan baidu com article ca00d56c50e598e99eebcfea html
  • java实现x 的平方根

    class Solution public int mySqrt int x int left 61 1 int right 61 x int mid while left lt 61 right mid 61 left 43 right
  • 什么是字节对齐?字节对齐与位域的计算

    目录 1 什么是字节对齐 xff1f 为什么要字节对齐 xff1f 2 字节对齐的规则3 字节对齐的数值4 位域5 位域的填充 1 什么是字节对齐 xff1f 为什么要字节对齐 xff1f 字节对齐也称为字节填充 xff0c 它是一种牺牲空
  • Cordova打包流程(其中一种简单的方法)

    1 新建项目 cordova create carder 文件名字 com xtzn carder leader 项目名称 2 cd carder xff08 进入文件 xff09 3 运行 cordova platform add and
  • Could not found property service.vgroup_mapping.my_test_tx_group

    seat本地服务中的 file conf 和regeist conf 配置文件 与项目中的 file conf 和regeist conf 中对应的文件要一致 项目中的 regeist conf 本地服务中的 registry conf 上
  • 获取Windows 10上文件资源管理器的帮助

    Windows 10 no longer has built in help for File Explorer as Windows 7 does Microsoft makes you search the web for inform
  • 餐饮店实现扫码点餐、语音播报、自动打印厨房单结账单

    使用场景 xff1a 餐饮店在桌子上张贴二维码 小程序并引导消费者扫描点餐 xff0c 点餐后收银台会有声音提醒 xff1a 三号桌下单了 xff01 三号桌下单了 xff01 xff0c 服务员打开手机确认订单 xff0c 如果消费者需求
  • 关于electron报read ECONNRESET解决方案

    关于electron报read ECONNRESET解决方案 问题解决方法 问题 D APP gui gt npm install save dev electron npm ERR code 1 npm ERR path D APP gu
  • spring配置文件

    文章目录 1 Spring程序开发步骤2 Spring配置文件2 1 Bean标签基本配置2 2 Bean标签范围配置2 2 Bean生命周期配置2 3 Bean实例化三种方式2 4 Bean的依赖注入分析2 5 依赖注入概念2 6 Bea
  • SpringMVC学习【执行流程-搭建和使用】

    一 xff1a SpringMVC执行流程 1 一共有四大组件 中央管理器 处理器映射器 处理器适配器 视图解析器 2 描述流程 用户向服务端发送一次请求 xff0c 这个请求会先到中央控制器DispatcherServletDispatc
  • 多线程任务超时的处理机制

    使用Thread join long million 方法 xff0c 参数是毫秒 代码 amp 解析如下 xff1a 解析 xff1a 原本有t1和t2两个线程 xff0c 根据实例化new Task xff08 xff09 时t1传入了
  • django-apscheduler “Run time of job was missed“ solution

    在 Django 中使用 django apscheduler 实现定时任务 发现报错如下 Run span class token function time span of job span class token string 34
  • Freemarker异常:freemarker.template.TemplateNotFoundException: Template not found for name “xxx.ftl“.

    问题背景 在Spring Boot项目里整合Freemarker xff0c 目标是使用Freemarker模板文件生成代码 模板在在resources template里边明明有对应的xxx ftl文件 xff0c 但是却报错说没有找到该
  • Eclipse+IntelliJ IDEA如何设置中文

    一 Eclipse中文教程 1 进入 Eclipse Babel Project Downloads The Eclipse Foundation 查看最新的语言包存储库链接 xff0c 复制下来等会儿进入eclipse中需要使用 xff1
  • Linux系统运行等级切换(6和7系列)

    一 查看系统运行等级 运行等级介绍 运行级别 模式说明 简介 0 系统关机 系统默认运行级别不能设置为0 xff0c 不能将initdefault设置为0 1 单用户 root权限 xff0c 用于系统维护 xff0c 禁止远程登陆 xff
  • 在Ubuntu中安装选项卡式文件管理器

    One of the greatest mysteries to me is why most file managers don t have tabs it makes performing tasks so much simpler

随机推荐

  • linux查看防火墙状态及开启关闭命令(centos6版)

    存在以下两种方式 xff1a 一 service方式 查看防火墙状态 xff1a service iptables status 开启防火墙 xff1a service iptables start 关闭防火墙 xff1a service
  • IntelliJ IDEA中程序包org.slf4j 找不到的问题解决方案

    最近导入项目的时候遇到个莫名其妙的问题 xff0c 提示程序包org slf4j找不到 查了下maven xff0c slf4j和log4j都已经导入了 捣鼓了老半天终于发现问题了 xff1a 记得把slf4j log4j的包也一起导入进去
  • 头条一面:Spring IOC容器中只存放单例Bean吗?

    最近 xff0c 很多小伙伴出去面试 xff0c 感觉自己面的不是很理想 xff0c 回来后 xff0c 不少小伙伴把面试题做了记录发给我 xff0c 让我给大家解析下 xff0c 然后发出来 当我看到这些面试题时 xff0c 快速在脑海中
  • SpringBoot 启动类 @SpringBootApplication 注解

    64 SpringBootApplication是SpringBoot项目的核心注解 xff0c 目的是开启自动配置 annotation 以下是 64 SpringBootApplication源代码的一部分 xff1a 64 span
  • 【SAP-FI】承诺项目(Commitment item)详解

    定义 xff1a 承诺项目表示组织在财务管理区域 xff08 FM区域 xff09 内的功能分组 用途 xff1a 承诺项目将影响流动性的预算交易和商业交易分类为收入 xff0c 支出和现金余额项目 您可以将特定责任区域 xff08 资金中
  • ERROR 1054 (42S22): Unknown column ‘password‘ in ‘field list‘

    centos8安装mysql5 7修改密码时报错 xff1a ERROR 1054 42S22 Unknown column password in field list MySQL官网手册表示MySQL5 7版本后 xff0c passw
  • PS二寸证件照制作

    一 新建画布 文件 gt 新建 二寸证件照尺寸 xff1a 3 5 5 3 厘米 413 626 像素 分辨率为300 像素 英寸 一寸证件照尺寸 xff1a 2 5 3 5 厘米 295 413 像素 分辨率为300 像素 英寸 小二寸证
  • Eclipse安装教程(JDK安装+Eclipse+汉化)Windows系统

    文章目录 说明 xff1a 本教程截图是JDK13 43 eclipse2019 12的 xff0c 但是安装方法相同第一步 xff1a 下载并安装JDK1 下载JDK xff08 目前已更新到JDK14 xff0c 和JDK13安装方法相
  • arch linux 安装教程

    注意 本文章停更 xff0c 如果想看最新版本 xff0c 请移步Arch Linux安装教程 下一篇 xff1a archlinux系统配置 archlinux系统配置
  • archlinux 配置

    文章目录 上一篇 xff1a archlinux 系统安装下一篇 xff1a archlinux kde美化 上一篇 xff1a archlinux 系统安装 archlinux安装教程 此文章停止更新 xff0c 最新版请查看archli
  • 【Frobenius norm(弗罗贝尼乌斯-范数)(F-范数)】

    xff08 1 xff09 Frobenius 范数 xff08 F 范数 xff09 一种矩阵范数 xff0c 记为 xff1a 即矩阵中每项数的平方和的开方值 这个范数是针对矩阵而言的 xff0c 具体定义可以类比 向量的L2范数 可用
  • 谷歌pay 手续费_您可以使用Google Pay进行的所有操作

    谷歌pay 手续费 Google Pay has really grown over the last several months It stepped away from the Android specific branding an
  • RabbitMQ工作模式

    RabbitMQ工作模式 简述 xff1a RabbitMQ主要有五种工作模式 xff0c 分别是 xff1a 1 简单模式 xff08 Hello World xff09 2 工作队列模式 xff08 Work Queue xff09 3
  • AD布局时出现的自动推挤的使用

    AD布局时出现的自动推挤的使用 在使用AD进行器件布局发现拖动元件时会出现以下3中情况 xff1a 1 拖动器件时会直接挤走与之相近的器件 xff1b 2 拖动器件时碰到相邻方向有器件时无法越过对应阻碍其拖动的器件 xff1b 3 拖动器件
  • 多线程基础学习之线程安全和抢火车票问题

    前言 xff1a 在生活中 xff0c 每次出远门 xff0c 避免不了的就是要坐火车或者高铁 xff0c 那么抢票就是我们必须要经历的环节 xff0c 但你是否想过 xff0c 假如你和别人同时抢到一张票 xff0c 会发生什么 xff1
  • Git基础学习之Gitee的使用和设置SSH公钥

    前言 xff1a 今天给大家分享的学习内容是 xff1a Gitee的注册和使用 xff0c SSH公钥的设置 xff0c 以及如何搭建自己的远程仓库 学习前提 xff1a 安装和配置好本地Git xff0c 如果还没有安装好本地Git的小
  • Redis基础学习之NoSQL数据库四大分类

    前言 xff1a 在NoSQL数据库中 xff0c 主要有四大分类 xff0c 分别是KV键值对数据库 文档型数据库 列存储数据库和图形关系数据库 xff0c 那么它们各自的特点以及之间的区别是什么呢 xff1f 这就是今天我们所要学习的内
  • SpringBoot基础学习之整合SpringSercurity框架

    前言 xff1a 小伙伴们 xff0c 大家好 xff0c 我是狂奔 蜗牛rz xff0c 当然你们可以叫我蜗牛君 xff0c 我是一个学习Java半年多时间的小菜鸟 xff0c 同时还有一个伟大的梦想 xff0c 那就是有朝一日 xff0
  • SpringMVC基础学习之页面跳转方式的简单使用

    前言 xff1a 小伙伴们 xff0c 大家好 xff0c 我是狂奔 蜗牛rz xff0c 当然你们可以叫我蜗牛君 xff0c 我是一个学习Java半年多时间的小菜鸟 xff0c 同时还有一个伟大的梦想 xff0c 那就是有朝一日 xff0
  • SpringBoot+LayUI+MybatisPlus+Echarts图表 前后端分离 实现数据统计功能

    前言 xff1a 小伙伴们 xff0c 大家好 xff0c 我是狂奔 蜗牛rz xff0c 当然你们可以叫我蜗牛君 xff0c 我是一个学习Java快一年时间的小菜鸟 xff0c 同时还有一个伟大的梦想 xff0c 那就是有朝一日 xff0