项目中的Echarts图表统计

news2024/11/27 21:42:15

数据可视化

  • 一、Echarts
  • 二、前端(Vue+Echarts)
    • HomeView.vue(完整代码)
  • 三、后端(SpringBoot+MyBatis)
    • BorrowController.java
    • IBorrowService.java
    • BorrowService.java
      • datetimeToDateStr()函数
      • countList()函数
    • BorrowReturCountPO(自定义类封装)
    • BorrowMapper.java
    • Borrow.xml

前情提要:本次Echarts数据可视化基于图书管理系统设计

一、Echarts

Echarts是一个开源的可视化图表库,由百度前端技术部开发维护。它基于JavaScript语言实现,通过简单的配置即可生成丰富多样的图表,包括柱状图、折线图、饼图等等。Echarts支持各种数据格式,如JSON、XML、CSV等,同时也提供了强大的交互功能,可以让用户在图表上进行缩放、平移、标记等操作。Echarts还有丰富的扩展插件和主题,方便用户根据不同需求进行自定义定制。Echarts的优点在于使用简单、灵活性高、可定制性强,并且提供了完善的文档和API参考,方便开发人员快速上手和开发。

二、前端(Vue+Echarts)

Echarts下载:npm i echarts -S

HomeView.vue(完整代码)

<template>
  <div>
    <div style="margin: 20px 0">
      <el-select class="input" v-model="timeRange" placeholder="请选择" @change="load">
        <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
        </el-option>
      </el-select>
    </div>
    <el-card>
      <div id="line" style="width: 100%; height: 400px"></div>
    </el-card>
  </div>
</template>

<script>
import Cookies from 'js-cookie'
import request from "@/utils/request";
import * as echarts from 'echarts'

const option = {
  title: {
    text: '图书借还统计'
  },
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: ['借书数量', '还书数量']
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  toolbox: {
    feature: {
      saveAsImage: {}
    }
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: []  //从后台动态获取
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      name: '借书数量',
      type: 'line',
      stack: 'Total',
      smooth: true,
      data: []    //从后台动态获取
    },
    {
      name: '还书数量',
      type: 'line',
      smooth: true,
      data: []   //从后台动态获取
    }
  ]
}

  export default {
    data() {
      return {
        admin: Cookies.get('admin') ? JSON.parse(Cookies.get('admin')) : {},
        lineBox: null,
        timeRange: 'week',
        options: [
          {label: '最近一周', value: 'week'},
          {label: '最近一个月', value: 'month'},
          {label: '最近两个月', value: 'month2'},
          {label: '最近三个月', value: 'month3'},
        ]
      }
    },
    mounted() {  // 等页面元素全部初始化好才开始加载mounth()函数
      this.load()
    },
    methods: {
      load() {
        if (!this.lineBox) {
          this.lineBox = echarts.init(document.getElementById('line'))  //初始化echarts容器
        }
        //从后台获取数据
        request.get('/borrow/lineCharts/' + this.timeRange).then(res => {
          option.xAxis.data = res.data.date
          option.series[0].data = res.data.borrow
          option.series[1].data = res.data.retur
          this.lineBox.setOption(option)  //设置容器的属性值,当数据重新发生变化时,一定要重新setOption()
        })
      }
    }
  }
</script>

<style>
.input {
  width: 300px;
}
</style>

1、导入echarts

import * as echarts from 'echarts'

2、原始的option代码

option = {
  title: {
    text: 'Stacked Line'
  },
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  toolbox: {
    feature: {
      saveAsImage: {}
    }
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      name: 'Email',
      type: 'line',
      stack: 'Total',
      data: [120, 132, 101, 134, 90, 230, 210]
    },
    {
      name: 'Union Ads',
      type: 'line',
      stack: 'Total',
      data: [220, 182, 191, 234, 290, 330, 310]
    },
    {
      name: 'Video Ads',
      type: 'line',
      stack: 'Total',
      data: [150, 232, 201, 154, 190, 330, 410]
    },
    {
      name: 'Direct',
      type: 'line',
      stack: 'Total',
      data: [320, 332, 301, 334, 390, 330, 320]
    },
    {
      name: 'Search Engine',
      type: 'line',
      stack: 'Total',
      data: [820, 932, 901, 934, 1290, 1330, 1320]
    }
  ]
};

