当前位置:首页 » 《关注互联网》 » 正文

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

25 人参与  2024年04月21日 16:10  分类 : 《关注互联网》  评论

点击全文阅读


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

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

前言

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",                    // 数据data                    data:[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@AllArgsConstructorpublic 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: 1            userId: 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 = [];        //只需修改不需要展示的name    var noNeed=["id","date"];    //原始数据的所有name    let 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;    @Override    public 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);    }    @Override    public int hashCode() {        return Objects.hash(id, date);    }    @Override    public 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.*;@Servicepublic class DataService implements Constant {    @Autowired    RedisTemplate 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 = [];        //只需修改不需要展示的name    var 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;    @Override    public 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);    }    @Override    public int hashCode() {        return Objects.hash(id, date);    }}

5.3 加入测试数据

    @Autowired    RedisTemplate redisTemplate;    @Autowired    DataService dataService;    Integer userId=1;    //清空数据    @Test    public void restore() {        String key= ELD_DATA +userId;        redisTemplate.delete(key);        testSearchMap();    }    @Test    public void testSearchMap(){        HashMap<String, ArrayList> map = dataService.searchMap(userId);        System.out.println(map);    }    @Test    public 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;    //不需要展示的name    var noNeed=["datax"];

6.2 后端

ChineseName
/** * 如果某个属性需要展示,就添加`ChineseName`注解 <br> * 如果某个属性是横轴数据,其`value`值是`datax` <br> */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ChineseName {    //中文name    String 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@ToStringpublic 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_CDouble    血脂-低密度脂蛋白胆固醇(LDL-C)正常成年人的LDL-C范围为2.6-3.4毫摩尔/升。 * FPG    Double    血糖-空腹血糖(FPG)        正常成年人的空腹血糖范围为3.9-6.1毫摩尔/升。 * twohPGDouble    血糖-餐后2小时血糖(2hPG)    正常成年人的餐后2小时血糖范围为3.9-7.8毫摩尔/升。 */@Data@NoArgsConstructor@AllArgsConstructor@ToStringpublic 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;@SpringBootTestpublic class EchartsTest implements Constant {    @Autowired    RedisTemplate redisTemplate;    @Autowired    DataService dataService;    Integer userId=1;    Date date=new Date(2024-1900,4-1,14);    @Test    public void test(){        System.out.println(date);    }    //清空数据    @Test    public void restore() {        String key= ELD_DATA +userId;        redisTemplate.delete(key);        testSearchMap();    }    @Test    public void testSearchMap(){        HashMap<String, ArrayList> map = dataService.searchMap(userId);        System.out.println(map);    }    @Test    public 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://zhangshiyu.com/post/98677.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1