前言:
小伙伴们,大家好,我是狂奔の蜗牛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;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BarVO implements Serializable {
private List<String> names;
private List<Integer> values;
}
1.1.2 饼状图视图对象PieVO的实现代码
package com.rz.sport_manager.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@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;
@Data
@AllArgsConstructor
@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;
@Data
@AllArgsConstructor
@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;
@Data
@AllArgsConstructor
@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;
@Repository
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
public List<UserCountVo> getRoleUserCountList();
public List<GenderCountVo> getUserGenderCountList();
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>
<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="roleName" column="role_name"/>
<result property="userCount" column="user_count"/>
</resultMap>
<resultMap id="genderCountMap" type="com.rz.sport_manager.entity.vo.GenderCountVo">
<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="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;
public interface UserInfoService extends IService<UserInfo> {
public BarVO getRoleUserCountBarList();
public List<PieVO> getUserGenderCountPieList();
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;
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
@Override
public BarVO getRoleUserCountBarList() {
List<UserCountVo> userCountVoList = userInfoMapper.getRoleUserCountList();
List<String> roleNames = new ArrayList<>();
List<Integer> userCounts = new ArrayList<>();
for (UserCountVo userCountVo : userCountVoList) {
roleNames.add(userCountVo.getRoleName());
userCounts.add(userCountVo.getUserCount());
}
BarVO barVO = new BarVO();
barVO.setNames(roleNames);
barVO.setValues(userCounts);
return barVO;
}
@Override
public List<PieVO> getUserGenderCountPieList() {
List<GenderCountVo> genderCountVoList = userInfoMapper.getUserGenderCountList();
List<PieVO> pieVOList = new ArrayList<PieVO>();
for (GenderCountVo genderCountVo : genderCountVoList) {
PieVO pieVO = new PieVO();
pieVO.setValue(genderCountVo.getUserCount());
pieVO.setName(genderCountVo.getGenderName());
pieVOList.add(pieVO);
}
return pieVOList;
}
@Override
public BarVO getUserAgeCountBarList() {
List<AgeCountVo> ageCountVoList = userInfoMapper.getUserAgeCountList();
List<String> ageLevels = new ArrayList<>();
List<Integer> userCounts = new ArrayList<>();
for (AgeCountVo ageCountVo : ageCountVoList) {
ageLevels.add(ageCountVo.getAgeLevel());
userCounts.add(ageCountVo.getUserCount());
}
BarVO barVO = new BarVO();
barVO.setNames(ageLevels);
barVO.setValues(userCounts);
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;
@Controller
@RequestMapping("/sport_manager/user_info")
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
@GetMapping("/getRoleUserCountBarList")
@ResponseBody
public BarVO getRoleUserCountBarList() {
return userInfoService.getRoleUserCountBarList();
}
@GetMapping("/getUserGenderCountPieList")
@ResponseBody
public List<PieVO> getUserGenderCountPieList() {
return userInfoService.getUserGenderCountPieList();
}
@GetMapping("/getUserAgeCountBarList")
@ResponseBody
public BarVO 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>
<div class="layui-tab layui-tab-card">
<ul class="layui-tab-title">
<li class="layui-this my-tab">各角色用户数量统计</li>
<li class="my-tab">各性别用户数量统计</li>
<li class="my-tab">各年龄段用户数量统计</li>
</ul>
<div class="layui-tab-content" style="min-height: 260px;">
<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>
layui.use(['jquery','echarts'], function () {
var $ = layui.jquery,
echarts = layui.echarts;
$(function () {
roleCountBar();
userGenderPie();
ageCountBar();
function roleCountBar() {
let myChart = echarts.init(document.getElementById('role-count-bar'));
myChart.clear();
$(".my-tab").click(function (e) {
setTimeout(function () {
myChart.resize();
}, 300);
});
$.ajax({
type: 'GET',
url: "http://localhost:8080/sport_manager/user_info/getRoleUserCountBarList",
dataType: 'json',
contentType: 'application/json',
async: true,
success: function (data) {
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
},
xAxis: [{
type: 'category',
data: data.names,
axisLine: {
show: true,
lineStyle: {
color: "rgb(88,87,86)",
width: 1,
type: "solid"
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
show: true,
splitNumber: 15,
textStyle: {
color: "rgb(88,87,86)",
fontSize: '16',
},
},
}],
yAxis: [{
type: 'value',
axisLabel: {
show: true,
textStyle: {
color: "rgb(88,87,86)",
fontSize: '12',
},
},
axisTick: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: "rgb(88,87,86)",
width: 1,
type: "solid"
},
},
splitLine: {
lineStyle: {
color: "rgb(211,211,211)",
}
}
}],
series: [{
type: 'bar',
data: data.values,
barWidth: '20%',
itemStyle: {
normal: {
color: '#2f89cf',
opacity: 1,
barBorderRadius: 5,
}
}
}]
};
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
});
}
function userGenderPie() {
let myChart = echarts.init(document.getElementById('user-gender-pie'));
myChart.clear();
$(".my-tab").click(function (e) {
setTimeout(function () {
myChart.resize();
}, 300);
});
$.ajax({
type: 'GET',
url: "http://localhost:8080/sport_manager/user_info/getUserGenderCountPieList",
dataType: 'json',
contentType: 'application/json',
async: true,
success: function (data) {
let option = {
title: [{
text: '男女性别占比',
left: 'center',
textStyle: {
color: 'rgb(88,87,86)',
fontSize: '16'
}
}],
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)",
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: "用户数量",
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);
window.addEventListener("resize", function () {
myChart.resize();
});
}
})
}
function ageCountBar() {
let myChart = echarts.init(document.getElementById('age-count-bar'));
myChart.clear();
$(".my-tab").click(function (e) {
setTimeout(function () {
myChart.resize();
}, 300);
});
$.ajax({
type: 'GET',
url: "http://localhost:8080/sport_manager/user_info/getUserAgeCountBarList",
dataType: 'json',
contentType: 'application/json',
async: true,
success: function (data) {
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
},
xAxis: [{
type: 'category',
data: data.names,
axisLine: {
show: true,
lineStyle: {
color: "rgb(88,87,86)",
width: 1,
type: "solid"
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
show: true,
splitNumber: 15,
textStyle: {
color: "rgb(88,87,86)",
fontSize: '16',
},
},
}],
yAxis: [{
type: 'value',
axisLabel: {
show: true,
textStyle: {
color: "rgb(88,87,86)",
fontSize: '12',
},
},
axisTick: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: "rgb(88,87,86)",
width: 1,
type: "solid"
},
},
splitLine: {
lineStyle: {
color: "rgb(211,211,211)",
}
}
}],
series: [{
type: 'bar',
data: data.values,
barWidth: '20%',
itemStyle: {
normal: {
color: '#2f89cf',
opacity: 1,
barBorderRadius: 5,
}
}
}]
};
myChart.setOption(option);
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(使用前将#替换为@)