前言:
小伙伴们,大家好,我是狂奔の蜗牛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图表来实现数据统计功能的所有分享内容了。欢迎各位小伙伴讨论和学习,觉得还不错的不妨给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!