3、修改

目录:

text: '图书借还统计

折线:

 legend: {
    data: ['借书数量', '还书数量']
  },

横坐标:

  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: []
  },

纵坐标:

  yAxis: {
    type: 'value'
  },

series(与相应折线legend对应)

series: [
    {
      name: '借书数量',
      type: 'line',
      stack: 'Total',
      smooth: true,
      data: []
    },
    {
      name: '还书数量',
      type: 'line',
      stack: 'Total',
      smooth: true,
      data: []
    }
  ]

4、定义echart图标对应的dom元素
html

    <el-card>
      <div id="line" style="width: 100%; height: 400px"></div>
    </el-card>

在这里插入图片描述在这里插入图片描述5、定义echarts容器
js

    data() {
      return {
        lineBox: null,
      }
    }

6、根据时间范围加载最新的数据
html

    <div style="margin: 20px 0">
      <el-select class="input" v-model="timeRange" placeholder="请选择" @change="load">
        <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
        </el-option>
      </el-select>
    </div>

js

    mounted() {  // 等页面元素全部初始化好才开始加载mounth()函数
      this.load()
    },
    methods: {
      load() {
        if (!this.lineBox) {
          this.lineBox = echarts.init(document.getElementById('line'))  //初始化echarts容器
        }
        //从后台获取数据
        request.get('/borrow/lineCharts/' + this.timeRange).then(res => {
          option.xAxis.data = res.data.date
          option.series[0].data = res.data.borrow
          option.series[1].data = res.data.retur
          this.lineBox.setOption(option)  //设置容器的属性值,当数据重新发生变化时,一定要重新setOption()
        })
      }
    }

三、后端(SpringBoot+MyBatis)

1、请求接口
在这里插入图片描述2、返回前端的数据
在这里插入图片描述

BorrowController.java

    //timeRange:week、month、month2、month3
    @GetMapping("/lineCharts/{timeRange}")
    public Result lineCharts(@PathVariable String timeRange) {
        return Result.success(borrowService.getCountByTimeRange(timeRange));
    }

IBorrowService.java

Map<String, Object> getCountByTimeRange(String timeRange);

BorrowService.java

导入
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;

Java工具类库Hutool 提供的方法:
DateUtil.rangeToList() 返回从开始时间到结束时间的一个时间范围 返回类型 List < DateTime >
DateUtil.offsetDay() 计算时间的一个工具方法 返回类型 DateTime

通过自定义函数 datetimeToDateStr()DateTime类型 的 List 转换成一个 String类型 的 List
原因是前端里 “data”:[ ]、“return”:[ ]、“borrow”:[ ] 数组存储的是String类型的元素
在这里插入图片描述

    @Override
    public Map<String, Object> getCountByTimeRange(String timeRange) {
        Map<String, Object> map = new HashMap<>();
        Date today = new Date();
        List<DateTime> dateRange;
        switch (timeRange) {
            case "week":
                dateRange = DateUtil.rangeToList(DateUtil.offsetDay(today, -6), today, DateField.DAY_OF_WEEK);
                break;
            case "month":
                dateRange = DateUtil.rangeToList(DateUtil.offsetDay(today, -29), today, DateField.DAY_OF_MONTH);
                break;
            case "month2":
                dateRange = DateUtil.rangeToList(DateUtil.offsetDay(today, -59), today, DateField.DAY_OF_MONTH);
                break;
            case "month3":
                dateRange = DateUtil.rangeToList(DateUtil.offsetDay(today, -89), today, DateField.DAY_OF_MONTH);
                break;
            default:
                dateRange = new ArrayList<>();
        }
        List<String> dateStrRange = datetimeToDateStr(dateRange);
        map.put("date", dateStrRange); // x轴的时间日期数据生成完毕
        //1 borrow  2 retrun
        //getCountByTimeRange:不会统计数据库没有的日期,比如没有2022.11.4,他不会返回 **data=2022-11-04,count=0**
        List<BorrowReturCountPO> borrowCount = borrowMapper.getCountByTimeRange(timeRange, 1);
        List<BorrowReturCountPO> returnCount = borrowMapper.getCountByTimeRange(timeRange, 2);
        map.put("borrow", countList(borrowCount, dateStrRange));
        map.put("retur", countList(returnCount, dateStrRange));
        return map;
    }

