el-table表格自动循环向上滚动鼠标放上去停止,移开恢复

排序的图标是两个图片,点击向后端发请求带不同的参数

javascript 复制代码
<template>
    <div style="height: 100%" class="table-content">
      <div :style="{ 'position': 'absolute', 'z-index': '9999', 'right': '3%', 'top': 0 }"
        :class="`tagBtn bg${centerKey}`">
        <div class="item" @click="centerKey = 1"></div>
        <div class="item" @click="centerKey = 2"></div>
      </div>
      <div style=" flex:1;height:0px" class="table-info" id="table">
        <el-table class="temp-table" ref="tableRef" @current-change="currChange" highlight-current-row
          :row-class-name="tableRowClassName" :data="tableData" size="mini" height="100%" :key="rank"
          @cell-mouse-enter="handleMouseOver" @cell-mouse-leave="handleMouseLeave">
          <el-table-column prop="rank" label="排名" align="center" min-width="80" show-overflow-tooltip>
            <template #header>
              <div style="display: flex;flex-direction: row;align-items: center;justify-content: center;"
                @click="sortChange">
                <span>排名</span>
                <span style="cursor: pointer;" v-if="show"><img
                    src="../../../assets/imgs/jiangxu.png" /></span>
                <span style="cursor: pointer;" v-if="!show"><img
                    src="../../../assets/imgs/shengxu.png" /></span>
              </div>
            </template>
            <template #default="scope">
              <span>{{ scope.row.rank }}</span>
            </template>
          </el-table-column>
          <el-table-column label="xx" prop="COMMUNITYNAME" min-width="120" align="left" show-overflow-tooltip>
          </el-table-column>
          <el-table-column label="xxx" prop="AVGTEMP" min-width="85" align="center" show-overflow-tooltip>
          </el-table-column>
          <el-table-column v-if="centerKey === 1" label="xxx" prop="LOWTEMP" min-width="120" align="center"
            show-overflow-tooltip>
          </el-table-column>
          <el-table-column v-else label="xxx" prop="OVERTEMP" min-width="120" align="center" show-overflow-tooltip>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </Card>
</template>

