vue实现列表自动滚动(纯与原生方式)

news2024/11/25 20:46:38

Vue实现列表自动滚动(纯与原生方式)

源码放在最后!

1.效果展示:

请添加图片描述

2.功能说明:

该滚动可能存在的Bug:

  • 1.如果你写的大屏不是使用的接口轮询的方式可能会存在也页面空白的情况(需要手动刷新才能触发列表滚动),因为我使用的是监听数据的变化然后做出响应,一般来说写大屏都会有个数据更新的机制。这一点需要你对源码进行改动。

3.原理分析:

1.核心数据和变量:
  • CityData:包含了所有的表格数据,是一个二维数组,每一行数据代表一个城市的信息。
  • CURRENTDATA:存储当前显示在屏幕上的行数据,动态更新以实现滚动效果。
  • COLUMNHEIGHT:存储每一行的高度,在滚动时通过调整前几行的高度来实现滑动效果。
  • CURRENTINDEX:表示当前显示的首行索引,在滚动过程中不断递增,最终通过循环回到起始行。
2.数据初始化:

当组件挂载时,会通过 onMounted 钩子初始化表格数据。关键步骤包括:

  • 计算每列的宽度 HandelHeaderAverageWidthHandelColumnAverageWidth
  • 计算行的高度 HandelAverageHeight
  • 格式化数据并初始化 CityData,为每一行数据添加索引列,并根据 Alluserdata 动态填充内容。
3.高度变化实现(核心!)

滚动动画的关键在于每行的高度如何变化。为了模拟滚动,我们让行逐渐“消失”并再“出现”。具体实现步骤如下:

  • 初始行高度:表格中的每一行都有固定的高度,在初始化时通过 HandelAverageHeight 计算每行的平均高度,并将结果存储在 COLUMNHEIGHT 中。

    const HandelAverageHeight = () => {
        const AverageHeight = height.value / columnNumber.value;
        AverageHeighT.value = AverageHeight;
        const TotalCount = 23;  // 表示总的行数
        COLUMNHEIGHT.value = new Array(TotalCount).fill(AverageHeight);
    };
    

    例如,假设每行的高度为 50px,这意味着表格中的所有行在初始时都是统一高度的。

  • 高度变化模拟滚动:在开始动画时,StartAnimation 函数负责将某些行的高度设置为 0,模拟这些行滚动出可视区域。

    COLUMNHEIGHT.value.splice(0, MoveNumber, ...new Array(MoveNumber).fill(0));
    

    这个 splice 操作将 COLUMNHEIGHT 数组中前 MoveNumber 行的高度设置为 0,因此这些行会逐渐缩小到不可见,产生滚动的效果。

    当行的高度变为 0 时,浏览器会根据 CSS 的 transition 动画特性让该行逐渐收缩,这就是为什么行从视野中“滑动”出去,而不是瞬间消失。

4.数据无限循环的过程:

为了让滚动效果无限循环,需要对 CityData(存储所有表格数据)和 CURRENTDATA(存储当前显示的行数据)进行操作,使得数据能够循环显示。

  • 当前索引控制:通过 CURRENTINDEX 控制当前显示的起始行。在每次动画开始时,会计算新的起始行索引,并根据这个索引来更新当前显示的数据。

    const alldataLenght = CityData.value.length;  // 获取所有数据的长度
    const MoveNumber = 1;  // 表示每次滚动多少行
    const index = CURRENTINDEX.value;  // 当前滚动的索引
    

    CURRENTINDEX 会随着每次滚动递增,当它达到数据集的长度时,循环回到开头,确保表格数据可以无限滚动。

  • 数据循环拼接:为了避免滚动到最后几行时的“断层”,StartAnimation 函数会将 CityData 从当前索引开始的数据提取出来,并将前面的数据拼接到后面,形成一个无缝连接的效果。

    const rowdata = cloneDeep(CityData.value);  // 深拷贝 CityData 避免直接修改
    const rows = rowdata.slice(index);  // 从当前索引开始提取数据
    rows.push(...rowdata.slice(0, index));  // 将索引之前的行拼接到后面
    

    比如当表格已经滚动到倒数第二行时,slice(index) 提取出剩下的最后几行,而 slice(0, index) 则从头部提取最开始的几行,并将它们拼接在一起。这使得滚动能够无缝连接。

    这样,在 CURRENTDATA 中,数据始终是连续的,模拟了数据无限循环滚动的效果。

