智慧社区(七)——基于 ECharts 与 Spring Boot 实现小区住户数据统计可视化
在智慧社区管理系统中,数据可视化是非常重要的一环。本文将详细介绍如何使用 ECharts 结合 Spring Boot 后端实现小区住户数量的统计与展示,包括柱状图对比和饼图占比分析。
技术准备首先需要准备相关的技术栈和环境:
- 后端:Spring Boot、MyBatis-Plus
- 前端:Vue.js、ECharts 4.9.0
- 数据库:MySQL
ECharts 安装
在前端项目中安装 ECharts:
cnpm install echarts@4.9.0 --save
安装完成后,在 Vue 项目中全局引入 ECharts:
// main.js
import echarts from "echarts";
Vue.prototype.$echarts = echarts;
功能需求分析
我们需要实现的功能是:查询所有小区名称及其对应的住户数量,通过 ECharts 以柱状图和饼图两种形式展示。
返回的数据格式应包含:
- 小区名称数组 (names)
- 住户数量数组 (nums)
- 包含名称和数量的对象数组 (list)
后端实现
1. 数据模型设计
首先创建用于封装图表数据的 VO 类:
package com.qcby.community.vo;import lombok.Data;/*** 图表数据封装VO类*/
@Data
public class ChartVO {private Integer value; // 数值,这里表示住户数量private String name; // 名称,这里表示小区名称
}
2. Mapper 层实现
创建 Mapper 接口,编写 SQL 查询小区及其对应的住户数量:
package com.qcby.community.mapper;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qcby.community.entity.InOutRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.community.vo.ChartVO;
import com.qcby.community.vo.InOutRecordVO;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;import java.util.Date;
import java.util.List;/*** 出入记录Mapper接口*/
@Repository
public interface InOutRecordMapper extends BaseMapper<InOutRecord> {/*** 统计各小区住户数量* 从社区表(community)和住户表(person)关联查询* 按小区分组,统计每个小区的住户数量*/@Select("select count(*) value, c.community_name name " +"from community c, person p " +"where p.community_id = c.community_id " +"group by c.community_id")List<ChartVO> chart();// 其他方法...
}
SQL 查询说明:
- 通过
community
表和person
表关联,关联条件是p.community_id = c.community_id
- 使用
count(*)
统计每个小区的住户数量,别名value
- 选取小区名称
c.community_name
,别名name
- 按
c.community_id
分组,确保每个小区只统计一次
3. Service 层实现
创建 Service 接口和实现类,处理业务逻辑:
package com.qcby.community.service;import com.qcby.community.entity.InOutRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.community.form.InOutRecordListForm;
import com.qcby.community.vo.PageVO;import java.util.Map;/*** 出入记录服务接口*/
public interface InOutRecordService extends IService<InOutRecord> {/*** 获取小区住户统计数据* @return 包含统计数据的Map*/Map chart();// 其他方法...
}
Service 层逻辑说明:
- 调用 Mapper 层的
chart()
方法获取原始统计数据 - 将数据分别封装到三个列表中:
names
:存储所有小区名称nums
:存储对应小区的住户数量list
:存储包含名称和数量的对象
- 将三个列表放入 Map 中返回
4. Controller 层实现
创建 Controller,提供 HTTP 接口供前端调用:
package com.qcby.community.controller;import com.qcby.community.service.InOutRecordService;
import com.qcby.community.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;/*** 出入记录控制器*/
@RestController
@RequestMapping("/sys/inOut")
public class InOutRecordController {@Autowiredprivate InOutRecordService inOutRecordService;/*** 查看小区数据统计* 提供ECharts所需的统计数据* @return 包含统计数据的响应结果*/@GetMapping("/chart")public Result chart() {// 调用Service层获取统计数据Map map = this.inOutRecordService.chart();// 封装成统一响应格式返回return Result.ok().put("data", map);}// 其他接口...
}
Controller 层说明:
- 使用
@RestController
注解标识这是一个 RESTful 接口控制器 - 映射路径为
/sys/inOut
- 提供
/chart
接口,通过 GET 方式访问 - 调用 Service 层的
chart()
方法获取数据 - 使用统一的
Result
工具类封装响应结果
前端实现
1. 从 ECharts 官网获取基础图表代码
ECharts 官网 (Apache ECharts) 提供了丰富的图表示例,我们可以从中获取基础代码并进行修改。
例如,柱状图基础代码结构:
// 初始化图表实例
var myChart = echarts.init(document.getElementById('myChart'));// 配置图表选项
var option = {title: {text: '图表标题'},tooltip: {},xAxis: {data: ['数据1', '数据2', '数据3']},yAxis: {},series: [{name: '系列名称',type: 'bar',data: [10, 20, 30]}]
};// 使用配置项绘制图表
myChart.setOption(option);
饼图基础代码结构:
// 初始化图表实例
var myChart2 = echarts.init(document.getElementById('myChart2'));// 配置图表选项
var option2 = {title: {text: '图表标题'},tooltip: {trigger: 'item'},series: [{name: '系列名称',type: 'pie',data: [{value: 10, name: '数据1'},{value: 20, name: '数据2'},{value: 30, name: '数据3'}]}]
};// 使用配置项绘制图表
myChart2.setOption(option2);
2. 改造代码适配后端数据
我们需要将从官网获取的基础代码改造为能够加载后端接口数据的形式:
<template><div class="app-container"><div><!-- 柱状图容器 --><div id="myChart" style="width: 50%;height:600px;margin-top: 10px; float: left"></div><!-- 饼图容器 --><div id="myChart2" style="width: 50%;height:600px;margin-top: 10px; float: right"></div></div></div>
</template><script>
// 导入API接口
import { chart } from '@/api/sys/inOut'export default {name: 'CommunityChart',data() {return {}},// 组件挂载后执行mounted(){this.drawLine();},methods: {// 绘制图表方法drawLine(){// 调用后端API获取统计数据chart().then(res => {// 基于准备好的dom,初始化echarts实例let myChart = this.$echarts.init(document.getElementById('myChart'))// 绘制柱状图myChart.setOption({color: ['#3398DB'],title: {text: '智慧社区住户量统计',subtext: '对比图',left: 'center'},tooltip: {trigger: 'axis',axisPointer: {type: 'shadow'}},// X轴数据使用后端返回的小区名称数组xAxis: {data: res.data.names},yAxis: {},series: [{name: '住户量',type: 'bar',// 系列数据使用后端返回的住户数量数组data: res.data.nums}],animationType: 'scale',animationEasing: 'elasticOut',animationDelay: function (idx) {return Math.random() * 200;}});// 初始化饼图实例let myChart2 = this.$echarts.init(document.getElementById('myChart2'))// 绘制饼图myChart2.setOption({title: {text: '智慧社区住户量统计',subtext: '占比图',left: 'center'},tooltip: {trigger: 'item',formatter: '{a} <br/>{b} : {c} ({d}%)'},visualMap: {show: false,min: 80,max: 600,inRange: {colorLightness: [0, 1]}},series: [{name: '住户量',type: 'pie',radius: '55%',center: ['50%', '50%'],// 饼图数据使用后端返回的对象数组data: res.data.list.sort(function (a, b) { return a.value - b.value; }),roseType: 'radius',itemStyle: {color: '#3398DB'},animationType: 'scale',animationEasing: 'elasticOut',animationDelay: function (idx) {return Math.random() * 200;}}]});});}}
}
</script><style lang="scss" scoped>
/* 组件样式 */
</style>
前端实现说明:
- 在组件挂载后调用
drawLine()
方法 - 通过
chart()
API 调用后端接口获取数据 - 初始化两个 ECharts 实例,分别用于柱状图和饼图
- 将后端返回的数据填充到图表配置中:
- 柱状图的 xAxis.data 使用
res.data.names
- 柱状图的 series.data 使用
res.data.nums
- 饼图的 series.data 使用
res.data.list
- 柱状图的 xAxis.data 使用
- 添加动画效果增强用户体验
完整流程解析
-
数据流向:
- 数据库 → Mapper → Service → Controller → 前端 → ECharts
-
关键步骤:
- 数据库查询:通过关联查询获取每个小区的住户数量
- 数据转换:将查询结果转换为 ECharts 所需的格式
- 接口提供:通过 RESTful 接口向前端提供数据
- 数据渲染:前端获取数据后渲染到 ECharts 图表中
-
前后端数据对接:
- 后端返回的数据结构与前端 ECharts 所需的数据格式完全匹配
- 柱状图需要两个数组(名称数组和数值数组)
- 饼图需要一个包含 name 和 value 属性的对象数组