数据可视化插件echarts【前端】

数据可视化插件echarts【前端】

  • 前言
  • 版权
  • 开源
  • 推荐
  • 数据可视化插件echarts
    • 一、如何使用
      • 1.1 下载
      • 1.2 找到js文件
      • 1.3 入门使用
      • 1.4 我的使用
    • 二、前后端交互:入门demo
      • 2.1 前端
        • html
        • js
      • 2.2 后端
        • entity
        • controller
        • service
        • mapper
    • 三、前后端交互:动态数据
      • 3.1 前端
        • js
      • 3.2 后端
        • service
    • 四、前后端交互:动态数据
      • 4.1 前端
        • js
      • 4.2 后端
        • ChineseName注解
        • EldData
        • DataService
    • 五、测试扩展性
      • 5.0 开发说明
      • 5.1 测试结果
      • 5.2 Eld多加一个属性
      • 5.3 加入测试数据
    • 六、注解优化
      • 6.0 开发说明
      • 6.1 测试结果
      • 6.2 前端
      • 6.2 后端
        • ChineseName
        • EldData
        • DataService
    • 七、实际项目开发
      • EldData
      • Constant
      • 测试数据
  • 最后

前言

2024-4-12 16:08:09

以下内容源自《【前端】》
仅供学习交流使用

版权

禁止其他平台发布时删除以下此话
本文首次发布于CSDN平台
作者是CSDN@日星月云
博客主页是https://jsss-1.blog.csdn.net
禁止其他平台发布时删除以上此话

开源

日星月云 / echarts数据可视化

v1:二、入门demo
v2:三、动态数据
v3:四、动态数据
v4:六、注解优化
v5:七、项目开发

推荐

echarts入门教程(超级详细带案例)

数据可视化插件echarts

一、如何使用

1.1 下载

(1)从 npm 获取
npm install echarts --save
(2)从 CDN 获取
(3)从 GitHub 获取

1.2 找到js文件

在这里插入图片描述

node_modules\echarts\dist中找到
echart.jsecharts.min,js

在这里插入图片描述

1.3 入门使用

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><!-- 01 导入js --><script src="js/echarts.js"></script><!-- 03 设置容器的样式 --><style>#container{width: 800px;height: 600px;}</style></head><body><!-- 02 创建个容器 --><div id="container"></div></body><script>//04 实例化echarts// 4.1 创建一个实例var echart = echarts.init(document.getElementById("container"))// 4.2 定义配置项var option = {// 图表的标题title:{text:"我的第一个图表"},// 图表的提示tooltip:{},// 图例legend:{data:["睡眠时长"]},// x轴线xAxis:{data:["周一","周二","周三","周四","周五","周六","周日"]},// y轴线yAxis:{},// 设置数据series:[{// 数据名称name:"睡眠时长",// 类型为柱状图type:"bar",// 数据datadata:[8,10,4,5,9,4,8]}]}// 4.3 更新配置echart.setOption(option);// chart图表,set设置 Option选项  data数据 type类型 bar条(柱状条),series系列(数据) Axis轴线 xAxis水平轴线// legend传奇(图例) tooltip 提示 init初始化 document文档</script></html>

1.4 我的使用

下面的代码根据此代码修改

https://www.isqqw.com/?t=line

在这里插入图片描述

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><!-- 01 导入js --><script src="js/echarts.js"></script><!-- 03 设置容器的样式 --><style>#container{width: 800px;height: 600px;}</style></head><body><!-- 02 创建个容器 --><div id="container"></div></body><script>//实例化echarts// 1 创建一个实例var echart = echarts.init(document.getElementById("container"));let data1 = [175, 160, 153, 121, 156]let data2 = [200, 140, 205, 162, 175]let data3 = []let data4 = ['13:00', '14:00', '15:00', '16:00', '17:00']data1.forEach((item1,index)=>{if(item1>data2[index]){data3.push({yAxis: item1,  //标注的Y轴位置xAxis: data4[index], //标注的X轴位置value: item1  //标注的value值})}else{data3.push({yAxis: data2[index],  //标注的Y轴位置xAxis: data4[index], //标注的X轴位置value: data2[index]  //标注的value值})}})// 2 定义配置项var option = {backgroundColor: 'white',grid: {top: '20%',left: '5%',right: '5%',bottom: '8%',containLabel: true},tooltip: {trigger: 'axis',borderWidth: 1,axisPointer: {type: 'shadow'},extraCssText: 'z-index:2'},legend: [{top: 'top',left: 'center',orient: 'horizontal',data: ['进水量', '出水量'],itemWidth: 15,itemHeight: 10,itemGap: 15,borderRadius: 4,textStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 400}}],xAxis: {type: 'category',data: data4,axisLine: {show: false},axisTick: {show: false},axisLabel: {show: true,textStyle: {color: '#393939' //X轴文字颜色}}},yAxis: [{type: 'value',name: '',nameTextStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 600// padding: [0, 0, 0, 40], // 四个数字分别为上右下左与原位置距离},nameGap: 30,  // 表现为上下位置axisLine: {show: true,lineStyle: {color: '#eeeeee'}},axisTick: {show: false},axisLabel: {color: '#393939',fontSize: 14},splitLine: {show: true,lineStyle: {color: '#eeeeee'}}}],series: [{name: '进水量',type: 'line',showAllSymbol: true, //显示所有图形。//标记的图形为实心圆symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: '#5470c6',normal: {color: '#5470c6'//拐点颜色}},lineStyle: {color: '#5470c6'},markPoint:{data: data3},data: data1},{name: '出水量',type: 'line',showAllSymbol: true, //显示所有图形。symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: '#91cc75',normal: {color: '#91cc75'//拐点颜色}},lineStyle: {color: '#91cc75'},data: data2}]}// 3 更新配置echart.setOption(option);</script></html>