5.递归定时器控制滚动:

滚动效果通过递归调用 StartAnimation 来实现,每次滚动后等待一段时间,然后再执行下一次滚动。这就像一个“无尽的循环”,使表格持续滚动。

  • 延迟机制:在每次滚动之前,会通过 await 等待一段时间,控制滚动的速度。

    await new Promise(resolve => setTimeout(resolve, awaitTime));  // 等待500ms
    

    这里的 awaitTime 控制了滚动的速度,500ms 表示每次滚动间隔 0.5 秒。

  • 高度动画延迟:滚动分为两个阶段,先将行的高度逐渐设置为 0,然后让下一行进入视野。这个过程通过两次 setTimeout 来控制。

    await new Promise(resolve => setTimeout(resolve, 800 - awaitTime));  // 额外等待800ms
    

    这个延迟的机制让滚动变得平滑,防止表格中的数据瞬间跳跃。

4.完整源码

首先你要有pinia、loadsh、uuid这些库

这是我的文件目录,有点不规范,你可以自己修改hook可以抽取一下!
请添加图片描述

PlanList.vue
<template>
    <div class="AutoScrollTabel" :id="ID">
        <div class="header">
            <template v-for="(item, index) in Headerdata">
                <div class="headeritem" :style="{ width: `${AVERAGEWIDTH[index]}px` }">
                    {{ item }}
                </div>
            </template>
        </div>
        <div class="ColumLIst">
            <template v-for="(item, index) in CURRENTDATA" :key="item.Rowindex + '-' + index">
                <div class="itemWrapper"
                    :style="{ height: `${COLUMNHEIGHT[index]}px`, lineHeight: `${COLUMNHEIGHT[index]}px`, backgroundColor: item.Rowindex % 2 === 0 ? BGCOLOR2 : BGCOLOR1 }">
                    <template v-for="(iten, idx) in item.data" :key="item.Rowindex + '-' + idx">
                        <!-- 使用 Rowindex 和 idx 组合,确保每一项唯一 -->
                        <div class="item" :align="align[idx]" :style="{ width: `${COLUMNAVERAGEWIDTH[idx]}px` }"
                            v-html="iten"></div>
                    </template>
                </div>
            </template>
        </div>
    </div>
</template>

<script setup>
import { onMounted, ref, watch, nextTick } from 'vue'
import { v4 as uuidv4 } from 'uuid'
import cloneDeep from 'loadsh/cloneDeep'

import { storeToRefs } from 'pinia' // pinia
import { useAllUserDataStore } from '../../../store/index'; // pinia
const AllUserData = useAllUserDataStore() // pinia
const { Alluserdata } = storeToRefs(AllUserData) // pinia

import init from '../utils/init'
// CityData: 用于存储城市数据的二维数组,每行代表一条记录,每列代表不同的数据项
const CityData = ref([])

// columnIndex: 存储每行数据的索引列,通常用来表示行号或某种标识符
const columnIndex = ref([])

// Headerdata: 存储表格的表头数据,代表每列的标题
const Headerdata = ["城市订单量", "店铺数", "接单骑手人数", "新店铺数量", "人均订单量"]

// AVERAGEWIDTH: 存储表头每列的平均宽度
const AVERAGEWIDTH = ref([])

// COLUMNAVERAGEWIDTH: 存储每列的平均宽度,除了第一列的额外宽度(通常用于索引列)
const COLUMNAVERAGEWIDTH = ref([])

