vue3中自制了一个页面滚动功能和一个暂停、滚动按钮,目前出现的问题是暂停、滚动按钮有时好使有时失效,并且页面自动滚动偶尔会出现页面抖动的问题,求帮忙解决一下
以下是代码
<template>
<div class="home" v-on:scroll="onScroll" ref="scrollContainer">
<div class="header">仓库看板</div>
<div class="home-table">
<table class="homeTable1" border="1" cellspacing="0">
<thead class="table-head">
<th class="bgPrimary">库区</th>
<th class="bgPrimary">层数</th>
<th class="bgPrimary" v-for="(item, index) in 22" :key="index">
{{ (item = item < 10 ? "00" + item : "0" + item) }}
</th>
</thead>
<tbody v-for="(item, index) in filteredList" :key="index">
<tr v-for="(items, indexs) in item.list" :key="indexs">
<th
:rowspan="item.list.length"
class="bgPrimary"
v-if="indexs == 0"
>
{{ item.name }}
</th>
<th class="bgPrimary">{{ item.list.length - indexs }}</th>
<td
v-for="(itemss, indexss) in items.info"
:key="indexss"
:class="
itemss.volmueType == 0
? 'colorEmpty'
: itemss.volmueType > 0 && itemss.volmueType < 50
? 'colorMore'
: itemss.volmueType >= 50 && itemss.volmueType <= 100
? 'colorMore'
: itemss.volmueType > 100
? 'colorMore'
: 'colorPrimary'
"
:style="itemss.volmueType == '-1' ? 'border:none' : ''"
>
{{ itemss.MatName }}
</td>
</tr>
<div class="space"></div>
</tbody>
</table>
</div>
<div class="home-table">
<table class="homeTable1" border="1" cellspacing="0">
<thead>
<th class="bgPrimary">库区</th>
<th class="bgPrimary">层数</th>
<th class="bgPrimary" v-for="(item, index) in 10" :key="index">
{{ (item = item < 10 ? "00" + item : "0" + item) }}
</th>
</thead>
<tbody v-for="(item, index) in filteredElseList" :key="index">
<tr v-for="(items, indexs) in item.list" :key="indexs">
<th
:rowspan="item.list.length"
class="bgPrimary"
v-if="indexs == 0"
>
{{ item.name }}
</th>
<th class="bgPrimary">{{ item.list.length - indexs }}</th>
<td
v-for="(itemss, indexss) in items.info"
:key="indexss"
:class="
itemss.volmueType == 0
? 'colorEmpty'
: itemss.volmueType > 0 && itemss.volmueType < 50
? 'colorMore'
: itemss.volmueType >= 50 && itemss.volmueType <= 100
? 'colorMore'
: itemss.volmueType > 100
? 'colorMore'
: 'colorPrimary'
"
>
{{ itemss.MatName }}
</td>
</tr>
<div class="space"></div>
</tbody>
</table>
</div>
<el-button type="primary" class="floatBtn" @click="handleOnscroll">{{
isPaused ? "开始滚动" : "暂停滚动"
}}</el-button>
</div>
</template>
<script>
import { onMounted, ref, onUnmounted, computed } from "vue";
import { ExecJSON2 } from "@/api/mainPage";
export default {
name: "mainPage",
setup() {
const tableData = ref([]);
const rowstyles = ref();
const areaData = ref(new Array());
const timer = ref();
const scrolling = ref(false);
const timeoutId = ref(null);
const scrollContainer = ref(null);
const intervalId = ref(null);
const isPaused = ref(false);
const filteredList = computed(() => {
if (!tableData.value) {
return [];
}
return tableData.value.filter((item) => item.list.length > 1);
});
const filteredElseList = computed(() => {
return tableData.value.filter((item) => item.list.length == 1);
});
onMounted(() => {
getAllData();
onScroll();
timer.value = setInterval(() => {
getAllData();
location.reload();
}, 30 * 60 * 1000);
});
onUnmounted(() => {
clearInterval(timer);
});
const getAllData = () => {
const param = {
Code: "KB_01",
Data: [
{
WarehouseCode: "01",
},
],
};
ExecJSON2(param)
.then(async (res) => {
if (res.Success == "01") {
tableData.value = await bubbleSort(res.Data1);
}
})
.catch((err) => {
console.log(err, 19);
});
};
const bubbleSort = async (array) => {
for (let i = 0; i < array.length; i++) {
array[i].info = JSON.parse(array[i].info);
let newDataList = [];
for (let j = 0; j < array[i].info.length; j++) {
newDataList.push(array[i].info[j]);
let curNum = parseInt(array[i].info[j].WarehouseLocation, 10);
if (array[i].info[j + 1]) {
let nextNum = parseInt(array[i].info[j + 1].WarehouseLocation, 10);
if (nextNum - curNum > 1) {
for (let j = 1; j < nextNum - curNum; j++) {
newDataList.push({
MatName: "",
WarehouseLocation: (curNum + j).toString().padStart(3, "0"),
WarehouseLayers: array[i].info[j].WarehouseLayers,
WarehouseArea: array[i].info[j].WarehouseArea,
Volume: "0.00",
NewVolume: "0.00",
Quantity: "0",
SafetyStock: "0",
volmueType: "-1",
});
}
}
}
array[i].info[j].volmuePersent =
parseInt(array[i].info[j].NewVolume) == "0"
? " "
: Math.round(
(parseFloat(array[i].info[j].Volume) /
parseFloat(array[i].info[j].NewVolume)) *
10000
) /
100 +
"%";
array[i].info[j].volmueType =
parseInt(array[i].info[j].NewVolume) == "0"
? 0
: Math.round(
(parseFloat(array[i].info[j].Volume) /
parseFloat(array[i].info[j].NewVolume)) *
10000
) / 100;
}
array[i].info = newDataList;
}
array = await groupArr(array, "WarehouseArea");
return array;
};
const groupArr = (list, field) => {
var obj = {};
for (var i = 0; i < list.length; i++) {
for (let item in list[i]) {
if (item == field) {
obj[list[i][item]] = {
list: obj[list[i][field]] ? obj[list[i][field]].list : [],
name: list[i][field],
};
}
}
obj[list[i][field]].list.push(list[i]);
}
var att = [];
for (let item in obj) {
att.push({
list: obj[item].list,
name: obj[item].name,
});
}
return att;
};
const scrollDirection = ref("down");
const isAutoScrolling = ref(true);
const onScroll = () => {
if (isPaused.value) return;
// 停止自动滚动
clearTimeout(timeoutId.value);
// 设置滚动状态
scrolling.value = true;
// 滚动页面
const windowHeight = window.innerHeight;
const contentHeight = document.documentElement.scrollHeight;
let position = window.pageYOffset;
let reachedTop = false;
intervalId.value = setInterval(() => {
if (scrollDirection.value == "down") {
position += 1; // 每次滚动1px
window.scrollTo(0, position);
if (position + windowHeight >= contentHeight) {
clearInterval(intervalId.value);
scrolling.value = false;
scrollDirection.value = "up";
// 两秒后重新开始滚动
timeoutId.value = setTimeout(() => {
onScroll();
}, 2000);
}
} else {
if (position === 0) {
reachedTop = true;
}
if (!reachedTop) {
position -= 1; // 每次滚动1px
window.scrollTo(0, position);
}
if (reachedTop && position === 0) {
clearInterval(intervalId);
scrolling.value = false;
scrollDirection.value = "down";
reachedTop = false;
// 两秒后重新开始滚动
timeoutId.value = setTimeout(() => {
onScroll();
}, 2000);
}
}
}, 20); // 每20毫秒滚动一次
};
const handleOnscroll = () => {
if (isPaused.value) {
// 继续滚动
isPaused.value = false;
onScroll();
} else {
// 暂停滚动
isPaused.value = true;
clearTimeout(timeoutId.value);
clearInterval(intervalId.value);
}
console.log("isPaused.value:" + isPaused.value);
console.log("scrolling.value:" + scrolling.value);
console.log("intervalId.value:" + intervalId.value);
console.log("timeoutId.value:" + timeoutId.value);
};
return {
getAllData,
bubbleSort,
tableData,
rowstyles,
areaData,
groupArr,
filteredList,
filteredElseList,
timer,
scrolling,
timeoutId,
onScroll,
scrollContainer,
scrollDirection,
isAutoScrolling,
handleOnscroll,
intervalId,
isPaused,
};
},
mounted() {
this.$refs.scrollContainer.addEventListener("scroll", this.onScroll);
},
beforeUnmount() {
this.$refs.scrollContainer.removeEventListener("scroll", this.onScroll);
},
};
</script>
<style lang="less" scoped>
.home {
width: 100%;
.header {
font-size: 1.2rem;
color: #409eff;
position: sticky;
top: 0;
background: #f2f6fc;
}
.home-table {
display: flex;
table {
table-layout: fixed;
height: 100%;
width: 100%;
}
.table-head {
position: sticky;
top: 1.5rem;
}
}
table,
th {
text-align: center;
border: 0.5px solid #f5f6f9;
border-collapse: collapse;
color: #ffffff;
font-size: 0.7rem;
background: #f2f6fc;
}
.space {
width: 100%;
height: 3rem;
}
td {
color: black;
height: 3rem;
}
table td {
margin: 0 auto;
}
.colorPrimary {
background: #f2f6fc !important;
}
.bgPrimary {
background: #409eff !important;
}
.colorEmpty {
background: #ffffff !important;
}
.colorSimple {
background: #e3f6f5 !important;
}
.colorMore {
background: #bae8e8 !important;
}
.colorOverload {
background: #2c698d !important;
}
.floatBtn {
position: fixed;
right: 1rem;
bottom: 3rem;
}
}
</style>