|
@@ -1,200 +1,183 @@
|
|
<template>
|
|
<template>
|
|
- <div class="scrolling-table-container">
|
|
|
|
|
|
+ <div class="auto-scroll-container">
|
|
|
|
+ <!-- :height="tableHeight" :height="tableData.length>4?tableHeight:'auto'"-->
|
|
<el-table
|
|
<el-table
|
|
- :data="visibleData"
|
|
|
|
- :height="tableHeight"
|
|
|
|
- stripe
|
|
|
|
- style="width: 100%;background: transparent;"
|
|
|
|
- header-row-class-name="fixed-header"
|
|
|
|
ref="scrollTable"
|
|
ref="scrollTable"
|
|
|
|
+ :data="tableData"
|
|
|
|
+
|
|
|
|
+ :height="tableHeight"
|
|
|
|
+ @mouseenter.native="pauseScroll"
|
|
|
|
+ @mouseleave.native="resumeScroll"
|
|
|
|
+ @scroll.passive="handleScroll"
|
|
|
|
+ :style="'width: 100%;background: transparent;max-height:'+tableHeight"
|
|
>
|
|
>
|
|
- <el-table-column
|
|
|
|
- align='center'
|
|
|
|
- prop="date"
|
|
|
|
- label="告警任务"
|
|
|
|
- width="100">
|
|
|
|
- </el-table-column>
|
|
|
|
- <el-table-column
|
|
|
|
- align='center'
|
|
|
|
- prop="name"
|
|
|
|
- label="告警内容"
|
|
|
|
- width="90">
|
|
|
|
- <template slot-scope="scope">
|
|
|
|
- <span :class="[scope.row.name == '1'||scope.row.name == '5'? 'coa' : scope.row.name == '2'? 'cob':scope.row.name == '3'||scope.row.name == '4'? 'coc' : '']" >{{ statusFormat(scope.row.name,statusOptions)}}</span>
|
|
|
|
- </template>
|
|
|
|
- </el-table-column>
|
|
|
|
- <el-table-column
|
|
|
|
- align='center'
|
|
|
|
- prop="createTime"
|
|
|
|
- label="告警时间">
|
|
|
|
- <!-- <template slot-scope="scope">
|
|
|
|
- <span>{{ parseTime(scope.row.createTime) }}</span>
|
|
|
|
- </template> -->
|
|
|
|
- </el-table-column>
|
|
|
|
-
|
|
|
|
|
|
+ <el-table-column :cell-style="{ whiteSpace: 'pre-line' }" v-for="(ite,idx) in columns" :key="idx" align='center' :prop="ite.prop" :label="ite.label"
|
|
|
|
+ :width="ite.width">
|
|
|
|
+ <template slot-scope="scope" >
|
|
|
|
+ <span v-if="ite.type&&ite.type=='katype'" :class="[scope.row.name == '1'||scope.row.name == '5'? 'coa' : scope.row.name == '2'? 'cob':scope.row.name == '3'||scope.row.name == '4'? 'coc' : '']" >{{ statusFormat(scope.row.name,statusOptions)}}</span>
|
|
|
|
+
|
|
|
|
+ <div v-else-if="ite.type&&ite.type=='hh'">
|
|
|
|
+ <div>{{ scope.row[ite.prop]}}</div>
|
|
|
|
+ <div>{{ scope.row['time']}}</div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else >{{ scope.row[ite.prop] }}</div>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+
|
|
</el-table>
|
|
</el-table>
|
|
|
|
+
|
|
|
|
+ <!-- 可选的滚动控制按钮 -->
|
|
|
|
+ <!-- <div class="scroll-controls">
|
|
|
|
+ <el-button @click="scrollToTop">滚动到顶部</el-button>
|
|
|
|
+ <el-button @click="toggleAutoScroll">
|
|
|
|
+ {{ autoScrollEnabled ? '暂停滚动' : '继续滚动' }}
|
|
|
|
+ </el-button>
|
|
|
|
+ </div> -->
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
export default {
|
|
export default {
|
|
- name: 'ScrollingTable',
|
|
|
|
|
|
+ name: 'AutoScrollTable',
|
|
props: {
|
|
props: {
|
|
|
|
+ columns: {
|
|
|
|
+ type: Array,
|
|
|
|
+ required: true
|
|
|
|
+ },
|
|
data: {
|
|
data: {
|
|
type: Array,
|
|
type: Array,
|
|
- required: true,
|
|
|
|
- default: () => []
|
|
|
|
|
|
+ required: true
|
|
},
|
|
},
|
|
- statusOptions:{
|
|
|
|
|
|
+ statusOptions: {
|
|
type: Array,
|
|
type: Array,
|
|
- required: true,
|
|
|
|
default: () => []
|
|
default: () => []
|
|
},
|
|
},
|
|
- // columns: {
|
|
|
|
- // type: Array,
|
|
|
|
- // required: true,
|
|
|
|
- // default: () => []
|
|
|
|
- // },
|
|
|
|
- rowHeight: {
|
|
|
|
- type: Number,
|
|
|
|
- default: 28 // ElementUI默认行高
|
|
|
|
- },
|
|
|
|
- visibleRows: {
|
|
|
|
- type: Number,
|
|
|
|
- default: 5
|
|
|
|
- },
|
|
|
|
- refreshInterval: {
|
|
|
|
- type: Number,
|
|
|
|
- default: 30000 // 30秒
|
|
|
|
- },
|
|
|
|
- scrollInterval: {
|
|
|
|
- type: Number,
|
|
|
|
- default: 3000 // 3秒滚动一次
|
|
|
|
- }
|
|
|
|
|
|
+ tableHeight:{
|
|
|
|
+ type: String,
|
|
|
|
+ default: '100px' // ElementUI默认行高
|
|
|
|
+ },
|
|
|
|
+ scrollTop:{
|
|
|
|
+ type: Number,
|
|
|
|
+ default: 36 // 滚动的高度
|
|
|
|
+ }
|
|
},
|
|
},
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
- currentIndex: 0,
|
|
|
|
- scrollTimer: null,
|
|
|
|
- refreshTimer: null,
|
|
|
|
- isScrolling: false,
|
|
|
|
- tableHeight: null,
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- computed: {
|
|
|
|
- visibleData() {
|
|
|
|
- // 如果数据不足visibleRows条,直接显示所有数据
|
|
|
|
- if (this.data.length <= this.visibleRows) {
|
|
|
|
- return this.data
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 计算当前应该显示的数据范围
|
|
|
|
- let endIndex = this.currentIndex + this.visibleRows
|
|
|
|
- if (endIndex > this.data.length) {
|
|
|
|
- // 如果超出数组长度,从开头补足
|
|
|
|
- return [
|
|
|
|
- ...this.data.slice(this.currentIndex),
|
|
|
|
- ...this.data.slice(0, endIndex - this.data.length)
|
|
|
|
- ]
|
|
|
|
- } else {
|
|
|
|
- return this.data.slice(this.currentIndex, endIndex)
|
|
|
|
- }
|
|
|
|
|
|
+ tableData: [],
|
|
|
|
+ autoScrollEnabled: true,
|
|
|
|
+ scrollInterval: null,
|
|
|
|
+ dataRefreshInterval: null,
|
|
|
|
+ isUserScrolling: false,
|
|
|
|
+ lastScrollTime: 0,
|
|
}
|
|
}
|
|
},
|
|
},
|
|
mounted() {
|
|
mounted() {
|
|
- // this.calculateTableHeight()
|
|
|
|
- // this.initScroll()
|
|
|
|
- // this.initRefresh()
|
|
|
|
-
|
|
|
|
- // 监听窗口变化重新计算高度
|
|
|
|
- window.addEventListener('resize', this.calculateTableHeight)
|
|
|
|
|
|
+ this.loadData();
|
|
|
|
+ // this.startAutoScroll();
|
|
|
|
+ // this.setupDataRefresh();
|
|
},
|
|
},
|
|
beforeDestroy() {
|
|
beforeDestroy() {
|
|
- this.clearTimers()
|
|
|
|
- window.removeEventListener('resize', this.calculateTableHeight)
|
|
|
|
|
|
+ this.stopAutoScroll();
|
|
|
|
+ this.clearDataRefresh();
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
- statusFormat(row, list) {
|
|
|
|
- return this.selectDictLabel(list, row);
|
|
|
|
- },
|
|
|
|
- calculateTableHeight() {
|
|
|
|
- // 计算表格高度 = 表头高度 + 可见行数 * 行高
|
|
|
|
- const headerHeight = 48 // ElementUI默认表头高度
|
|
|
|
- this.tableHeight = headerHeight + (this.visibleRows * this.rowHeight)
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- initScroll() {
|
|
|
|
- this.clearScrollTimer()
|
|
|
|
-
|
|
|
|
- // 如果数据不足visibleRows条,不需要滚动
|
|
|
|
- if (this.data.length <= this.visibleRows) {
|
|
|
|
- return
|
|
|
|
|
|
+ statusFormat(row, list) {
|
|
|
|
+ return this.selectDictLabel(list, row);
|
|
|
|
+ },
|
|
|
|
+ async loadData() {
|
|
|
|
+ try {
|
|
|
|
+ // const data = await this.fetchData();
|
|
|
|
+ this.tableData = this.data;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('加载数据失败:', error);
|
|
}
|
|
}
|
|
-
|
|
|
|
- this.scrollTimer = setInterval(() => {
|
|
|
|
- this.scrollToNext()
|
|
|
|
- }, this.scrollInterval)
|
|
|
|
},
|
|
},
|
|
-
|
|
|
|
- scrollToNext() {
|
|
|
|
- if (this.isScrolling) return
|
|
|
|
|
|
+ startAutoScroll() {
|
|
|
|
+ this.stopAutoScroll();
|
|
|
|
|
|
- this.isScrolling = true
|
|
|
|
- const tableBody = this.$refs.scrollTable.$el.querySelector('.el-table__body-wrapper')
|
|
|
|
|
|
+ const tableWrapper = this.$refs.scrollTable?.bodyWrapper;
|
|
|
|
+ if (!tableWrapper) return;
|
|
|
|
|
|
- // 添加过渡效果
|
|
|
|
- tableBody.style.transition = 'transform 0.5s ease-in-out'
|
|
|
|
- tableBody.style.transform = `translateY(-${this.rowHeight}px)`
|
|
|
|
|
|
+ // 初始滚动位置设为0
|
|
|
|
+ tableWrapper.scrollTop = 0;
|
|
|
|
|
|
- // 动画结束后更新数据
|
|
|
|
- setTimeout(() => {
|
|
|
|
- tableBody.style.transition = 'none'
|
|
|
|
- tableBody.style.transform = 'translateY(0)'
|
|
|
|
|
|
+ this.scrollInterval = setInterval(() => {
|
|
|
|
+ if (!this.autoScrollEnabled || this.isUserScrolling) return;
|
|
|
|
|
|
- // 更新当前索引
|
|
|
|
- this.currentIndex = (this.currentIndex + 1) % this.data.length
|
|
|
|
|
|
+ const tableWrapper = this.$refs.scrollTable?.bodyWrapper;
|
|
|
|
+ if (!tableWrapper) return;
|
|
|
|
|
|
- // 强制重新渲染以确保DOM更新
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
- this.isScrolling = false
|
|
|
|
- })
|
|
|
|
- }, 500)
|
|
|
|
|
|
+ // 如果已经滚动到底部,回到顶部
|
|
|
|
+ if (tableWrapper.scrollTop + tableWrapper.clientHeight >= tableWrapper.scrollHeight - 2) {
|
|
|
|
+ tableWrapper.scrollTop = 0;
|
|
|
|
+ } else {
|
|
|
|
+ tableWrapper.scrollTop += 2;
|
|
|
|
+ }
|
|
|
|
+ }, 100);
|
|
},
|
|
},
|
|
-
|
|
|
|
- initRefresh() {
|
|
|
|
- this.clearRefreshTimer()
|
|
|
|
- this.refreshTimer = setInterval(() => {
|
|
|
|
- this.$emit('refresh-data')
|
|
|
|
- }, this.refreshInterval)
|
|
|
|
|
|
+ stopAutoScroll() {
|
|
|
|
+ if (this.scrollInterval) {
|
|
|
|
+ clearInterval(this.scrollInterval);
|
|
|
|
+ this.scrollInterval = null;
|
|
|
|
+ }
|
|
},
|
|
},
|
|
-
|
|
|
|
- clearScrollTimer() {
|
|
|
|
- if (this.scrollTimer) {
|
|
|
|
- clearInterval(this.scrollTimer)
|
|
|
|
- this.scrollTimer = null
|
|
|
|
|
|
+ pauseScroll() {
|
|
|
|
+ this.autoScrollEnabled = false;
|
|
|
|
+ },
|
|
|
|
+ resumeScroll() {
|
|
|
|
+ // 如果用户正在手动滚动,不恢复自动滚动
|
|
|
|
+ if (!this.isUserScrolling) {
|
|
|
|
+ this.autoScrollEnabled = true;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
-
|
|
|
|
- clearRefreshTimer() {
|
|
|
|
- if (this.refreshTimer) {
|
|
|
|
- clearInterval(this.refreshTimer)
|
|
|
|
- this.refreshTimer = null
|
|
|
|
|
|
+ toggleAutoScroll() {
|
|
|
|
+ this.autoScrollEnabled = !this.autoScrollEnabled;
|
|
|
|
+ if (this.autoScrollEnabled) {
|
|
|
|
+ this.isUserScrolling = false;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
-
|
|
|
|
- clearTimers() {
|
|
|
|
- this.clearScrollTimer()
|
|
|
|
- this.clearRefreshTimer()
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- watch: {
|
|
|
|
- data() {
|
|
|
|
- // 数据更新时重置索引
|
|
|
|
- this.currentIndex = 0
|
|
|
|
- this.initScroll()
|
|
|
|
|
|
+ handleScroll({ scrollTop }) {
|
|
|
|
+ // 记录最后一次滚动时间
|
|
|
|
+ this.lastScrollTime = Date.now();
|
|
|
|
+
|
|
|
|
+ // 如果用户手动滚动,暂停自动滚动
|
|
|
|
+ if (Math.abs(scrollTop - this.lastScrollTop) > 5) {
|
|
|
|
+ this.isUserScrolling = true;
|
|
|
|
+ this.autoScrollEnabled = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.lastScrollTop = scrollTop;
|
|
|
|
+
|
|
|
|
+ // 如果用户停止滚动超过2秒,恢复自动滚动
|
|
|
|
+ clearTimeout(this.scrollResumeTimeout);
|
|
|
|
+ this.scrollResumeTimeout = setTimeout(() => {
|
|
|
|
+ this.isUserScrolling = false;
|
|
|
|
+ this.autoScrollEnabled = true;
|
|
|
|
+ }, 2000);
|
|
},
|
|
},
|
|
- visibleRows() {
|
|
|
|
- this.calculateTableHeight()
|
|
|
|
|
|
+ scrollToTop() {
|
|
|
|
+ const tableWrapper = this.$refs.scrollTable?.bodyWrapper;
|
|
|
|
+ if (tableWrapper) {
|
|
|
|
+ tableWrapper.scrollTop = 0;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ scrollTo(position) {
|
|
|
|
+ const tableWrapper = this.$refs.scrollTable?.bodyWrapper;
|
|
|
|
+ if (tableWrapper) {
|
|
|
|
+ tableWrapper.scrollTop = position;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ setupDataRefresh() {
|
|
|
|
+ this.clearDataRefresh();
|
|
|
|
+ this.dataRefreshInterval = setInterval(() => {
|
|
|
|
+ this.loadData();
|
|
|
|
+ }, 60000); // 每分钟刷新一次
|
|
|
|
+ },
|
|
|
|
+ clearDataRefresh() {
|
|
|
|
+ if (this.dataRefreshInterval) {
|
|
|
|
+ clearInterval(this.dataRefreshInterval);
|
|
|
|
+ this.dataRefreshInterval = null;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -204,9 +187,10 @@ export default {
|
|
.coa{color: #FFBB37;}
|
|
.coa{color: #FFBB37;}
|
|
.cob{color: #0096FF;}
|
|
.cob{color: #0096FF;}
|
|
.coc{color: #00FFFF;}
|
|
.coc{color: #00FFFF;}
|
|
-::v-deep .el-table tr{background-color: transparent;color: #fff;}
|
|
|
|
-::v-deep .el-table td{border:none;font-size: 14px;height: 28px;padding: 0;}
|
|
|
|
-::v-deep .el-table .el-table__header-wrapper th{background-color: #011C39 !important;color: #fff;padding: 2px 0;height: 27px;box-sizing: border-box;font-size: 14px;border: none;z-index: 10;}
|
|
|
|
|
|
+.aimgs{min-height: 80px;width: 100%;display: flex;align-items: center;justify-content: center;}
|
|
|
|
+::v-deep .el-table tr{background-color: transparent;color: #FFFFFF;}
|
|
|
|
+::v-deep .el-table td{border:none;font-size: 14px;height: 36px;padding: 0;}
|
|
|
|
+::v-deep .el-table .el-table__header-wrapper th{background-color: transparent !important;color: #fff;padding: 2px 0;height: 36px;box-sizing: border-box;font-size: 14px;border: none;z-index: 10;font-weight: bold;}
|
|
::v-deep .el-table__row--striped{background: rgba(185, 223, 250, 0.05) !important}
|
|
::v-deep .el-table__row--striped{background: rgba(185, 223, 250, 0.05) !important}
|
|
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{background-color: transparent;}
|
|
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{background-color: transparent;}
|
|
::v-deep .el-table .current-row > td {
|
|
::v-deep .el-table .current-row > td {
|
|
@@ -223,17 +207,32 @@ export default {
|
|
width: 100%;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
|
|
+::v-deep .el-table__header{width: 100% !important;height: 100%;}
|
|
|
|
+::v-deep .el-table__body{width: 100% !important;height: 100%;}
|
|
|
|
+::v-deep .el-table .cell{padding: 0 2px !important;word-break: break-word;}
|
|
|
|
+.btn{min-width: 82px;display: inline-flex;align-items: center;justify-content: center;font-size: 14px;padding: 0 2px;box-sizing: border-box;height: 23px;color: #FFFFFF;border-radius: 12px;
|
|
|
|
+ &.btna{background: #009944;}
|
|
|
|
+ &.btnb{background: #D85600;}
|
|
|
|
+}
|
|
|
|
+.auto-scroll-container {
|
|
|
|
+ position: relative;
|
|
|
|
+}
|
|
|
|
|
|
-/* 固定表头样式 */
|
|
|
|
-.fixed-header {
|
|
|
|
- position: sticky;
|
|
|
|
- top: 0;
|
|
|
|
- z-index: 10;
|
|
|
|
- // background-color: #fff;
|
|
|
|
|
|
+.scroll-controls {
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+ text-align: center;
|
|
|
|
+}
|
|
|
|
+/* 隐藏滚动条 gutter */
|
|
|
|
+::v-deep .el-table .el-table__body-wrapper::-webkit-scrollbar {
|
|
|
|
+ width: 0 !important;
|
|
|
|
+}
|
|
|
|
+::v-deep .el-table th.gutter {
|
|
|
|
+ display: none;
|
|
}
|
|
}
|
|
|
|
|
|
-/* 表格滚动区域样式 */
|
|
|
|
-.el-table__body-wrapper {
|
|
|
|
- overflow: hidden;
|
|
|
|
|
|
+/* 确保表头和表体对齐 */
|
|
|
|
+::v-deep .el-table colgroup col[name='gutter'] {
|
|
|
|
+ width: 0 !important;
|
|
}
|
|
}
|
|
|
|
+
|
|
</style>
|
|
</style>
|