// columnNumber: 表示每列的数量或展示的列数,可能会影响表格的布局
const columnNumber = ref(10)

// AverageHeighT: 存储每行的平均高度,用于控制行高
const AverageHeighT = ref(0)

// COLUMNHEIGHT: 存储每行的高度,用于控制行的高度
const COLUMNHEIGHT = ref([])

// Datalenght: 存储数据的长度,即行数
const Datalenght = ref(0)

// CURRENTINDEX: 当前滚动到的索引位置,用于动画或分页等功能
const CURRENTINDEX = ref(0)

// CURRENTDATA: 存储当前显示的数据,用于表格的内容展示
const CURRENTDATA = ref([])

// ID: 每个表格的唯一标识符,使用 UUID 来确保唯一性
const ID = `BaseScorelist+${uuidv4()}`

// BGCOLOR1: 表格背景颜色 1,用于奇数行或默认背景色
const BGCOLOR1 = 'rgb(55,55,55)'

// BGCOLOR2: 表格背景颜色 2,用于偶数行或替代背景色
const BGCOLOR2 = 'rgb(44,44,44)'

// align: 表格每列的对齐方式,这里是全部居中
const align = ["center", "center", "center", "center", "center", "center"]

const { width, height } = init(ID)
// 生成 UUID 的函数
function generateUUID() {
    return uuidv4();
}
// 处理数据行,将数据转换为适合显示的格式
const Handeldata = () => {
    // 为每一行数据添加行索引
    CityData.value.map((item, index) => {
        item.unshift(columnIndex.value[index])
    })

    // 生成包含行数据和行索引的数组
    const data = CityData.value.map((item, index) => {
        return {
            data: item,
            Rowindex: index
        }
    })

    // 更新 CityData
    CityData.value = data
}

// 处理表头的宽度
const HandelHeaderAverageWidth = () => {
    const needAverage = Headerdata.length
    const currentWidth = 50
    // 计算表头的平均宽度
    const averagewidth = (width.value - currentWidth) / needAverage
    AVERAGEWIDTH.value = new Array(Headerdata.length)
    AVERAGEWIDTH.value.fill(averagewidth)
}
// 处理表格列的平均宽度(除了索引列)
const HandelColumnAverageWidth = () => {
    let needAverage = 5
    const averagewidth = (width.value - 40) / needAverage
    COLUMNAVERAGEWIDTH.value = new Array(5)
    COLUMNAVERAGEWIDTH.value.fill(averagewidth)
    COLUMNAVERAGEWIDTH.value.unshift(50)
}
// 处理每行的平均高度
const HandelAverageHeight = () => {
    const AverageHeight = height.value / columnNumber.value
    AverageHeighT.value = AverageHeight
    const TotalCount = 23
    COLUMNHEIGHT.value = new Array(TotalCount).fill(AverageHeight)
}
// 启动动画,控制表格内容的滚动
const StartAnimation = async () => {
    console.log("111")
    // 获取真实数据长度
    const alldataLenght = CityData.value.length;
    const MoveNumber = 1;
    const index = CURRENTINDEX.value;

    // 当数据长度小于需要移动的数量时,直接退出
    // if (alldataLenght <= MoveNumber) return;
    console.log("进入了动画函数 StartAnimation")

    const rowdata = cloneDeep(CityData.value);
    const rows = rowdata.slice(index); // 获取当前起始位置后的数据

    // 连接数据头尾,避免卡顿
    rows.push(...rowdata.slice(0, index));

    CURRENTDATA.value = rows;
    COLUMNHEIGHT.value = new Array(alldataLenght).fill(AverageHeighT.value);

    const awaitTime = 500;
    await new Promise(resolve => setTimeout(resolve, awaitTime));

    // 更新前几个行的高度为 0
    COLUMNHEIGHT.value.splice(0, MoveNumber, ...new Array(MoveNumber).fill(0));

    // 更新当前索引
    CURRENTINDEX.value += MoveNumber;
    const ISLAST = CURRENTINDEX.value - alldataLenght;
    if (ISLAST >= 0) {
        CURRENTINDEX.value = ISLAST; // 循环回到数据开始位置
    }

    await new Promise(resolve => setTimeout(resolve, 800 - awaitTime));
    await StartAnimation(); // 递归调用自身进行动画
    console.log("调用了动画函数 StartAnimation");
};