注意:
getCountByTimeRange sql语句:不会统计数据库没有的日期,比如没有2022.11.4,他不会返回 data=2022-11-04,count=0 这个数据,所以又写countList()函数对在统计数据库时其中不存在的数据进行处理

datetimeToDateStr()函数

把 DateTime类型 的 List 转换成一个 String类型 的 List

    private List<String> datetimeToDateStr(List<DateTime> dateTimeList) {
        List<String> list = CollUtil.newArrayList();
        if (CollUtil.isEmpty(dateTimeList)) {
            return list;
        }
        for (DateTime dateTime : dateTimeList) {
            String date = DateUtil.formatDate(dateTime);
            list.add(date);
        }
        return list;
    }

countList()函数

1、对在统计数据库时其中不存在的数据进行处理
2、.map(BorrowReturCountPO::getCount) 取出对象里的count值
3、有就取出,没有就.orElse(0)对没匹配的数据返回 0

    private List<Integer> countList(List<BorrowReturCountPO> countPOList, List<String> dateRange) {
        List<Integer> list = CollUtil.newArrayList();
        if (CollUtil.isEmpty(countPOList)) {
            return list;
        }
        for (String date : dateRange) {
            Integer count = countPOList.stream().filter(countPO -> date.equals(countPO.getDate()))
                    .map(BorrowReturCountPO::getCount).findFirst().orElse(0);
            list.add(count);
        }
       /*    "date": [
                    "2023-06-01",
                    "2023-06-02",
                    "2023-06-03",
                    "2023-06-04",
                    "2023-06-05",
                    "2023-06-06",
                    "2023-06-07"
        ],
            "retur": [
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    2
        ],
            "borrow": [
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    3
        ]*/
        return list;
    }

BorrowReturCountPO(自定义类封装)

@Data
public class BorrowReturCountPO {
    private String date;
    private Integer count;
}

BorrowMapper.java

    List<BorrowReturCountPO> getCountByTimeRange(@Param("timeRange") String timeRange, @Param("type") int type);  // 1 borrow  2 return

Borrow.xml

1、DATE_FORMAT(createtime,‘%Y-%m-%d’) :把DateTime类型的数据格式化为 yyyy-MM-dd
2、getCountByTimeRange sql语句:如果是1查 borrow表,2查 return表
3、DATE_SUB(NOW(),INTERVAL 1 WEEK) :数据库进行时间计算的函数(对当前的时间减去一周)

    <select id="getCountByTimeRange" resultType="com.example.springboot.mapper.po.BorrowReturCountPO">
        select count(id) as count, DATE_FORMAT(createtime,'%Y-%m-%d') as date from
        <if test="type == 1">
            borrow
        </if>
        <if test="type == 2">
            retur
        </if>
        where
        <choose>
            <when test="timeRange == 'week'">
                createtime >=  DATE_SUB(NOW(),INTERVAL 1 WEEK)
            </when>
            <when test="timeRange == 'month'">
                createtime >=  DATE_SUB(NOW(),INTERVAL 1 MONTH)
            </when>
            <when test="timeRange == 'month2'">
                createtime >=  DATE_SUB(NOW(),INTERVAL 2 MONTH)
            </when>
            <when test="timeRange == 'month3'">
                createtime >=  DATE_SUB(NOW(),INTERVAL 3 MONTH)
            </when>
            <otherwise>
                createtime > now()
            </otherwise>
        </choose>
        group by date
    </select>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/620682.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同样是产品经理 段位差别大

