0


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

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

前言

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.js

echarts.min,js

在这里插入图片描述

1.3 入门使用

<!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title><!-- 01 导入js --><scriptsrc="js/echarts.js"></script><!-- 03 设置容器的样式 --><style>#container{width: 800px;height: 600px;}</style></head><body><!-- 02 创建个容器 --><divid="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

在这里插入图片描述

<!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title><!-- 01 导入js --><scriptsrc="js/echarts.js"></script><!-- 03 设置容器的样式 --><style>#container{width: 800px;height: 600px;}</style></head><body><!-- 02 创建个容器 --><divid="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();});functionlist(){
    $.ajax({type:"GET",url:SERVER_PATH+"/data/list",xhrFields:{withCredentials:true},success:function(result){if(result.status){alertBox(result.data.message);returnfalse;}init(result.data);}});}functioninit(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@AllArgsConstructorpublicclassData{IntegerInWater;IntegerOutWater;Date date;}
controller
@GetMapping("/list")publicResponseModelgetDataList(){HashMap<String,Object> search = dataService.searchMap();returnnewResponseModel(search);}
service
publicHashMap<String,Object>searchMap(){HashMap<String,Object> map=newHashMap<>();List<Data> dataList =search();List<Integer> inWaterList =newArrayList<>();List<Integer> outWaterList =newArrayList<>();List<Date> dateList =newArrayList<>();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;}publicList<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);returnfalse;}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: 'AlibabaPuHuiTi',
                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: 'AlibabaPuHuiTi',
                    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
//返回数据链表publicHashMap<String,ArrayList>searchMap(Integer userId){HashMap<String,ArrayList> map=newHashMap<>();List<EldData> dataList =search(userId);List<String> fieldNames =newArrayList<>();Class<?> dataClass =EldData.class;// 获取 OldData 类的所有属性名Field[] fields = dataClass.getDeclaredFields();for(Field field : fields){
            fieldNames.add(field.getName());
            map.put(field.getName(),newArrayList<>());}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;}//搜索数据publicList<EldData>search(Integer userId){String key=ELD_DATA+userId;Set set = redisTemplate.opsForZSet().reverseRange(key,0,19);// 获取分数最高的20个数据return set !=null?newArrayList<>(set):newArrayList<>();}

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

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

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

在seachMap()中,重新定义

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

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

//搜索数据//    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<>();////    }//搜索数据publicList<EldData>search(Integer userId){String key=ELD_DATA+userId;Set set = redisTemplate.opsForZSet().reverseRange(key,0, limit-1);// 获取分数最高的limit个数据if(set==null){returnnewArrayList<>();}ArrayList<EldData> resList =newArrayList<>(set);Collections.reverse(resList);return resList;}

在这里插入图片描述

4.1 前端

js

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