watch(() => Alluserdata.value, (NewData) => {
    Datalenght.value = NewData.length;
    CityData.value = [];  // 清空原有数据

    for (let i = 0; i < Datalenght.value; i++) {
        CityData.value[i] = [];
        // 生成列索引和内容
        if (i % 2 === 0) {
            columnIndex.value[i] = `<div style="width:100%; padding-left=5px; height:100%; display:flex; align-items:center; justify-content:center; background:rgb(44,44,44)">
            <div style="width:15px;height:15px;background:rgb(72,122,72);border-radius:50%;border:1px solid #fff;"/>
            </div>`;
        } else {
            columnIndex.value[i] = `<div style="width:100%; height:100%; display:flex; align-items:center; justify-content:center; background:rgb(44,44,44)">
            <div style="width:15px;height:15px;background:rgb(38,88,104);border-radius:50%;border:1px solid #fff;"/>
            </div>`;
        }
        // 生成数据行
        for (let i = 0; i < Datalenght.value; i++) {
            CityData.value[i] = [];

            // 根据行索引来决定前面点的背景颜色
            const pointBgColor = i % 2 === 0 ? 'rgb(44,44,44)' : 'rgb(55,55,55)'; // 偶数行和奇数行的背景颜色

            columnIndex.value[i] = `
        <div style="width:100%; height:100%; display:flex; align-items:center; justify-content:center; background:${pointBgColor}">
            <div style="width:15px;height:15px;background:rgb(72,122,72);border-radius:50%;border:1px solid #fff;"></div>
        </div>`;

            // 生成数据行
            for (let j = 0; j < 5; j++) {
                let text = '';
                switch (j) {
                    case 0: text = NewData[i].order; break;
                    case 1: text = NewData[i].shop; break;
                    case 2: text = NewData[i].rider; break;
                    case 3: text = NewData[i].newShop; break;
                    case 4: text = NewData[i].avgOrder; break;
                }
                // 其他列的内容颜色保持不变
                if (j === 1 || j === 3) {
                    CityData.value[i].push(`<div style="color:rgb(178,209,126)">${text}</div>`);
                } else {
                    CityData.value[i].push(`<div>${text}</div>`);
                }
            }
        }

    }
    Handeldata();
});

onMounted(() => {

    StartAnimation()
    Handeldata()
    HandelHeaderAverageWidth()
    HandelColumnAverageWidth()
    HandelAverageHeight()
})

</script>

<style scoped lang="less">
.AutoScrollTabel {
    width: 100%;
    height: 100%;
    // margin: 30px;
    user-select: none;
    box-sizing: border-box;

    .header {
        display: flex;
        align-items: center;
        // justify-content: space-around;
        background-color: rgb(90, 90, 90);
        color: rgb(255, 255, 255);
        padding-left: 50px;

        .headeritem {
            font-size: 15px;
            padding: 10px 0;
            text-align: center;
        }

    }

    .ColumLIst {
        .itemWrapper {
            overflow: hidden;
            display: flex;
            font-size: 30px;
            align-items: center;
            transition: all 0.3s linear;

            .item {
                width: 100%;
                height: 100%;
                overflow: hidden;
                text-align: center;
                // align-items: center;
                font-size: 20px;
                // padding: 10px 0px;
            }
        }

    }
}
</style>
init.ts
import { ref, onMounted } from 'vue'