同样是产品经理&#xff0c;段位差别大 趣讲大白话&#xff1a;做人的差距大 【趣讲信息科技189期】 **************************** 市场越内卷 对产品的要求越来越高 不管叫不叫产品经理这个头衔 产品开发的重要性不会降低 《人人都是产品经理》总结的段位 姑且一看&#xff…

java线程多线程并发

文章目录 对java线程的认识wait&#xff08;&#xff09;和sleep&#xff08;&#xff09;区别&#xff1f;wait&#xff0c;notify为什么要放在同步代码块中&#xff1f; 多线程**什么时候使用多线程**&#xff1a;**多线程的优缺点**&#xff1a;**线程安全问题**&#xff1a…

MATLAB应用

目录 网站 智能图像色彩缩减和量化 网站 https://yarpiz.com/ 智能图像色彩缩减和量化 使用智能聚类方法&#xff1a;&#xff08;a&#xff09;k均值算法&#xff0c;&#xff08;b&#xff09;模糊c均值聚类&#xff08;FCM&#xff09;和&#xff08;c&#xff09;自组织神…

Mysql—存储过程

简介 存储过程就是类似于MySQL触发器&#xff0c;经过事先编写好相应语句&#xff0c;通过编译后存储在数据库上。触发器不需要手动调用即可实现相应SQL功能。MySQL存储过程&#xff0c;需要自己去调用得到相应的结果。 语法 创建存储过程 CREATE DEFINER CURRENT_USER PR…

git---->团队开发神器,一篇文章直接掌握

git---->团队开发神器&#xff0c;一篇文章直接掌握 一 学习git的原因概念版本的概念1 版本控制软件的基础功能2 集中式版本控制软件3 分布式版本控制 二 git的安装三 GitHub Desktop的使用四 团队操作五 中央服务器--github从github上下载文件到本地仓库传输文件 六 国内中…

chatgpt赋能python:Python如何实现自增

Python如何实现自增 在Python编程中&#xff0c;自增是一种非常常用的操作&#xff0c;它可以让我们在循环、计数等场景中更加方便地进行操作。实际上&#xff0c;在Python中&#xff0c;实现自增非常简单&#xff0c;本文将介绍Python中常用的自增操作&#xff0c;并分享自增…

时间复杂度 空间复杂度

概览 时间复杂度与空间复杂度的作用是在衡量一个算法的优劣性&#xff0c;以及在二者之间进行权衡&#xff0c;寻找二者的平衡点。 时间复杂度是指执行算法所需时间的增长率&#xff0c;而空间复杂度则是指执行算法所需存储空间的增长率。 高时间复杂度的算法可能需要在短时间…

LayUI前框框架普及版

LayUI 一、课程目标 1. 【了解】LayUI框架 2. 【理解】LayUI基础使用 3. 【掌握】LayUI页面元素 4. 【掌握】LayUI内置模块二、LayUI基本使用 2.1 概念 layui&#xff08;谐音&#xff1a;类UI) 是一款采用自身模块规范编写的前端 UI 框架&#xff0…

Nginx+Tomcat 负载均衡、动静分离

目录 一、Nginx代理服务器概念 1.正向代理 2.反向代理 二、动静分离 三、负载均衡 四、Nginx七层代理实验 1.部署Nginx服务 2. 部署Tomcat服务 2.1在192.168.88.50 虚拟机上部署双实例 2.2在192.168.88.60 上部署Tomcat服务器3 3.动静分离配置 3.1Tomcat1 server 配…

RecyclerView的回收缓存均由内部类Recycler完成

1. RecyclerView的三级缓存 通常在RecyclerView中存在着四级缓存&#xff0c;从低到高分别为&#xff1a; 可直接重复使用的临时缓存&#xff08;mAttachedScrap/mChangedScrap&#xff09; mAttachedScrap中缓存的是屏幕中可见范围的ViewHoldermChangedScrap只能在预布局状态…