<script lang="ts">
import { defineComponent, reactive, ref, toRefs, watch, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { useAppStore } from '@/store/modules/app'
import { listRoomTempRange } from '@/api/Tou/index.ts'


export default defineComponent({
  components: {
  },
  props: {
    intervalTime: {
      type: Number,
      default: 20
    }
  },
  setup(props) {
    // store
    const appStore = useAppStore()
    const router = useRouter()

    const state = reactive({
      tableRef: null,
      tableData: [],
      centerKey: 1,
      type: 0,
      timer: null,
      distance: 0,
      mouserEnter: false, //用来标识鼠标是否在表格区域(防止请求接口之后,鼠标还指示在图表上)
      mouseScroll: false,
      currdata: null,
      show: true,
    }) as any

    const methods = {
      sortChange() {
        state.show = !state.show
        if (state.show === true) {
          state.type = 0 // 0降序
          methods.getData(state.type);
        } else {
          state.type = 1 // 1升序
          methods.getData(state.type);
        }
      },
      getData(type: number) {
        let params = {
          temporder: type == 0 ? 0 : 1, // 1升序 0降序
        }
        listRoomTempRange(params)
          .then(res => {
            // 处理成功的响应
            // 返回的数据顺序是后端处理好的,这里只需要按顺序添加编号即可            
            const data = res?.data.map((item: any, index: number) => {
              return {
                ...item,
                rank: index + 1,
              }
            })
            methods.initData(data);
          })
          .catch(error => {
            // 处理错误的响应
            console.error(error);
          });
      },
        
      // 设置行颜色
      tableRowClassName({ row, rowIndex }) {
        if (rowIndex % 2 == 0) {
          return "warning-row";
        } else if (rowIndex % 2 == 1) {
          return "success-row";
        }
        return "";
      },

      // 切换选项抛出事件
      currChange(val, i) {
        state.currdata = val;
      },

      initData(data) {
        //根据行数判断表格是否溢出,溢出滚动,否则不滚动
        if (data.length > 9) {

          state.tableData = [...data, ...data];
        } else {
          state.tableData = data;
        }
        //如果当前有选中的话,则请求接口之后高亮此项
        if (state.currdata) {
          let index = state.tableData.filter((r) => {
            if (r.COMMUNITYID == state.currdata.COMMUNITYID) {
              return r;
            }
          });
          state.tableRef.setCurrentRow(index[0]);
        } else {
          // 初始时是默认选中第一条
          state.tableRef.setCurrentRow(state.tableData[0]);
        }
        nextTick(() => {
          state.tableRef && state.tableRef.doLayout(); //解决表格错位
          if (data.length > 9 && !state.mouserEnter) {
            methods.scroll();
            methods.mouseWheel();
          }
        });
      },

      // 无缝滚动
      scroll() {
        window.clearInterval(state.timer);
        state.mouserEnter = true;
        const tableEl = document.getElementById('table')
        const bodyContent = tableEl.getElementsByClassName('el-table__body')[0];
        const bodyWrapperHeight = tableEl.getElementsByClassName('el-table__body-wrapper')[0].clientHeight;
        const bodyContentHeight = tableEl.getElementsByClassName('el-table__body')[0].clientHeight;
        if (bodyWrapperHeight < bodyContentHeight) {
          state.timer = setInterval(() => {
            state.distance -= 1;
            bodyContent.style.top = `${state.distance % bodyContent.offsetHeight / 2}px`;
          }, 20);
        }
      },
      // 滚轮滚动
      mouseWheel() {
        state.mouserEnter = true;
        const tableEl = document.getElementById('table')
        const bodyWrapper = tableEl.getElementsByClassName('el-table__body-wrapper')[0];
        const bodyContent = tableEl.getElementsByClassName('el-table__body')[0];
        bodyWrapper.addEventListener('mousewheel', (e) => {
          // 滚动table的时候,禁止屏幕滚动
          e.preventDefault();
          state.distance -= e.deltaY / 2;
          if (state.distance > 0) {
            state.distance = 0;
          }
          if (bodyContent.offsetHeight > bodyWrapper.offsetHeight) {
            bodyContent.style.top = `${state.distance % bodyContent.offsetHeight / 2}px`;
          }
        }, { passive: false })
      },
      // 鼠标移入停止滚动
      handleMouseOver() {
        window.clearInterval(state.timer);
        state.mouserEnter = true;
      },
      // 鼠标移出,恢复滚动
      handleMouseLeave() {
        methods.scroll();
      },
    }

    const timer2 = ref(null)

    onMounted(() => {
      methods.getData(0)
      timer2.value = setInterval(() => {
        methods.getData(state.type)
      }, 1000 * props.intervalTime);
    })

    onUnmounted(() => {
      clearInterval(timer2.value);
    })

    return {
      ...toRefs(state),
      ...methods,
    }
  }
})
</script>

<style lang="less" scoped>
.card-info {
  position: relative;
}

.table-content {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 3%;

  .table-info {
    height: 0;
    flex: 1;
    border-radius: 6px;
    overflow: hidden;
  }

  .tagBtn {
    width: 129px;
    height: 23px;
    background: url(../../../assets/imgs/upToPar1.png) no-repeat;
    background-size: 100% 100%;
    display: flex;
    flex-direction: row;
    justify-content: center;

    &.bg2 {
      background: url(../../../assets/imgs/upToPar2.png) no-repeat;
      background-size: 100% 100%;
    }

    &>.item {
      width: 65px;
      cursor: pointer;

      &:last-child {
        margin-left: 4px;

      }
    }
  }
}

.el-table {
  border-radius: 6px;
}

:deep(.el-table td.el-table__cell div) {
  padding-left: 8px !important;
  padding-right: 8px !important;
  font-size: 12px;
  font-family: MicrosoftYaHei;
  color: #C0D7FB;
  line-height: 16px;
}

:deep(.el-table th>.cell) {
  text-align: center;
}

::v-deep .el-table .warning-row {
  height: 36px;
  background: #070C33;
  // background: linear-gradient(90deg, rgba(0, 15, 35, 0) 0%, #000E23 100%);
}

::v-deep .el-table .success-row {
  height: 36px;
  background: #0A1749;
  // background: rgba(20, 57, 140, 0.34);
}

::v-deep .el-table .current-row {
  height: 36px;
  background: #043A90;
}

::v-deep .el-table--scrollable-y .el-table__body-wrapper {
  overflow: hidden;
}

::v-deep .el-table__body {
  position: relative;
  min-height: 100%;
  width: 100%;
}

// 表头样式
.el-table .el-table__header th {
  background: rgba(26, 131, 255, 0.29);
}

:deep(.el-table__header) {
  height: 46px !important;
}

:deep(.el-table thead th.el-table__cell ) {
  color: #FFFFFF !important;
  font-size: 14px !important;
}

::v-deep .el-table_3_column_11 .is-left .is-leaf {
  border-radius: 6px 0px 0px 6px;
}

:deep(.el-table__body tr.current-row>td) {
  color: #FFFFFF !important;
  background-color: #0073FF !important;
}
</style>
相关推荐
梵得儿SHI14 小时前
Vue 模板语法深度解析:从文本插值到 HTML 渲染的核心逻辑
前端·vue.js·html·模板语法·文本插值·v-text指令·v-html指令
listhi52015 小时前
Vue.js 3的组合式API
android·vue.js·flutter
WYiQIU16 小时前
高级Web前端开发工程师2025年面试题总结及参考答案【含刷题资源库】
前端·vue.js·面试·职场和发展·前端框架·reactjs·飞书
夏之小星星16 小时前
Springboot结合Vue实现分页功能
vue.js·spring boot·后端
韩立学长16 小时前
【开题答辩实录分享】以《自动售货机刷脸支付系统的设计与实现》为例进行答辩实录分享
vue.js·spring boot·后端
静西子16 小时前
Vue标签页切换时的异步更新问题
前端·javascript·vue.js
时间的情敌16 小时前
Vue 3.0 源码导读
前端·javascript·vue.js
天天向上102420 小时前
vue 网站导航栏
前端·javascript·vue.js
JIngJaneIL1 天前
财务管理|基于SprinBoot+vue的个人财务管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·财务管理系统
qq_338032921 天前
VUE的生命周期钩子,vue2和vue3的生命周期钩子的核心差异
前端·javascript·vue.js