const init = (id: string) => {
    const width = ref<number>(0)
    const height = ref<number>(0)

    // 获取 dom
    onMounted(() => {
        const container = document.getElementById(id) as HTMLElement | null
        if (container) {
            const domwidth = container.clientWidth
            const domheight = container.clientHeight
            // 初始化宽高
            width.value = domwidth
            height.value = domheight
        }
    })

    return {
        width,
        height
    }
}

export default init
PanList文件夹下的Index.vue
<template>
    <div class="plan-list">
        <div class="title">区域销售大盘环比分析</div>
        <div class="planlistScore">
            <PanlList />

        </div>
    </div>
</template>

<script setup>
import { onMounted } from 'vue';
import PanlList from './cpns/PanlList.vue';

import { useAllUserDataStore } from '../../store/index'; // 引入 Pinia store

// 获取 Pinia store 实例
const AllUserDataStore = useAllUserDataStore();

// 定义更新数据函数
const updateData = () => {
    // 直接触发更新,而不是生成随机数据
    const newData = AllUserDataStore.getAllUserData();  // 假设这个函数获取当前的用户数据
    AllUserDataStore.setAllUserData(newData); // 直接更新数据
};

// 使用 onMounted 生命周期钩子来定时更新数据
onMounted(() => {
    // 每隔 3 秒触发一次更新
    setInterval(() => {
        updateData();
    }, 1000); // 每 3 秒更新一次
});
</script>

<style scoped lang="less">
.plan-list {
    width: 100%;
    height: 100%;
    background: rgb(55, 55, 55);
    padding: 20px 10px;
    color: #fff;
    box-sizing: border-box;

    .title {
        font-size: 26px;
        text-align: center;
    }

    .planlistScore {
        width: 100%;
        height: calc(100% - 40px);
        background: rgb(40, 40, 40);
        overflow: hidden;
    }
}
</style>
Store文件夹下面的index.ts
import { defineStore } from 'pinia'

// 定义 `UserData` 数据结构类型
interface UserData {
    order: string;  // 修改为 string 类型
    shop: string;   // 修改为 string 类型
    rider: string;  // 修改为 string 类型
    newShop: string; // 修改为 string 类型
    avgOrder: string; // 修改为 string 类型
    Rowindex?: number; // 添加 RowIndex 字段
}

