代码已上传至码云:echarts_boot: echarts使用demo
ECharts是一个使用 JavaScript 实现的"数据可视化"库, 它可以流畅的运行在 PC 和移动设备上
什么是数据可视化?
也就是可以将数据通过图表的形式展示出来,
Echarts官网:Apache ECharts
本篇文章以此柱状图为例:
数据库中分别有学生表、课程表、成绩表三张表
使用echarts对 某科目全班平均分近三年变化、某个人总分数变化、某人某年各科成绩作统计和可视化操作
表结构如下:
/*
Navicat Premium Data Transfer
Source Server : CloudShell
Source Server Type : MySQL
Source Server Version : 50736 (5.7.36)
Source Host : 124.70.69.186:13306
Source Schema : echarts_test
Target Server Type : MySQL
Target Server Version : 50736 (5.7.36)
File Encoding : 65001
Date: 01/07/2023 15:44:13
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`cou_num` int(11) DEFAULT NULL COMMENT '课程号',
`cou_name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '课程名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='课程表';
-- ----------------------------
-- Records of course
-- ----------------------------
BEGIN;
INSERT INTO `course` (`id`, `cou_num`, `cou_name`) VALUES (1, 1, '语文');
INSERT INTO `course` (`id`, `cou_num`, `cou_name`) VALUES (2, 2, '数学');
INSERT INTO `course` (`id`, `cou_num`, `cou_name`) VALUES (3, 3, '英语');
COMMIT;
-- ----------------------------
-- Table structure for score
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`cou_num` int(11) NOT NULL COMMENT '课程号',
`stu_num` int(11) NOT NULL COMMENT '学号',
`score` int(11) DEFAULT NULL COMMENT '成绩',
`time` timestamp NULL DEFAULT NULL COMMENT '时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='成绩表';
-- ----------------------------
-- Records of score
-- ----------------------------
BEGIN;
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (1, 1, 1, 90, '2023-06-30 09:57:19');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (2, 2, 1, 88, '2023-06-30 09:57:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (3, 3, 1, 95, '2023-06-30 09:57:42');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (4, 1, 2, 70, '2023-06-30 09:57:54');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (5, 2, 2, 99, '2023-06-30 09:58:04');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (6, 3, 2, 60, '2023-06-30 09:58:12');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (7, 1, 3, 56, '2023-06-30 09:58:20');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (8, 2, 3, 32, '2023-06-30 09:58:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (9, 3, 3, 43, '2022-06-30 09:58:48');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (10, 1, 1, 88, '2022-06-30 09:57:19');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (11, 2, 1, 86, '2022-06-30 09:57:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (12, 3, 1, 93, '2022-06-30 09:57:42');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (13, 1, 2, 70, '2022-06-30 09:57:54');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (14, 2, 2, 99, '2022-06-30 09:58:04');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (15, 3, 2, 60, '2022-06-30 09:58:12');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (16, 1, 3, 56, '2022-06-30 09:58:20');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (17, 2, 3, 32, '2022-06-30 09:58:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (18, 3, 3, 43, '2022-06-30 09:58:48');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (19, 1, 1, 86, '2021-06-30 09:57:19');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (20, 2, 1, 84, '2021-06-30 09:57:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (21, 3, 1, 91, '2021-06-30 09:57:42');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (22, 1, 2, 70, '2021-06-30 09:57:54');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (23, 2, 2, 99, '2021-06-30 09:58:04');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (24, 3, 2, 60, '2021-06-30 09:58:12');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (25, 1, 3, 56, '2021-06-30 09:58:20');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (26, 2, 3, 32, '2021-06-30 09:58:31');
INSERT INTO `score` (`id`, `cou_num`, `stu_num`, `score`, `time`) VALUES (27, 3, 3, 43, '2021-06-30 09:58:48');
COMMIT;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`stu_num` int(11) NOT NULL COMMENT '学号',
`stu_name` varchar(255) COLLATE utf8mb4_bin NOT NULL COMMENT '姓名',
`stu_sex` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='学生表';
-- ----------------------------
-- Records of student
-- ----------------------------
BEGIN;
INSERT INTO `student` (`id`, `stu_num`, `stu_name`, `stu_sex`) VALUES (1, 1, '张三', '男');
INSERT INTO `student` (`id`, `stu_num`, `stu_name`, `stu_sex`) VALUES (2, 2, '李四', '女');
INSERT INTO `student` (`id`, `stu_num`, `stu_name`, `stu_sex`) VALUES (3, 3, '王五', '男');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
mysql、mybaits-plus和lombok
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
3.4.0
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
mysql
mysql-connector-java
8.0.11
junit
junit
4.13.1
test
server:
port: 18889
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/echarts_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&AllowPublicKeyRetrieval=True&useSSL=false
username: root
password: root
mybatis-plus:
mapper-locations: mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
type-aliases-package: com.crazyk.echartsboot.bo
以学生实体为例
实体类
package com.crazyk.echartsboot.bo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @program: EchartsBoot
* @description: 学生实体
* @author: CrazyK
* @create: 2023-06-30 10:02
**/
@Data
@TableName("student")
public class Student {
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 学号
*/
private Integer stuNum;
/**
* 姓名
*/
private String stuName;
/**
* 性别
*/
private String StuSex;
}
mapper接口
package com.crazyk.echartsboot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.crazyk.echartsboot.bo.Student;
import org.apache.ibatis.annotations.Mapper;
/**
* @program: EchartsBoot
* @description: 学生接口
* @author: CrazyK
* @create: 2023-06-30 10:08
**/
@Mapper
public interface StudentMapper extends BaseMapper {
}
service实现类
package com.crazyk.echartsboot.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crazyk.echartsboot.bo.Student;
import com.crazyk.echartsboot.mapper.StudentMapper;
import org.springframework.stereotype.Service;
/**
* @program: EchartsBoot
* @description: 学生服务
* @author: CrazyK
* @create: 2023-06-30 10:10
**/
@Service
public class StudentService extends ServiceImpl {
}
controller控制类
package com.crazyk.echartsboot.controller;
import com.crazyk.echartsboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
/**
* @program: EchartsBoot
* @description: 学生控制层
* @author: CrazyK
* @create: 2023-06-30 10:12
**/
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
}
mapper.xml
博主太懒了,不想写sql,所以用的stream
package com.crazyk.echartsboot.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.crazyk.echartsboot.bo.Course;
import com.crazyk.echartsboot.bo.Score;
import com.crazyk.echartsboot.bo.Student;
import com.crazyk.echartsboot.service.CourseService;
import com.crazyk.echartsboot.service.ScoreService;
import com.crazyk.echartsboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
import java.util.stream.Collectors;
/**
* @program: EchartsBoot
* @description: 成绩控制层
* @author: CrazyK
* @create: 2023-06-30 10:14
**/
@RestController
@RequestMapping("/score")
public class ScoreController {
@Autowired
private ScoreService scoreService;
@Autowired
private CourseService courseService;
@Autowired
private StudentService studentService;
/**
* 某科目全班平均分 近三年变化
*/
@RequestMapping("avg")
public Map avg(String couName){
Integer couNum = courseService.getOne(new QueryWrapper().eq("cou_name", couName))
.getId();
Map> map = scoreService.list(new QueryWrapper().eq("cou_num", couNum))
.stream()
.collect(Collectors.groupingBy(s -> s.getTime().toString().substring(24)));
Map res = new HashMap<>();
for (String key : map.keySet()){
Double average = map.get(key).stream()
.map(s -> s.getScore())
.mapToInt(Integer::valueOf)
.average().orElse(0D);
Integer score = Integer.valueOf(String.valueOf(average).substring(0,2));
res.put(key,score);
}
System.out.println(res);
return res;
}
/**
* 某个人总分数变化
*/
@RequestMapping("sum")
public Map sum(String stuName){
Integer stuNum = studentService.getOne(new QueryWrapper().eq("stu_name",stuName)).getStuNum();
Map> map = scoreService.list(new QueryWrapper().eq("stu_num", stuNum))
.stream()
.collect(Collectors.groupingBy(s -> s.getTime().toString().substring(24)));
Map res = new HashMap<>();
for (String key : map.keySet()){
Integer sum = map.get(key).stream()
.map(s -> s.getScore())
.mapToInt(Integer::valueOf)
.sum();
res.put(key,sum);
}
System.out.println(res);
return res;
}
/**
* 某人某年各科成绩
*/
@RequestMapping("own")
public Map own(String stuName,String year){
Integer stuNum = studentService.getOne(new QueryWrapper().eq("stu_name",stuName)).getStuNum();
Map> map = scoreService.list(new QueryWrapper().eq("stu_num", stuNum))
.stream()
.filter(s -> s.getTime().toString().substring(24).equals(year))
.collect(Collectors.groupingBy(s -> s.getCouNum()));
Map res = new HashMap<>();
for (Integer key : map.keySet()){
String couName = courseService.getOne(new QueryWrapper().eq("cou_num",map.get(key).get(0).getCouNum())).getCouName();
Integer score = map.get(key).get(0).getScore();
res.put(couName,score);
}
System.out.println(res);
return res;
}
}
测试一下刚才写的三个接口
测试没问题就可以开始写前端了
我创建的是vue2
vue create 项目名
部署成功后安装需要的依赖
npm install vue-router --save #vueRouter
npm i element-ui -S #element-ui
npm install echarts -S #echarts
npm install axios #axios
在main.js全局引入,这是vue项目的入口
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import * as echarts from "echarts";
import {postRequest} from "@/utils/api";
import {getRequest} from "@/utils/api";
import {putRequest} from "@/utils/api";
import {deleteRequest} from "@/utils/api";
Vue.config.productionTip = false
Vue.use(ElementUI,{size:'small'});
Vue.prototype.$echarts = echarts;
new Vue({
router,
render: h => h(App),
}).$mount('#app')
在vue.config.js文件中添加代理,使请求转发到后端端口
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
})
let proxyObj = {}
proxyObj['/'] = {
//websocket
ws: false,
//目标地址
target: 'http://localhost:18889',
changeOrigin: true,
pathRewrite: {
'^/': '/'
}
};
module.exports = defineConfig({
transpileDependencies: true,
devServer:{
host: 'localhost',
port: 8080,
proxy: proxyObj
}
})
api.js用于封装请求
import axios from "axios";
let base = '';
//json格式post请求
export const postRequest = (url,params) => {
return axios({
method: 'post',
url: base + url,
data:params
})
}
//put请求
export const putRequest = (url,params) => {
return axios({
method: 'put',
url:base + url,
data:params
})
}
//get请求
export const getRequest = (url,params) => {
return axios({
method: 'get',
url:base + url,
data:params
})
}
//delete请求
export const deleteRequest = (url,params) => {
return axios({
method: 'delete',
url:base + url,
data:params
})
}
然后在main.js中引入请求封装
//插件形式使用请求
Vue.prototype.postRequest = postRequest;
Vue.prototype.getRequest = getRequest;
Vue.prototype.putRequest = putRequest;
Vue.prototype.deleteRequest = deleteRequest;
请输入年份
请输入学生姓名
请输入学生姓名
请输入科目名称
this.titleEcharts