二、前后端交互:入门demo

2.1 前端

html
		<div class="data-container"></div>
js
$(document).ready(function () {list();});function list() {$.ajax({type: "GET",url: SERVER_PATH + "/data/list",xhrFields: {withCredentials: true},success: function (result) {if (result.status) {alertBox(result.data.message);return false;}init(result.data);}});
}function init(dataLists) {//实例化echarts// 1 创建一个实例var echart = echarts.init(document.querySelector(".data-container"));//进水量let data1 = dataLists.inWaterList;//出水量let data2 = dataLists.outWaterList;//标注let data3 = []//横轴时间let data4 = dataLists.dateList;data1.forEach((item1, index) => {if (item1 > data2[index]) {data3.push({yAxis: item1,  //标注的Y轴位置xAxis: data4[index], //标注的X轴位置value: item1  //标注的value值})} else {data3.push({yAxis: data2[index],  //标注的Y轴位置xAxis: data4[index], //标注的X轴位置value: data2[index]  //标注的value值})}})// 2 定义配置项var option = {backgroundColor: 'white',grid: {top: '20%',left: '5%',right: '5%',bottom: '8%',containLabel: true},tooltip: {trigger: 'axis',borderWidth: 1,axisPointer: {type: 'shadow'},extraCssText: 'z-index:2'},legend: [{top: 'top',left: 'center',orient: 'horizontal',data: ['进水量', '出水量'],itemWidth: 15,itemHeight: 10,itemGap: 15,borderRadius: 4,textStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 400}}],xAxis: {type: 'category',data: data4,axisLine: {show: false},axisTick: {show: false},axisLabel: {show: true,textStyle: {color: '#393939' //X轴文字颜色}}},yAxis: [{type: 'value',name: '',nameTextStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 600// padding: [0, 0, 0, 40], // 四个数字分别为上右下左与原位置距离},nameGap: 30,  // 表现为上下位置axisLine: {show: true,lineStyle: {color: '#eeeeee'}},axisTick: {show: false},axisLabel: {color: '#393939',fontSize: 14},splitLine: {show: true,lineStyle: {color: '#eeeeee'}}}],series: [{name: '进水量',type: 'line',showAllSymbol: true, //显示所有图形。//标记的图形为实心圆symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: '#5470c6',normal: {color: '#5470c6'//拐点颜色}},lineStyle: {color: '#5470c6'},markPoint: {data: data3},data: data1},{name: '出水量',type: 'line',showAllSymbol: true, //显示所有图形。symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: '#91cc75',normal: {color: '#91cc75'//拐点颜色}},lineStyle: {color: '#91cc75'},data: data2}]}// 3 更新配置echart.setOption(option);}

2.2 后端

entity
@lombok.Data
@NoArgsConstructor
@AllArgsConstructor
public class Data {Integer InWater;Integer OutWater;Date date;
}
controller
    @GetMapping("/list")public ResponseModel getDataList(){HashMap<String, Object> search = dataService.searchMap();return new ResponseModel(search);}
service
	public HashMap<String,Object> searchMap(){HashMap<String,Object> map=new HashMap<>();List<Data> dataList = search();List<Integer> inWaterList = new ArrayList<>();List<Integer> outWaterList = new ArrayList<>();List<Date> dateList = new ArrayList<>();for(Data data : dataList){inWaterList.add(data.getInWater());outWaterList.add(data.getOutWater());dateList.add(data.getDate());}map.put("inWaterList",inWaterList);map.put("outWaterList",outWaterList);map.put("dateList",dateList);return map;}public List<Data> search() {return dataDao.list();}
mapper
@Select("SELECT * FROM test limit 20")List<Data> list();

三、前后端交互:动态数据

在这里插入图片描述

3.1 前端

js
$(document).ready(function () {list();});function list() {$.ajax({type: "GET",url: SERVER_PATH + "/data/list",data: {userId: 1},xhrFields: {withCredentials: true},success: function (result) {if (result.status) {alertBox(result.data.message);return false;}init(result.data);}});
}function init(dataLists) {//实例化echarts// 1 创建一个实例var echart = echarts.init(document.querySelector(".data-container"));//进水量let data1 = dataLists.rate1;//出水量let data2 = dataLists.rate2;//横轴时间let data4 = dataLists.date;//标注数据let data3 = [];//只需修改以下对应let names=["rate1","rate2"];let datas=[data1,data2];let colors=['#5470c6','#91cc75']//动态生成下面的数据for(let i=0;i<names.length;i++){data3.push([]);}datas.forEach((data, index) => {data.forEach((item, i) => {data3[index].push({yAxis: item,  // 标注的Y轴位置xAxis: data4[i], // 标注的X轴位置value: item  // 标注的value值});});});let seriesData=[];for (var i = 0; i < datas.length; i++) {seriesData.push({name: names[i],type: 'line',showAllSymbol: true, //显示所有图形。//标记的图形为实心圆symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: colors[i],normal: {color: colors[i]//拐点颜色}},lineStyle:{color: colors[i]},markPoint: {data: data3[i]},data: datas[i]});}// 2 定义配置项var option = {backgroundColor: 'white',grid: {top: '20%',left: '5%',right: '5%',bottom: '8%',containLabel: true},tooltip: {trigger: 'axis',borderWidth: 1,axisPointer: {type: 'shadow'},extraCssText: 'z-index:2',// formatter: function(params) {//     var tooltipContent = params[0].name + '<br/>'; // 显示日期//     params.forEach(function(param) {//         tooltipContent += param.seriesName + ': ' + param.value + '<br>';//     });//     return tooltipContent;// }},legend: [{top: 'top',left: 'center',orient: 'horizontal',data: names,itemWidth: 15,itemHeight: 10,itemGap: 15,borderRadius: 4,textStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 400}}],xAxis: {type: 'category',data: data4,axisLine: {show: false},axisTick: {show: false},axisLabel: {show: true,textStyle: {color: '#393939' //X轴文字颜色}}},yAxis: [{type: 'value',name: '',nameTextStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 600// padding: [0, 0, 0, 40], // 四个数字分别为上右下左与原位置距离},nameGap: 30,  // 表现为上下位置axisLine: {show: true,lineStyle: {color: '#eeeeee'}},axisTick: {show: false},axisLabel: {color: '#393939',fontSize: 14},splitLine: {show: true,lineStyle: {color: '#eeeeee'}}}],series: seriesData}// 3 更新配置echart.setOption(option);}

3.2 后端

service
	//返回数据链表public HashMap<String,ArrayList> searchMap(Integer userId){HashMap<String,ArrayList> map=new HashMap<>();List<EldData> dataList = search(userId);List<String> fieldNames = new ArrayList<>();Class<?> dataClass = EldData.class;// 获取 OldData 类的所有属性名Field[] fields = dataClass.getDeclaredFields();for (Field field : fields) {fieldNames.add(field.getName());map.put(field.getName(),new ArrayList<>());}for (EldData data : dataList) {for (String fieldName : fieldNames) {ArrayList<Object> rowData =map.get(fieldName);try {Field field = dataClass.getDeclaredField(fieldName);field.setAccessible(true);rowData.add(field.get(data));} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}map.put(fieldName,rowData);}}return map;}//搜索数据public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 获取分数最高的20个数据return set !=null?new ArrayList<>(set):new ArrayList<>();}

四、前后端交互:动态数据

后端name根据注解ChineseName
前端颜色是随机生成的

在这里插入图片描述
hashMap导致没有顺序,换成LinkedHashMap

在seachMap()中,重新定义

//        HashMap<String,ArrayList> map=new HashMap<>();HashMap<String,ArrayList> map=new LinkedHashMap<>();

在这里插入图片描述
发现它是时间顺序是反这的
修改一下

    //搜索数据
//    public List<EldData> search(Integer userId) {
//        String key= ELD_DATA +userId;
//        Set set = redisTemplate.opsForZSet().reverseRange(key, 0, limit-1);// 获取分数最高的20个数据
//
//        return set !=null?new ArrayList<>(set):new ArrayList<>();
//
//    }//搜索数据public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, limit-1);// 获取分数最高的limit个数据if(set==null){return new ArrayList<>();}ArrayList<EldData> resList = new ArrayList<>(set);Collections.reverse(resList);return resList;}

在这里插入图片描述

4.1 前端

js

变成真实登录的用户
而不是固定userId是1

$(document).ready(function () {list();});function list() {var id=sessionStorage.getItem("id");$.ajax({type: "GET",url: SERVER_PATH + "/data/list",data: {// userId: 1userId: id},xhrFields: {withCredentials: true},success: function (result) {if (result.status) {alertBox(result.data.message);return false;}init(result.data);}});
}function init(dataLists) {//实例化echarts// 1 创建一个实例var echart = echarts.init(document.querySelector(".data-container"));//横轴时间let datax = dataLists.date;//标注数据let data0 = [];//只需修改不需要展示的namevar noNeed=["id","date"];//原始数据的所有namelet keys=Object.keys(dataLists);//只需添加足够的颜色// let colors=[//     '#5470c6','#91cc75'// ]//动态生成下面的数据,不需要修改//随机生成相同数量的颜色let colors=generateRandomColors(keys.length);//名称和对应的数据let names = []let datas = [];keys.forEach((name) => {if(!noNeed.includes(name)){names.push(name);datas.push(dataLists[name]);}});for(let i=0;i<names.length;i++){data0.push([]);}datas.forEach((data, index) => {data.forEach((item, i) => {data0[index].push({yAxis: item,  // 标注的Y轴位置xAxis: datax[i], // 标注的X轴位置value: item  // 标注的value值});});});let seriesData=[];for (var i = 0; i < datas.length; i++) {seriesData.push({name: names[i],type: 'line',showAllSymbol: true, //显示所有图形。//标记的图形为实心圆symbolSize: 8, //标记的大小itemStyle: {//折线拐点标志的样式color: 'white',borderWidth: '2',borderColor: colors[i],normal: {color: colors[i]//拐点颜色}},lineStyle:{color: colors[i]},markPoint: {data: data0[i]},data: datas[i]});}// 2 定义配置项var option = {backgroundColor: 'white',grid: {top: '20%',left: '5%',right: '5%',bottom: '8%',containLabel: true},tooltip: {trigger: 'axis',borderWidth: 1,axisPointer: {type: 'shadow'},extraCssText: 'z-index:2',// formatter: function(params) {//     var tooltipContent = params[0].name + '<br/>'; // 显示日期//     params.forEach(function(param) {//         tooltipContent += param.seriesName + ': ' + param.value + '<br>';//     });//     return tooltipContent;// }},legend: [{top: 'top',left: 'center',orient: 'horizontal',data: names,itemWidth: 15,itemHeight: 10,itemGap: 15,borderRadius: 4,textStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 400}}],xAxis: {type: 'category',data: datax,axisLine: {show: false},axisTick: {show: false},axisLabel: {show: true,textStyle: {color: '#393939' //X轴文字颜色}}},yAxis: [{type: 'value',name: '',nameTextStyle: {color: '#000',fontFamily: 'Alibaba PuHuiTi',fontSize: 14,fontWeight: 600// padding: [0, 0, 0, 40], // 四个数字分别为上右下左与原位置距离},nameGap: 30,  // 表现为上下位置axisLine: {show: true,lineStyle: {color: '#eeeeee'}},axisTick: {show: false},axisLabel: {color: '#393939',fontSize: 14},splitLine: {show: true,lineStyle: {color: '#eeeeee'}}}],series: seriesData}// 3 更新配置echart.setOption(option);}function generateRandomColors(num) {let randomColors = [];let characters = '0123456789ABCDEF';for (let i = 0; i < num; i++) {let color = '#';for (let j = 0; j < 6; j++) {color += characters[Math.floor(Math.random() * 16)];}randomColors.push(color);}return randomColors;
}

4.2 后端

ChineseName注解
package com.jsss.echarts.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ChineseName {String value();
}
EldData
package com.jsss.echarts.entity;import com.jsss.echarts.annotation.ChineseName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;import java.sql.Date;
import java.util.Objects;@Data
@NoArgsConstructor
@AllArgsConstructorpublic class EldData {@ChineseName("id")String id;@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;@ChineseName("date")Date date;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;EldData eldData = (EldData) o;return Objects.equals(id, eldData.id) && Objects.equals(date, eldData.date);}@Overridepublic int hashCode() {return Objects.hash(id, date);}@Overridepublic String toString() {return "EldData{" +"rate1=" + rate1 +", rate2=" + rate2 +", date=" + date +'}';}}
DataService
package com.jsss.echarts.service;import com.jsss.echarts.annotation.ChineseName;
import com.jsss.echarts.entity.EldData;
import com.jsss.utils.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;import java.lang.reflect.Field;
import java.util.*;@Service
public class DataService implements Constant {@AutowiredRedisTemplate redisTemplate;//返回数据链表public HashMap<String,ArrayList> searchMap(Integer userId){
//        HashMap<String,ArrayList> map=new HashMap<>();HashMap<String,ArrayList> map=new LinkedHashMap<>();List<EldData> dataList = search(userId);List<String> fieldNames = new ArrayList<>();Class<?> dataClass = EldData.class;// 获取 OldData 类的所有属性名Field[] fields = dataClass.getDeclaredFields();for (Field field : fields) {fieldNames.add(field.getName());
//            map.put(field.getName(),new ArrayList<>());map.put(field.getAnnotation(ChineseName.class).value(), new ArrayList<>());}for (EldData data : dataList) {for (String fieldName : fieldNames) {
//                ArrayList<Object> rowData = map.get(fieldName);try {Field field = dataClass.getDeclaredField(fieldName);ArrayList<Object> rowData =map.get(field.getAnnotation(ChineseName.class).value());field.setAccessible(true);rowData.add(field.get(data));map.put(field.getAnnotation(ChineseName.class).value(),rowData);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}
//                map.put(fieldName, rowData);}}return map;}//搜索数据
//    public List<EldData> search(Integer userId) {
//        String key= ELD_DATA +userId;
//        Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 获取分数最高的20个数据
//
//        return set !=null?new ArrayList<>(set):new ArrayList<>();
//
//    }//搜索数据public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, limit-1);// 获取分数最高的limit个数据if(set==null){return new ArrayList<>();}ArrayList<EldData> resList = new ArrayList<>(set);Collections.reverse(resList);return resList;}// 将数据存储到有序集合中,分数为日期的时间戳public boolean addData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());}// 更新数据,先删除数据,后增加新数据public boolean updateData(Integer userId,EldData oldData,EldData newData) {long res=removeData(userId,oldData);if (res==0){//没有旧数据,就修改失败return false;}return addData(userId, newData);}// 删除指定的数据public long removeData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().remove(key, data);}}

五、测试扩展性

5.0 开发说明

后端:

只需要更改EldData的属性就好了
并且添加对应注解

如果有一个属性没有注解会报错,由于searchMap()中默认是所有属性都有此注解。

如果有属性不需要前端展示,可以在前端noNeed中添加
也可以后端修改注解,增加need属性,增加代码逻辑
另外:注解也可增加:x轴属性

    @ChineseName("id")String id;@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;@ChineseName("率3")Integer rate3;@ChineseName("date")Date date;

前端:

修改横轴:datax
怎么标注数据:data0
以及不需要展示的name链表:noNeed

    //横轴时间let datax = dataLists.date;//标注数据let data0 = [];//只需修改不需要展示的namevar noNeed=["id","date"];

5.1 测试结果

在这里插入图片描述

5.2 Eld多加一个属性

package com.jsss.echarts.entity;import com.jsss.echarts.annotation.ChineseName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.sql.Date;
import java.util.Objects;@Data
@NoArgsConstructor
@AllArgsConstructorpublic class EldData {@ChineseName("id")String id;@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;@ChineseName("率3")Integer rate3;@ChineseName("date")Date date;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;EldData eldData = (EldData) o;return Objects.equals(id, eldData.id) && Objects.equals(date, eldData.date);}@Overridepublic int hashCode() {return Objects.hash(id, date);}}

5.3 加入测试数据

@AutowiredRedisTemplate redisTemplate;@AutowiredDataService dataService;Integer userId=1;//清空数据@Testpublic void restore() {String key= ELD_DATA +userId;redisTemplate.delete(key);testSearchMap();}@Testpublic void testSearchMap(){HashMap<String, ArrayList> map = dataService.searchMap(userId);System.out.println(map);}@Testpublic void testValidAdd(){EldData eldData=new EldData(Toolbox.getRandomString(),175,160,111,new Date(2024-1900,4-1,8));dataService.addData(userId,eldData);eldData=new EldData(Toolbox.getRandomString(),160,140,121,new Date(2024-1900,4-1,9));dataService.addData(userId,eldData);eldData=new EldData(Toolbox.getRandomString(),153,205,131,new Date(2024-1900,4-1,10));dataService.addData(userId,eldData);eldData=new EldData(Toolbox.getRandomString(),121,162,141,new Date(2024-1900,4-1,11));dataService.addData(userId,eldData);eldData=new EldData(Toolbox.getRandomString(),156,175,151,new Date(2024-1900,4-1,12));dataService.addData(userId,eldData);testSearchMap();}

运行前端,登录admin:admin用户

在加入测试数据

userId=2

登录jsss:123456,也是可以的
在这里插入图片描述
2024-4-13 16:26:41

六、注解优化

6.0 开发说明

后端:
在EldData中

如果某个属性需要前端展示,就添加ChineseName注解
如果某个属性是横轴数据,其value值就是datax

前端:
不需要修改任何代码

public class EldData {@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;//没有注解,就不展示Integer rate3;//横轴的注解的值是datax@ChineseName("datax")Date date;}

6.1 测试结果

rate3没有注解
在这里插入图片描述
rate3添加注解
在这里插入图片描述

6.2 前端

对应的改一下这两个就行了

    //横轴数据let datax = dataLists.datax;//不需要展示的namevar noNeed=["datax"];

6.2 后端

ChineseName
/*** 如果某个属性需要展示,就添加`ChineseName`注解 <br>* 如果某个属性是横轴数据,其`value`值是`datax` <br>*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ChineseName {//中文nameString value();}
EldData

redis判断是根据序列化的结果判断是否相同,
equals和hashCode不起作用

package com.jsss.echarts.entity;import com.jsss.echarts.annotation.ChineseName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.sql.Date;@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class EldData {@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;//没有注解,就不展示Integer rate3;//横轴的注解的值是datax@ChineseName("datax")Date date;}
DataService
	//返回数据链表public HashMap<String,ArrayList> searchMap(Integer userId){HashMap<String,ArrayList> map=new LinkedHashMap<>();List<EldData> dataList = search(userId);List<String> fieldNames = new ArrayList<>();Class<?> dataClass = EldData.class;// 获取 OldData 类的所有被ChineseName注解的属性名Field[] fields = dataClass.getDeclaredFields();for (Field field : fields) {//添加是否有注解的判断ChineseName chineseNameAnnotation = field.getAnnotation(ChineseName.class);if (chineseNameAnnotation!=null){fieldNames.add(field.getName());map.put(field.getAnnotation(ChineseName.class).value(), new ArrayList<>());}}for (EldData data : dataList) {for (String fieldName : fieldNames) {try {Field field = dataClass.getDeclaredField(fieldName);field.setAccessible(true);ArrayList<Object> rowData =map.get(field.getAnnotation(ChineseName.class).value());rowData.add(field.get(data));map.put(field.getAnnotation(ChineseName.class).value(),rowData);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}}}return map;}//搜索数据public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, limit-1);// 获取分数最高的limit个数据if(set==null){return new ArrayList<>();}ArrayList<EldData> resList = new ArrayList<>(set);Collections.reverse(resList);return resList;}

七、实际项目开发

加入分栏就更好了
在这里插入图片描述

EldData

package com.jsss.echarts.entity;import com.jsss.echarts.annotation.ChineseName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.sql.Date;/*** 字段名称	类型	        字段说明	                    备注* <p>* HT	    Integer	    通用-身高(HT)	            单位:m* WT	    Integer	    通用-体重(WT)	            单位:kg* BMI	    Double	    通用-身高体重指数(BMI)	    正常范围 18.5~23.9,超重24.0~27.9,肥胖≥28.0* SBP	    Integer	    血压-收缩压(SBP)	            正常成年人的收缩压范围为90-140毫米汞柱(mmHg)。* DBP	    Integer	    血压-舒张压(DBP)	            正常成年人的舒张压范围为60-90毫米汞柱(mmHg)。* Hb	    Integer	    血常规-血红蛋白(Hb)	        正常成年人的正常范围为120-175克/升。* WBC	    Integer	    血常规-白细胞计数(WBC)	    正常成年人的白细胞计数范围为4-10 × 10^9/L。* PLT	    Integer	    血常规-血小板计数(PLT)	    正常成年人的血小板计数范围为100-300 × 10^9/L。* ALT	    Integer	    肝功能-谷丙转氨酶(ALT)	    正常成年人的ALT范围为10-40单位/升。* AST	    Integer	    肝功能-谷草转氨酶(AST)	    正常成年人的AST范围为10-35单位/升。* TBIL	    Double	    肝功能-总胆红素(TBIL)	        正常成年人的总胆红素范围为3.4-17.1毫摩尔/升。* BUN	    Double	    肾功能-血尿素氮(BUN)	        正常成年人的BUN范围为2.5-7.1毫摩尔/升。* Cr	    Integer	    肾功能-血肌酐(Cr)	        正常成年人的血肌酐范围为53-115微摩尔/升。* TC	    Double	    血脂-总胆固醇(TC)	        正常成年人的总胆固醇范围为3.1-5.2毫摩尔/升。* TG	    Double	    血脂-甘油三酯(TG)	        正常成年人的甘油三酯范围为0.4-1.7毫摩尔/升。* LDL_C	Double	    血脂-低密度脂蛋白胆固醇(LDL-C)	正常成年人的LDL-C范围为2.6-3.4毫摩尔/升。* FPG	    Double	    血糖-空腹血糖(FPG)	        正常成年人的空腹血糖范围为3.9-6.1毫摩尔/升。* twohPG	Double	    血糖-餐后2小时血糖(2hPG)	    正常成年人的餐后2小时血糖范围为3.9-7.8毫摩尔/升。*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class EldData {@ChineseName("通用-身高(米)")Integer HT;@ChineseName("通用-体重(千克)")Integer WT;@ChineseName("通用-身高体重指数(千克/米2)")Double BMI;@ChineseName("血压-收缩压(毫米汞柱)")Integer SBP;@ChineseName("血压-舒张压(毫米汞柱)")Integer DBP;@ChineseName("血常规-血红蛋白(克/升)")Integer Hb;@ChineseName("血常规-白细胞计数(10^9/升)")Integer WBC;@ChineseName("血常规-血小板计数(10^9/升)")Integer PLT;@ChineseName("肝功能-谷丙转氨酶(单位/升)")Integer ALT;@ChineseName("肝功能-谷草转氨酶(单位/升)")Integer AST;@ChineseName("肝功能-总胆红素(毫摩尔/升)")Double TBIL;@ChineseName("肾功能-血尿素氮(毫摩尔/升)")Double BUN;@ChineseName("肾功能-血肌酐(微摩尔/升)")Integer Cr;@ChineseName("血脂-总胆固醇(毫摩尔/升)")Double TC;@ChineseName("血脂-甘油三酯(毫摩尔/升)")Double TG;@ChineseName("血脂-低密度脂蛋白胆固醇(毫摩尔/升)")Double LDL_C;@ChineseName("血糖-空腹血糖(毫摩尔/升)")Double FPG;@ChineseName("血糖-餐后2小时血糖(毫摩尔/升)")Double twohPG;//横轴的注解的值是datax@ChineseName("datax")Date date;}

Constant

package com.jsss.utils;import com.jsss.echarts.entity.EldData;import java.sql.Date;public interface Constant {/*** redis键:老人的体检数据*/String ELD_DATA = "eld_data:";EldData MIN_DATA=new EldData(Integer.MIN_VALUE,Integer.MIN_VALUE,18.5,90,60,120,4,100,10,10,3.4,2.5,53,3.1,0.4,2.6,63.9,7.8,new Date(System.currentTimeMillis()));EldData MAX_DATA=new EldData(Integer.MAX_VALUE,Integer.MAX_VALUE,23.9,140,90,175,10,300,40,35,17.1,7.1,115,5.2,1.7,2.4,6.1,7.8,new Date(System.currentTimeMillis()));}

测试数据

package com.jsss.echarts;import com.jsss.echarts.entity.EldData;
import com.jsss.echarts.service.DataService;
import com.jsss.utils.Constant;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;@SpringBootTest
public class EchartsTest implements Constant {@AutowiredRedisTemplate redisTemplate;@AutowiredDataService dataService;Integer userId=1;Date date=new Date(2024-1900,4-1,14);@Testpublic void test(){System.out.println(date);}//清空数据@Testpublic void restore() {String key= ELD_DATA +userId;redisTemplate.delete(key);testSearchMap();}@Testpublic void testSearchMap(){HashMap<String, ArrayList> map = dataService.searchMap(userId);System.out.println(map);}@Testpublic void testValidAdd(){EldData eldData=randomData();eldData.setDate(new Date(2024-1900,4-1,8));dataService.addData(userId,eldData);eldData=randomData();eldData.setDate(new Date(2024-1900,4-1,9));dataService.addData(userId,eldData);eldData=randomData();eldData.setDate(new Date(2024-1900,4-1,10));dataService.addData(userId,eldData);eldData=randomData();eldData.setDate(new Date(2024-1900,4-1,11));dataService.addData(userId,eldData);eldData=randomData();eldData.setDate(new Date(2024-1900,4-1,12));dataService.addData(userId,eldData);testSearchMap();}EldData minData=MIN_DATA;EldData maxData=MAX_DATA;public EldData randomData(){EldData data=new EldData(randomInt(160,190), randomInt(45,80), randomDouble(minData.getBMI(),maxData.getBMI()),randomInt(minData.getSBP(),maxData.getSBP()),randomInt(minData.getDBP(),maxData.getDBP()),randomInt(minData.getHb(),maxData.getHb()),randomInt(minData.getWBC(),maxData.getWBC()),randomInt(minData.getPLT(),maxData.getPLT()),randomInt(minData.getALT(),maxData.getALT()),randomInt(minData.getAST(),maxData.getAST()),randomDouble(minData.getTBIL(),maxData.getTBIL()),randomDouble(minData.getBUN(),maxData.getBUN()),randomInt(minData.getCr(),maxData.getCr()),randomDouble(minData.getTC(),maxData.getTC()),randomDouble(minData.getTG(),maxData.getTG()),randomDouble(minData.getLDL_C(),maxData.getLDL_C()),randomDouble(minData.getFPG(),maxData.getFPG()),randomDouble(minData.getTwohPG(),maxData.getTwohPG()),new Date(System.currentTimeMillis()));return data;}public Integer randomInt(int min,int max){Random random = new Random();return random.nextInt(max - min + 1) + min; // 生成 min 到 max 范围内的随机 int 数}public Double randomDouble(double min,double max){Random random = new Random();return min + (max - min) * random.nextDouble(); // 生成 min 到 max 范围内的随机 double 值}}

最后

2024-4-13 18:49:18

迎着日光月光星光,直面风霜雨霜雪霜。

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

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

相关文章

【08】c++运算符重载

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、加号运算符二、左移运算符三.递增或者递减运算符总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;C运算符重载…

JVM性能调优——OOM分类及解决方案

文章目录 1、概述2、OOM案例1&#xff1a;堆内存溢出3、OOM案例2&#xff1a;元空间溢出4、OOM案例3:GC overhead limit exceeded5、OOM案例4&#xff1a;线程溢出6、小结 在工作中会经常遇到内存溢出(Out Of Memory,OOM)异常的情况&#xff0c;每当遇到OOM&#xff0c;总是让人…

关于使用druid数据源连接Oracle导致的SQLRecoverableException(socket read timeout,关闭的连接等)

背景 数据源初始化后,获取Oracle的连接进行查询操作,相隔 半个小时 左右,再次对同一数据库进行查询操作。 问题 第二次查询的时候,就会出现如下一些异常情况 2019-06-05 14:17:58.247 [CorePoolHandler-thread-6] ERROR [LOGID:] com.alibaba.druid.pool.DruidDataSource -…

matlab2024a软件下载

matlab2024a软件下载 MATLAB R2024a版本终于来了&#xff0c;通过上一个版本连续更新至Update7就预感这个版本将带来更多的新功能及增强。MATLAB更新包括编辑器拼写检查、面板导航、局部函数、Python接口互操作性、REST函数服务、安全信息存储以及ode对象求解器。Simulink更新…

camera驱动学习总结记录

https://www.yuque.com/u2132176/yfiyal/ch1zsrgzevcwf1rw 视频教程里面对应的gc2053c驱动源码注解&#xff1a; gc2053.c(60 KB) 对应的驱动文档&#xff1a; Rockchip_Driver_Guide_VI_CN_v1.1.1(2).pdf(2.3 MB) 视频里面对应的mipi协议文档汇总&#xff1a; MIPI标准文档大…

lv_micropython to download and building

想要在ESP32-C3使用Micropython开发GUI&#xff0c;所以需要编译lv_micropython&#xff0c;当前github上的版本是9.1.0。 一、开发环境 因为编译lv_micropython需要在linux系统下&#xff0c;但是我的电脑是windows系统&#xff0c;所以我在windows系统上安装了VMware虚拟机&…

如何用composer来安装和配置LAMP环境?

LAMP环境是一个开发和运行Web应用程序的常见环境&#xff0c;它由Linux、Apache、MySQL和PHP组成。Composer是一个用于管理PHP依赖关系的工具&#xff0c;可以方便地安装和配置LAMP环境中的各种软件包。下面是使用Composer安装和配置LAMP环境的步骤&#xff1a; 安装Composer&a…

Django框架设计原理

相信大多数的Web开发者对于MVC&#xff08;Model、View、Controller&#xff09;设计模式都不陌生&#xff0c;该设计模式已经成为Web框架中一种事实上的标准了&#xff0c;Django框架自然也是一个遵循MVC设计模式的框架。不过从严格意义上讲&#xff0c;Django框架采用了一种更…

C语言什么是指针? 什么是指针变量?

一、问题 指针是 C 语⾔中的⼀个重要概念&#xff0c;也是 C 语⾔中的⼀个重要特⾊。它的身影在整个 C 语⾔体系中都会出现&#xff0c;⽽且其概念也⼗分复杂&#xff0c;需要多加注意和思考。 二、解答 为了更好地弄清指针的概念&#xff0c;这⾥不得不先提到地址以及数据在内…

MySQL知识整理

MySQL知识整理 基础第一讲&#xff1a;基础架构&#xff1a;一条SQL查询语句是如何执行的&#xff1f;架构尽量减少长连接的原因和方案为什么尽量不要依赖查询缓存 索引第四讲&#xff1a;深入浅出索引&#xff08;上&#xff09;第五讲&#xff1a;深入浅出索引&#xff08;下…

C#面:介绍 ArrayList 与 Array 的区别

ArrayList 和 Array 是 C# 中两种不同的数据结构。 Array&#xff08;数组&#xff09; 是一种固定长度的数据结构&#xff0c;它可以存储相同类型的元素。在创建数组时&#xff0c;需要指定数组的长度&#xff0c;并且不能改变长度。数组的访问速度较快&#xff0c;因为它们…

【前端面试3+1】14 路由跳转的方式、如何取消已经发送的ajax请求、如何按顺序发起三个ajax请求并按顺序返回、【两个数组的并集】

一、路由跳转的几种方式 1、页面跳转 使用超链接 <a> 标签&#xff1a;通过在页面中定义超链接&#xff0c;用户点击超链接后会跳转到指定的URL页面。使用重定向&#xff1a;服务器端可以通过设置HTTP响应头中的Location字段&#xff0c;将用户重定向到指定的URL页面。使…

Web3 的社会影响:数字社会的新时代

随着科技的不断进步和创新&#xff0c;人类社会正逐步进入数字化时代的新阶段。Web3 技术作为数字社会的重要组成部分&#xff0c;正在以前所未有的方式重塑着我们的社会生活和交往方式。本文将探讨 Web3 技术对社会的影响&#xff0c;以及它所带来的数字社会的新时代。 1. Web…

JVM基础第一篇

内存结构 程序计数器 1.定义 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;每个线程都有一个独立的程序计数器&#xff0c;它是线程私有的&#xff0c;不会被线程切换所影响。 2.作用 记住下一条jvm指令的执行地址 3.特点 是线程私有的不会存在内存溢出 虚拟机…

数据结构——单链表(C语言版)

文章目录 一、链表的概念及结构二、单链表的实现SList.h链表的打印申请新的结点链表的尾插链表的头插链表的尾删链表的头删链表的查找在指定位置之前插入数据在指定位置之后插入数据删除pos结点删除pos之后的结点销毁链表 三、完整源代码SList.hSList.ctest.c 一、链表的概念及…

设计模式示例

单例模式示例 单例模式是一种常用的软件设计模式&#xff0c;其目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。以下是一个简单的单例模式示例&#xff1a; java public class Singleton {// 私有静态实例&#xff0c;防止被引用&#xff0c;此处赋值为nul…

【算法分析与设计】全排列

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给定一个不含重复数字的整数数组 nums &#xff0c;返回其 所有可能的全排列 。可以 按任意顺序 返回答案。 示例 示例 1&#xff1…

Transformer 结构浅析

Transformer 结构浅析 文章目录 Transformer 结构浅析Transformer 网络结构编码器位置编码多头注意力层Add&NormFeed Forward 解码器带掩码的多头注意力层多头注意力层 预测 Transformer 网络结构 Transformer模型的网络结构如图&#xff0c;且transformer结构主要分为两部…

二叉搜索树--搜索二维矩阵 II

题目描述 编写一个高效的算法来搜索 m * n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,…

unordered_map 值类型为函数指针概述

在C中&#xff0c;unordered_map是一种关联容器&#xff0c;可以存储键值对。如果你想在unordered_map中定义的值是有参函数&#xff0c;你可以使用std::function和std::bind来实现。 以下是一个简单的例子&#xff0c;展示了如何在unordered_map中存储有参函数&#xff0c;并…