// 定义 store
export const useAllUserDataStore = defineStore('AllUserData', {
    state: (): { Alluserdata: UserData[] } => ({
        Alluserdata: [
            { "order": "北京 -17%", "shop": "北京 -3%", "rider": "北京 +20%", "newShop": "北京 +14%", "avgOrder": "北京 -16%" },
            { "order": "上海 -19%", "shop": "上海 +12%", "rider": "上海 -15%", "newShop": "上海 +15%", "avgOrder": "上海 -21%" },
            { "order": "广州 +20%", "shop": "广州 -5%", "rider": "广州 +17%", "newShop": "广州 -15%", "avgOrder": "广州 +10%" },
            { "order": "深圳 -4%", "shop": "深圳 -23%", "rider": "深圳 -5%", "newShop": "深圳 +15%", "avgOrder": "深圳 -4%" },
            { "order": "南京 +10%", "shop": "南京 -6%", "rider": "南京 -7%", "newShop": "南京 -5%", "avgOrder": "南京 -22%" },
            { "order": "杭州 -3%", "shop": "杭州 +20%", "rider": "杭州 +16%", "newShop": "杭州 -11%", "avgOrder": "杭州 -17%" },
            { "order": "合肥 +8%", "shop": "合肥 +17%", "rider": "合肥 -23%", "newShop": "合肥 +6%", "avgOrder": "合肥 -11%" },
            { "order": "济南 -13%", "shop": "济南 -11%", "rider": "济南 +6%", "newShop": "济南 -7%", "avgOrder": "济南 +18%" },
            { "order": "太原 -11%", "shop": "太原 -10%", "rider": "太原 +18%", "newShop": "太原 -14%", "avgOrder": "太原 -2%" },
            { "order": "成都 +19%", "shop": "成都 -6%", "rider": "成都 +14%", "newShop": "成都 -19%", "avgOrder": "成都 +10%" },
            { "order": "重庆 -12%", "shop": "重庆 +12%", "rider": "重庆 +12%", "newShop": "重庆 +7%", "avgOrder": "重庆 -3%" },
            { "order": "苏州 +15%", "shop": "苏州 +18%", "rider": "苏州 -8%", "newShop": "苏州 -3%", "avgOrder": "苏州 +4%" },
            { "order": "无锡 -15%", "shop": "无锡 -19%", "rider": "无锡 -14%", "newShop": "无锡 +21%", "avgOrder": "无锡 -21%" },
            { "order": "常州 +12%", "shop": "常州 +10%", "rider": "常州 +5%", "newShop": "常州 -22%", "avgOrder": "常州 -13%" },
            { "order": "温州 -14%", "shop": "温州 -16%", "rider": "温州 -15%", "newShop": "温州 +14%", "avgOrder": "温州 +17%" },
            { "order": "哈尔滨 +5%", "shop": "哈尔滨 -18%", "rider": "哈尔滨 -18%", "newShop": "哈尔滨 -18%", "avgOrder": "哈尔滨 -20%" },
            { "order": "长春 +14%", "shop": "长春 -5%", "rider": "长春 -17%", "newShop": "长春 +18%", "avgOrder": "长春 +4%" },
            { "order": "大连 -4%", "shop": "大连 -15%", "rider": "大连 -22%", "newShop": "大连 +14%", "avgOrder": "大连 +14%" },
            { "order": "沈阳 -1%", "shop": "沈阳 -21%", "rider": "沈阳 -15%", "newShop": "沈阳 +24%", "avgOrder": "沈阳 +8%" },
            { "order": "拉萨 +18%", "shop": "拉萨 +5%", "rider": "拉萨 -6%", "newShop": "拉萨 -24%", "avgOrder": "拉萨 -10%" },
            { "order": "呼和浩特 +14%", "shop": "呼和浩特 -12%", "rider": "呼和浩特 +8%", "newShop": "呼和浩特 +9%", "avgOrder": "呼和浩特 -21%" },
            { "order": "武汉 -21%", "shop": "武汉 +13%", "rider": "武汉 -10%", "newShop": "武汉 -14%", "avgOrder": "武汉 +10%" },
            { "order": "南宁 -22%", "shop": "南宁 +23%", "rider": "南宁 -9%", "newShop": "南宁 +6%", "avgOrder": "南宁 -12%" }
        ] // 初始数据
    }),
    actions: {
        // 更新数据,并保持 RowIndex 一致
        setAllUserData(newData: UserData[]) {
            // 更新数据时可以保持 RowIndex
            this.Alluserdata = newData.map((item, index) => ({
                ...item,
                Rowindex: index + 1 // 给每一行加上递增的 RowIndex,从 1 开始
            }));
            console.log("Store updated");
        },
        // 添加新数据
        addData(data: UserData) {
            const newRowIndex = this.Alluserdata.length ? Math.max(...this.Alluserdata.map(item => item.Rowindex!)) + 1 : 1;
            this.Alluserdata.push({ ...data, Rowindex: newRowIndex });
        },

        getAllUserData() {
            return this.Alluserdata;
        }
    }
});
App.vue
<template>
  <div class="Wrapper">
    <div class="PanListWrapper">
      <PanList></PanList>
    </div>
  </div>
</template>

<script setup lang="ts">
import PanList from './components/PanList/index.vue'

</script>

<style scoped lang="less">
.Wrapper {
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;

  .PanListWrapper {
    width: 700px;
    height: 700px;
  }
}
</style>

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

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