$(document).ready(function(){list();});functionlist(){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);returnfalse;}init(result.data);}});}functioninit(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);}functiongenerateRandomColors(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注解
packagecom.jsss.echarts.annotation;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public@interfaceChineseName{Stringvalue();}
EldData
packagecom.jsss.echarts.entity;importcom.jsss.echarts.annotation.ChineseName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.EqualsAndHashCode;importlombok.NoArgsConstructor;importjava.sql.Date;importjava.util.Objects;@Data@NoArgsConstructor@AllArgsConstructorpublicclassEldData{@ChineseName("id")String id;@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;@ChineseName("date")Date date;@Overridepublicbooleanequals(Object o){if(this== o)returntrue;if(o ==null||getClass()!= o.getClass())returnfalse;EldData eldData =(EldData) o;returnObjects.equals(id, eldData.id)&&Objects.equals(date, eldData.date);}@OverridepublicinthashCode(){returnObjects.hash(id, date);}@OverridepublicStringtoString(){return"EldData{"+"rate1="+ rate1 +", rate2="+ rate2 +", date="+ date +'}';}}
DataService
packagecom.jsss.echarts.service;importcom.jsss.echarts.annotation.ChineseName;importcom.jsss.echarts.entity.EldData;importcom.jsss.utils.Constant;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.StringRedisSerializer;importorg.springframework.stereotype.Service;importjava.lang.reflect.Field;importjava.util.*;@ServicepublicclassDataServiceimplementsConstant{@AutowiredRedisTemplate redisTemplate;//返回数据链表publicHashMap<String,ArrayList>searchMap(Integer userId){//        HashMap<String,ArrayList> map=new HashMap<>();HashMap<String,ArrayList> map=newLinkedHashMap<>();List<EldData> dataList =search(userId);List<String> fieldNames =newArrayList<>();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(),newArrayList<>());}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<>();////    }//搜索数据publicList<EldData>search(Integer userId){String key=ELD_DATA+userId;Set set = redisTemplate.opsForZSet().reverseRange(key,0, limit-1);// 获取分数最高的limit个数据if(set==null){returnnewArrayList<>();}ArrayList<EldData> resList =newArrayList<>(set);Collections.reverse(resList);return resList;}// 将数据存储到有序集合中,分数为日期的时间戳publicbooleanaddData(Integer userId,EldData data){String key=ELD_DATA+userId;return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());}// 更新数据,先删除数据,后增加新数据publicbooleanupdateData(Integer userId,EldData oldData,EldData newData){long res=removeData(userId,oldData);if(res==0){//没有旧数据,就修改失败returnfalse;}returnaddData(userId, newData);}// 删除指定的数据publiclongremoveData(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 = [];

    
    //只需修改不需要展示的name
    var noNeed=["id","date"];

5.1 测试结果

在这里插入图片描述

5.2 Eld多加一个属性

packagecom.jsss.echarts.entity;importcom.jsss.echarts.annotation.ChineseName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.sql.Date;importjava.util.Objects;@Data@NoArgsConstructor@AllArgsConstructorpublicclassEldData{@ChineseName("id")String id;@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;@ChineseName("率3")Integer rate3;@ChineseName("date")Date date;@Overridepublicbooleanequals(Object o){if(this== o)returntrue;if(o ==null||getClass()!= o.getClass())returnfalse;EldData eldData =(EldData) o;returnObjects.equals(id, eldData.id)&&Objects.equals(date, eldData.date);}@OverridepublicinthashCode(){returnObjects.hash(id, date);}}

5.3 加入测试数据

@AutowiredRedisTemplate redisTemplate;@AutowiredDataService dataService;Integer userId=1;//清空数据@Testpublicvoidrestore(){String key=ELD_DATA+userId;
        redisTemplate.delete(key);testSearchMap();}@TestpublicvoidtestSearchMap(){HashMap<String,ArrayList> map = dataService.searchMap(userId);System.out.println(map);}@TestpublicvoidtestValidAdd(){EldData eldData=newEldData(Toolbox.getRandomString(),175,160,111,newDate(2024-1900,4-1,8));
        dataService.addData(userId,eldData);
        eldData=newEldData(Toolbox.getRandomString(),160,140,121,newDate(2024-1900,4-1,9));
        dataService.addData(userId,eldData);
        eldData=newEldData(Toolbox.getRandomString(),153,205,131,newDate(2024-1900,4-1,10));
        dataService.addData(userId,eldData);
        eldData=newEldData(Toolbox.getRandomString(),121,162,141,newDate(2024-1900,4-1,11));
        dataService.addData(userId,eldData);
        eldData=newEldData(Toolbox.getRandomString(),156,175,151,newDate(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

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

publicclassEldData{@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@interfaceChineseName{//中文nameStringvalue();}
EldData

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

packagecom.jsss.echarts.entity;importcom.jsss.echarts.annotation.ChineseName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importlombok.ToString;importjava.sql.Date;@Data@NoArgsConstructor@AllArgsConstructor@ToStringpublicclassEldData{@ChineseName("率1")Integer rate1;@ChineseName("率2")Integer rate2;//没有注解,就不展示Integer rate3;//横轴的注解的值是datax@ChineseName("datax")Date date;}
DataService
//返回数据链表publicHashMap<String,ArrayList>searchMap(Integer userId){HashMap<String,ArrayList> map=newLinkedHashMap<>();List<EldData> dataList =search(userId);List<String> fieldNames =newArrayList<>();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(),newArrayList<>());}}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;}//搜索数据publicList<EldData>search(Integer userId){String key=ELD_DATA+userId;Set set = redisTemplate.opsForZSet().reverseRange(key,0, limit-1);// 获取分数最高的limit个数据if(set==null){returnnewArrayList<>();}ArrayList<EldData> resList =newArrayList<>(set);Collections.reverse(resList);return resList;}

七、实际项目开发

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

EldData

packagecom.jsss.echarts.entity;importcom.jsss.echarts.annotation.ChineseName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importlombok.ToString;importjava.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@ToStringpublicclassEldData{@ChineseName("通用-身高(米)")IntegerHT;@ChineseName("通用-体重(千克)")IntegerWT;@ChineseName("通用-身高体重指数(千克/米2)")DoubleBMI;@ChineseName("血压-收缩压(毫米汞柱)")IntegerSBP;@ChineseName("血压-舒张压(毫米汞柱)")IntegerDBP;@ChineseName("血常规-血红蛋白(克/升)")IntegerHb;@ChineseName("血常规-白细胞计数(10^9/升)")IntegerWBC;@ChineseName("血常规-血小板计数(10^9/升)")IntegerPLT;@ChineseName("肝功能-谷丙转氨酶(单位/升)")IntegerALT;@ChineseName("肝功能-谷草转氨酶(单位/升)")IntegerAST;@ChineseName("肝功能-总胆红素(毫摩尔/升)")DoubleTBIL;@ChineseName("肾功能-血尿素氮(毫摩尔/升)")DoubleBUN;@ChineseName("肾功能-血肌酐(微摩尔/升)")IntegerCr;@ChineseName("血脂-总胆固醇(毫摩尔/升)")DoubleTC;@ChineseName("血脂-甘油三酯(毫摩尔/升)")DoubleTG;@ChineseName("血脂-低密度脂蛋白胆固醇(毫摩尔/升)")DoubleLDL_C;@ChineseName("血糖-空腹血糖(毫摩尔/升)")DoubleFPG;@ChineseName("血糖-餐后2小时血糖(毫摩尔/升)")Double twohPG;//横轴的注解的值是datax@ChineseName("datax")Date date;}

Constant

packagecom.jsss.utils;importcom.jsss.echarts.entity.EldData;importjava.sql.Date;publicinterfaceConstant{/**
     * redis键:老人的体检数据
     */StringELD_DATA="eld_data:";EldDataMIN_DATA=newEldData(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,newDate(System.currentTimeMillis()));EldDataMAX_DATA=newEldData(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,newDate(System.currentTimeMillis()));}

测试数据

packagecom.jsss.echarts;importcom.jsss.echarts.entity.EldData;importcom.jsss.echarts.service.DataService;importcom.jsss.utils.Constant;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.data.redis.core.RedisTemplate;importjava.sql.Date;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Random;@SpringBootTestpublicclassEchartsTestimplementsConstant{@AutowiredRedisTemplate redisTemplate;@AutowiredDataService dataService;Integer userId=1;Date date=newDate(2024-1900,4-1,14);@Testpublicvoidtest(){System.out.println(date);}//清空数据@Testpublicvoidrestore(){String key=ELD_DATA+userId;
        redisTemplate.delete(key);testSearchMap();}@TestpublicvoidtestSearchMap(){HashMap<String,ArrayList> map = dataService.searchMap(userId);System.out.println(map);}@TestpublicvoidtestValidAdd(){EldData eldData=randomData();
        eldData.setDate(newDate(2024-1900,4-1,8));
        dataService.addData(userId,eldData);
        eldData=randomData();
        eldData.setDate(newDate(2024-1900,4-1,9));
        dataService.addData(userId,eldData);
        eldData=randomData();
        eldData.setDate(newDate(2024-1900,4-1,10));
        dataService.addData(userId,eldData);
        eldData=randomData();
        eldData.setDate(newDate(2024-1900,4-1,11));
        dataService.addData(userId,eldData);
        eldData=randomData();
        eldData.setDate(newDate(2024-1900,4-1,12));
        dataService.addData(userId,eldData);testSearchMap();}EldData minData=MIN_DATA;EldData maxData=MAX_DATA;publicEldDatarandomData(){EldData data=newEldData(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()),newDate(System.currentTimeMillis()));return data;}publicIntegerrandomInt(int min,int max){Random random =newRandom();return random.nextInt(max - min +1)+ min;// 生成 min 到 max 范围内的随机 int 数}publicDoublerandomDouble(double min,double max){Random random =newRandom();return min +(max - min)* random.nextDouble();// 生成 min 到 max 范围内的随机 double 值}}

最后

2024-4-13 18:49:18

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


本文转载自: https://blog.csdn.net/qq_51625007/article/details/137684820
版权归原作者 日星月云 所有, 如有侵权,请联系我们删除。

“数据可视化插件echarts【前端】”的评论:

还没有评论