Material—— 常用材质节点

目录 Coordinates Absolute World Position Actor Position Object Position Utility SphereMask Coordinates 表示坐标类的节点&#xff1b; Absolute World Position 别名为WorldPosition&#xff0c;此节点输出当前像素在世界空间内的位置&#xff1b;常用于查找相机到…

作为过来人:有什么话想对当年高考前的自己说

目录 引言千人千面-有什么话想对当年高考前的自己说怀念高中&#xff0c;数学太难多考一分&#xff0c;人生就会不一样一定要勇敢&#xff0c;不止高考别把高考不当回事6的我没话说想到啥就去做别选**大学/专业强烈想出名的拖鞋哥英语全选C&#xff0c;理综要细心会的全做对当时…

Spring - 注解开发

文章目录 Spring的注解开发一、Bean 基本注解开发1.1 Component Bean的配置1.2 其他注解配置Bean1.3 Component 衍生注解 二、Bean依赖注入注解开发2.1 Value2.2 Autowired2.3 Qualifier2.4 Resource 三、非自定义注解开发3.1 无参非自定义注解开发3.2 有参非自定义注解开发 四…

Domino 14新内核

大家好&#xff0c;才是真的好。 还记得去年&#xff0c;我们不断跟进而放出的Notes/Domino产品路线图吗&#xff1f;是的&#xff0c;HCL正在按照产品路线图稳步推进&#xff0c;而很多人提出的idea&#xff0c;也逐步加入到产品中&#xff0c;等会我们也会聊到。 我最喜欢这…

MySQL安装-Linux版

MySQL-Linux版安装 1、准备一台Linux服务器 云服务器或者虚拟机都可以&#xff1b; Linux的版本为 CentOS7&#xff1b; 2、 下载Linux版MySQL安装包 下载地址 3、上传MySQL安装包 使用FinalShell软件上传即可&#xff01; 4、 创建目录,并解压 mkdir mysqltar -xvf my…

【Web服务器】Nginx网站服务

文章目录 一、Nginx 概述1.什么是 Nginx2.Nginx 的特点3.Nginx 应用场景 二、Nginx 服务基础1.编译安装 Nginx 服务1.1 布置环境1.2 安装依赖包1.3 创建运行用户、组1.4 编译安装 2.Nginx 的运行控制2.1 检查配置文件2.2 启动、停止 Nginx2.3 日志分割以及升级 Nginx 服务2.4 添…

调用腾讯API实现图片滤镜

目录 1. 作者介绍2. 图像滤波介绍3. 实验过程及结果&#xff08;附完整代码&#xff09;3.1 准备工作3.2 实验代码3.3 实验结果 1. 作者介绍 班梦威&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;模式识别与人工智能 电子…

企业如何有效制定企业信息化发展规划?(附信息化模板)

如何有效制定企业信息化发展规划&#xff1f;企业信息化发展规划是一个宏大而又复杂的命题&#xff0c;这篇来掰开揉碎讲一下企业应该如何有效制定信息化发展规划。 这里不给大家灌鸡汤&#xff0c;也不给大家画大饼&#xff0c;就说些实在的。 如果你想找经验方法&#xff0…

Lambda表达式与函数式编程

文章目录 函数式编程——Stream流概述为什么学?函数式编程思想 Lambda表达式概述Lambda表达式的前身省略规则 Stream流概述案例数据准备创建流中间操作终结操作reduce归并注意事项 Optional概述创建对象安全消费值获取值安全获取值过滤数据转换 函数式接口常用的默认方法 方法…

APPSCAN扫描https协议的网站证书安装过程(Googel浏览器)

【1】首先打开我们的appscan,点击外部设备。 【2】点击记录代理配置 【3】弹出选项后&#xff0c;在记录代理下我们可以看到AppScan SSL证书&#xff0c;这点我们点击导出 【4】这里你选择一个合适的位置&#xff0c;点击保存 【5】保存后的文件是一个zip压缩包&#xff0c;…