相关文章

软件供应链十年:探索开源的增长、风险和未来

回顾软件供应链状况报告的 10 年既是一个里程碑&#xff0c;也是一次行动号召。在过去十年中&#xff0c;开源消费改变了软件开发的世界。我们看到了前所未有的创新&#xff0c;但也出现了新的挑战&#xff0c;特别是在管理软件供应链的安全性和完整性方面。 在 Sonatype&…

基于SpringBoot民宿预订系统小程序【附源码】

效果如下&#xff1a; 管理员登录界面 管理员功能界面 用户管理界面 房东管理界面 小程序首页界面 民宿房间界面 功能界面 研究背景 随着旅游业的蓬勃发展和人们对旅行体验的不断追求&#xff0c;民宿作为一种独特的住宿方式&#xff0c;因其个性化、温馨及富含地方特色的服务…

disabled状态el-form下el-button的disabled的精细化控制

有一个很复杂的表单&#xff0c;支持编辑和查看两种模式。 查看时当然不希望编辑&#xff0c;最好是区分模式&#xff0c;在编辑模式下直接用div显示而不是用表单元素。这样工作量就有点大。那就考虑使用表单元素的disabled来让其不能编辑。如果每个表单元素都写这个玩意也是…

ssm职业高中学情成绩系统设计+jsp

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 摘 要 I Abstract II 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环…

codeforces round976 div2

A find minimum operations 思路&#xff1a;将所给的n变成k进制数&#xff0c;答案就是n的k进制形式下的位数之和 代码&#xff1a; #include <bits/stdc.h> using namespace std;typedef long long ll;ll n, k;void solve() {cin >> n >> k;ll cnt 0…

详解Spotbugs-maven-plugin(报告如何生成html测试报告)

Spotbugs介绍 SpotBugs是Findbugs的继任者&#xff08;Findbugs已经不再维护&#xff09;&#xff0c;用于对Java代码进行静态分析&#xff0c;查找相关的漏洞&#xff0c;SpotBugs比Findbugs拥有更多的校验规则。静态分析会检查Java字节码&#xff08;.class文件&#xff09;…

专题十一_递归_回溯_剪枝_综合练习_算法专题详细总结

目录 1. 找出所有⼦集的异或总和再求和&#xff08;easy&#xff09; 解析&#xff1a; 方法一&#xff1a; 解法二&#xff1a; 总结&#xff1a; 2. 全排列 Ⅱ&#xff08;medium&#xff09; 解析&#xff1a; 解法一&#xff1a;只关心“不合法”的分支 解法二&…

AI比诺奖得主更聪明。。。

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 AI圈又发生了哪些新鲜事&#xff1f; 特斯拉Optimus人形机器人亮相&#xff1a;日常任务好帮手 特斯拉在Cybercab活动上展示了其新款人形机器人Optimus&#xff0c;这款机器人能够执行拿包裹、浇水等…

CentOS快速配置网络Docker快速部署

CentOS快速配置网络&&Docker快速部署 CentOS裸机Docker部署1.联通外网2.配置CentOS镜像源3.安装Docker4.启动Docker5.CentOS7安装DockerCompose Bug合集ERROR [internal] load metadata for docker.io/library/java:8-alpineError: Could not find or load main class …

20241013组会

文章&#xff1a;A learnable end-edge-cloud cooperative network for driving emotion sensing 引言&#xff1a; 驾驶员的情绪状态直接影响安全驾驶。在“车-人-路-云”一体化控制框架下&#xff0c;我们提出了一种端-边-云协同情感感知网络模型&#xff08;EEC-Net&#x…

Android平台RTSP|RTMP播放器PK:VLC for Android还是SmartPlayer?

好多开发者&#xff0c;希望在Android端低延迟的播放RTMP或RTSP流&#xff0c;本文就目前市面上主流2个直播播放框架&#xff0c;做个简单的对比。 VLC for Android VLC for Android 是一款功能强大的多媒体播放器&#xff0c;具有以下特点和功能&#xff1a; 广泛的格式支持…

