独墅湖高教创新区危化品智慧管控平台(新危化品)
马宇豪
2025-04-24 235a109b3b461c7acbd1d7bb4f7e920075de2b9e
src/views/hazardousChemicals/bigScreen/components/midBottom.vue
@@ -1,19 +1,99 @@
<template>
  <div class="charts-container">
    <div id="preWarning"></div>
    <div class="table-wrapper">
      <table class="scrollable-table">
        <thead>
        <tr>
          <th>预警信息</th>
          <th>预警时间</th>
        </tr>
        </thead>
      </table>
      <div class="scroll-viewport" ref="viewport">
        <div class="scroll-content" :style="contentStyle">
          <table class="scrollable-table">
            <tbody>
            <tr v-for="(item,index) in warningData" :key="item.id">
              <td>{{ item.warningInfo }}</td>
              <td>{{ item.warningTime }}</td>
            </tr>
            <tr v-for="(item,index) in loopData" :key="`loop-${item.id}`">
              <td>{{ item.warningInfo }}</td>
              <td>{{ item.warningTime }}</td>
            </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import * as echarts from 'echarts';
import {onMounted} from "vue";
import {computed, onBeforeUnmount, onMounted, ref} from "vue";
import {getCompanyMessage, getDailywarningCount} from "@/api/monitor/screenCharts";
import {ElMessage} from "element-plus";
const warningData = [
  {warningInfo: '超期预警',warningTime: '2025-04-24 13:18:41' },
  {warningInfo: '超期预警',warningTime: '2025-04-23 13:00:21' },
  {warningInfo: '超期预警',warningTime: '2025-04-20 10:11:34' },
  {warningInfo: '超期预警',warningTime: '2025-04-18 09:28:51' },
  {warningInfo: '超期预警',warningTime: '2025-04-16 08:18:21' },
  {warningInfo: '超期预警',warningTime: '2025-04-15 05:12:21' },
  {warningInfo: '超期预警',warningTime: '2025-04-14 04:11:41' }
]
// 配置参数
const visibleRows = 5 // 显示的行数
const scrollSpeed = 0.5 // 每次滚动的像素数
const rowHeight = 36 // 行高,与CSS一致
const viewport = ref(null)
const scrollPosition = ref(0)
let animationFrame = null
onMounted(()=>{
  getList()
// 设置视口高度
  if (viewport.value) {
      viewport.value.style.height = `${visibleRows * rowHeight}px`
  }
  // 延迟启动滚动,确保初始渲染完成
  setTimeout(() => {
    scrollAnimation()
  }, 100)
})
onBeforeUnmount(() => {
  if (animationFrame) {
    cancelAnimationFrame(animationFrame)
  }
})
// 复制前几行数据用于循环
const loopData = computed(() => {
  return warningData.slice(0, visibleRows)
})
// 内容区域样式
const contentStyle = computed(() => {
  return {
    transform: `translateY(-${scrollPosition.value}px)`
  }
})
// 滚动动画
const scrollAnimation = () => {
  const totalHeight = warningData.length * rowHeight
  const loopHeight = loopData.value.length * rowHeight
  // 更新滚动位置
  scrollPosition.value += scrollSpeed
  // 当滚动到循环数据部分时,重置位置实现无缝衔接
  if (scrollPosition.value >= totalHeight) {
    scrollPosition.value -= totalHeight
  }
  animationFrame = requestAnimationFrame(scrollAnimation)
}
const getList = async () => {
  const res = await getDailywarningCount()
@@ -105,10 +185,66 @@
.charts-container{
  width: 100%;
  height: 100%;
  display: flex;
}
#preWarning{
  width: 100%;
  flex: 2;
  height: 100%;
}
.table-wrapper {
  position: relative;
  flex: 1;
  height: 100%;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 2px;
  overflow: hidden;
  .scrollable-table {
    width: 100%;
    border-collapse: collapse;
    th,td {
      padding: 12px 15px;
      color: #fff;
      text-align: left;
      border-bottom: 1px solid rgba(255,255,255,.1);
      height: 36px; /* 与rowHeight一致 */
      box-sizing: border-box;
      font-size: 12px;
      font-weight: normal;
    }
    th {
      position: sticky;
      top: 0;
      z-index: 10; /* 确保表头在内容之上 */
    }
    tr{
      background: rgb(6,38,87);
      &:nth-of-type(2n){
        background: rgb(19,72,127);
      }
    }
    thead tr{
      background: rgba(0,0,0,0);
    }
  }
  .scroll-viewport {
    position: relative;
    overflow: hidden;
    .scroll-content {
      will-change: transform; /* 优化性能 */
    }
    .danger {
      color: #ff2f2f;
      animation: blink 1s infinite;
    }
    .warning {
      color: yellow;
      animation: blink 1s infinite;
    }
  }
}
</style>