数据可视化插件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",
                    // 数据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
@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: 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
@AllArgsConstructor

public 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.*;

@Service
public 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
@AllArgsConstructor

public 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
@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 {

    @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://www.mfbz.cn/a/556597.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT AI 教我用python实现工作久坐定时提醒工具,防猝死!

日常工作学习久坐的危害很大&#xff0c;非常伤害颈椎和腰椎&#xff0c;严重危害上班族的身体健康&#xff0c;强烈建议久坐后间隔一小时活动一下&#xff0c;最好是能够调整好自己坐姿&#xff0c;行为举止一定要正确&#xff0c;为了您的老腰&#xff01; 久坐一族&#xff…

Linux——日志的编写与线程池

目录 前言 一、日志的编写 二、线程池 1.线程池基本原理 2.线程池作用 3.线程池的实现 前言 学了很多线程相关的知识点&#xff0c;线程控制、线程互斥、线程同步&#xff0c;今天我们将他们做一个总结&#xff0c;运用所学知识写一个较为完整的线程池&#xff0c;同时…

mac: docker安装及其Command not found: docker

已经安装了docker desktop&#xff0c;没安装的 点击安装 傻瓜式安装即可 接着打开终端&#xff1a;好一个 Comand not found:docker 看我不把你整顿&#xff0c;解决如下&#xff1a; 如果你在 macOS 上安装了 Docker Desktop&#xff0c;但是终端无法识别 docker 命令&…

目标检测——多模态人体动作数据集

一、重要性及意义 连续多模态人体动作识别检测的重要性及意义主要体现在以下几个方面&#xff1a; 首先&#xff0c;它极大地提升了人体动作识别的准确性和稳定性。由于人体动作具有复杂性和多样性&#xff0c;单一模态的数据往往难以全面、准确地描述动作的特征。而连续多模…

深度学习数据处理——对比标签文件与图像文件,把没有打标签的图像文件标记并删除

要对比目录下的jpg文件与json文件&#xff0c;并删除那些没有对应json文件的jpg文件&#xff0c;这个在深度学习或者机器学习时常会遇到。比如对一个数据集做处理时&#xff0c;往往会有些图像不用标注&#xff0c;那么这张图像是没有对应的标签文件的&#xff0c;这个时候又不…

python-django企业设备配件检修系统flask+vue

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台&#xff0c;设计的基本思路是&#xff1a; 前端&#xff1a;vue.jselementui 框架&#…

玄子Share-LVM与磁盘配额

玄子Share-LVM与磁盘配额 LVM概述 Logical Volume Manager&#xff0c;逻辑卷管理 Linux系统中对磁盘分区进行管理的一种逻辑机制&#xff0c;是建立在硬盘和分区之上的一个逻辑层动态调整磁盘容量&#xff0c;从而提高磁盘管理的灵活性 /boot分区用于存放引导文件&#xff…

服务器中查看CPU/GPU使用情况的常用命令

1、查看显卡 nvidia-smi2、间隔查看GPU使用情况 间隔5s刷新信息 watch -n 5 nvidia-smiCtrlC退出 参考博文&#xff1a;https://mbd.baidu.com/ug_share/mbox/4a83aa9e65/share?productsmartapp&tk6ff15196d305c4dd3daab94b4abb81a4&share_urlhttps%3A%2F%2Fyebd1h…

JavaSE备忘录(未完)

文章目录 基本数据类型println 小知识除法( / ) 和 Infinity(无穷) 小知识除法InfinityInfinity 在除法中正负判断 求余(%) 小知识 基本数据类型 除 int、char 的包装类分别为 Integer、Character 外&#xff0c;其余基本数据类型的第一个字母大写就是它的包装类。 println 小…

vscode自动生成返回值的快捷键

vscode中类似idea的altenter功能&#xff0c;可以添加返回值 idea中是Introduce local variable&#xff0c; vscode中按下command.(句号) 然后选extract to local variable或者 Assign statement to new local variable都行&#xff0c; 光标在分号前如图&#xff1a; 光标在…

Redis快速入门操作

启动Redis 进入命令行客户端 字符串命令常用操作&#xff08;redis默认使用字符串来存储数据&#xff09; 列表&#xff08;Lists&#xff09;常用操作 集合&#xff08;Sets&#xff09;常用操作 &#xff08;无序集合且元素不可重复&#xff09; 有序集合&#xff08;So…

云原生虚拟数仓 PieCloudDB Database 4月更新盘点

第一部分 PieCloudDB Database 最新动态 增强本地缓存文件生命周期管理 PieCloudDB 在最新版本中增强了本地缓存文件生命周期管理&#xff0c;执行器节点重启之后可以继续使用之前缓存在本地的数据文件&#xff0c;从而节约重新从远端下载数据文件的带宽资源&#xff0c;提升…

DFS之剪枝(上交考研题目--正方形数组的数目)

题目 给定一个非负整数数组 A A A&#xff0c;如果该数组每对相邻元素之和是一个完全平方数&#xff0c;则称这一数组为正方形数组。 返回 A A A 的正方形排列的数目。 两个排列 A 1 A1 A1 和 A 2 A2 A2 不同的充要条件是存在某个索引 i i i&#xff0c;使得 A 1 [ i …

C语言简单的数据结构:双向链表的实现

目录&#xff1a; 1.双向链表的结构和初始化1.1双向链表的结构1.2双向链表的初始化 2.双向链表的相关操作2.1双向链表的尾插、打印和头插2.11双向链表的尾插2.12双向链表的打印2.13双向链表的头插 2.2双向链表的尾删和头删2.21双向链表的尾删2.22双向链表的头删 2.3双向链表查找…

实力认证!亚数产品入选《中国网络安全行业全景图(第十一版)》

2024年4月12日&#xff0c;安全牛第十一版《中国网络安全行业全景图》&#xff08;以下简称“全景图”&#xff09;正式发布。 亚数信息科技&#xff08;上海&#xff09;有限公司&#xff08;以下简称“亚数”&#xff09;成功入选数字证书、加解密、密钥管理三项细分领域。 此…

开发同城O2O跑腿系统源码:构建高效便捷的本地服务平台教程

为了满足用户对便捷的需求&#xff0c;今天我们将一同探讨如何开发一个高效便捷的同城O2O跑腿系统&#xff0c;以构建一个功能全面、操作简单的本地服务平台。 一、确定需求和功能 在开发同城O2O跑腿系统之前&#xff0c;首先需要明确系统的需求和功能。用户可以通过该系统发布…

使用LangChain和Llama-Index实现多重检索RAG

大家好&#xff0c;在信息检索的世界里&#xff0c;查询扩展技术正引领着一场效率革命。本文将介绍这一技术的核心多查询检索&#xff0c;以及其是如何在LangChain和Llama-Index中得到应用的。 1.查询扩展 查询扩展是一种信息检索技术&#xff0c;通过在原始查询的基础上增加…

python辅助QQ登入

python辅助QQ登入 import pyautogui import time import random from pyautogui import ImageNotFoundException# 生成随机等待时间&#xff0c;范围在1到3秒之间 random_time random.uniform(1, 3)def find_and_click(image_path, moveFalse, execute_nextTrue):try:image_l…

达梦数据库:安装达梦数据库客户端并配置python调用

前言 本文主要介绍了达梦数据库的客户端安装方案、python调用方案。本文使用的达梦数据库版本为 V8&#xff0c;如果使用的是其他版本&#xff0c;操作可能会有些许差异。 下载 前往官网安装&#xff1a;产品下载 | 达梦数据库 根据自己的系统版本进行选择&#xff0c;而后点击…

基于SpringBoot的“论坛管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“论坛管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 论坛管理系统结构图 前台首页功能界面图 用户登录…