FPAG学习(5)-三种方法实现LED流水灯

目录 1.移位实现LED流水灯 1.1创建工程及源文件代码 1.1.1源代码 1.1.2仿真代码 1.1.3仿真 1.2实验结果 1.2.1总结 2.循环移位实现LED流水灯 3.38译码器实现LED流水灯 3.1原理 3.2源程序 1.移位实现LED流水灯 1.1创建工程及源文件代码 1.1.1源代码 利用计数器计数到…

【深度学习】经典的深度学习模型-01 开山之作:CNN卷积神经网络LeNet-5

【深度学习】经典的深度学习模型-01 开山之作&#xff1a;CNN卷积神经网络LeNet-5 Note: 草稿状态&#xff0c;持续更新中&#xff0c;如果有感兴趣&#xff0c;欢迎关注。。。 0. 论文信息 article{lecun1998gradient, title{Gradient-based learning applied to document r…

【智能算法应用】长鼻浣熊优化算法求解二维路径规划问题

摘要 本文采用长鼻浣熊优化算法 (Coati Optimization Algorithm, COA) 求解二维路径规划问题。COA 是一种基于长鼻浣熊的觅食和社群行为的智能优化算法&#xff0c;具有快速收敛性和较强的全局搜索能力。通过仿真实验&#xff0c;本文验证了 COA 在复杂环境下的路径规划性能&a…

【微服务】springboot3 集成 Flink CDC 1.17 实现mysql数据同步

目录 一、前言 二、常用的数据同步解决方案 2.1 为什么需要数据同步 2.2 常用的数据同步方案 2.2.1 Debezium 2.2.2 DataX 2.2.3 Canal 2.2.4 Sqoop 2.2.5 Kettle 2.2.6 Flink CDC 三、Flink CDC介绍 3.1 Flink CDC 概述 3.1.1 Flink CDC 工作原理 3.2 Flink CDC…

数据结构:栈的创建、使用以及销毁

这里写目录标题 栈的结构与概念栈底层结构的选取栈的代码实现&#xff08;stack&#xff09;头文件&#xff08;stack.h&#xff09;栈的初始化栈的销毁入栈出栈获取栈顶数据获取栈大小代码的测试 栈的结构与概念 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的…

【算法篇】动态规划类(1)(笔记)

目录 一、理论基础 1. 大纲 2. 动态规划的解题步骤 二、LeetCode 题目 1. 斐波那契数 2. 爬楼梯 3. 使用最小花费爬楼梯 4. 不同路径 5. 不同路径 II 6. 整数拆分 7. 不同的二叉搜索树 一、理论基础 1. 大纲 动态规划&#xff0c;英文&#xff1a;Dynamic Programm…

企业水、电、气、热等能耗数据采集系统

介绍 通过物联网技术&#xff0c;采集企业水、电、气、热等能耗数据&#xff0c;帮企业建立能源管理体系&#xff0c;找到跑冒滴漏&#xff0c;从而为企业节能提供依据。 进一步为企业实现碳跟踪、碳盘查、碳交易、谈汇报的全生命过程。 为中国碳达峰-碳中和做出贡献。 针对客…

【C++进阶】set的使用

1. 序列式容器和关联式容器 前面&#xff0c;我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间⼀般没有紧…

【工具箱】Flash基础及“SD NAND Flash”的测试例程

目录 一、“FLASH闪存”是什么&#xff1f; 1. 简介 2. 分类 3. 性能 4.可靠性 5.易用性 二、SD NAND Flash 1. 概述 2. 特点 3. 引脚分配 4. 数据传输模式 5. SD NAND寄存器 6. 通电图 7. 参考设计 三、STM32测试例程 1. 初始化 2. 单数据块测试 3. 多数据块…