From fd2579fb5de7168afed579d7f8b74d849316e44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E8=BE=89?= <13935151924@163.com> Date: Wed, 19 Nov 2025 13:02:40 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8E=86=E5=88=B6=E4=BD=9C111?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/AppLayout/AppLayout.vue | 10 + .../expected-station/expected-station.vue | 210 +++++++++++------- components/selectJobs/selectJobs.vue | 1 + packageA/pages/post/post.vue | 13 ++ 4 files changed, 149 insertions(+), 85 deletions(-) diff --git a/components/AppLayout/AppLayout.vue b/components/AppLayout/AppLayout.vue index c439a44..a6b4af7 100644 --- a/components/AppLayout/AppLayout.vue +++ b/components/AppLayout/AppLayout.vue @@ -90,6 +90,10 @@ const handleScrollToLower = () => { width: 100vw; height: calc(100% - var(--window-bottom)); overflow: hidden; + /* H5环境安全区域适配 */ + /* #ifdef H5 */ + height: 100vh; + /* #endif */ } .app-container { // background-image: url('@/static/icon/background2.png'); @@ -140,7 +144,13 @@ const handleScrollToLower = () => { .container-main { flex: 1; overflow: hidden; + padding-bottom: 20rpx; } +/* #ifdef H5 */ +.container-main { + padding-bottom: 120rpx!important; +} +/* #endif */ .main-scroll { width: 100%; diff --git a/components/expected-station/expected-station.vue b/components/expected-station/expected-station.vue index f6e3ce0..40d846b 100644 --- a/components/expected-station/expected-station.vue +++ b/components/expected-station/expected-station.vue @@ -25,7 +25,6 @@ @scroll="scrollTopBack" :scroll-y="true" class="sex-content-right" - @wheel="handleWheel" > {{ item.label }} @@ -58,6 +57,8 @@ export default { stationCateLog: 0, copyTree: [], scrollTop: 0, + scrollTimer: null, + lastScrollTime: 0, }; }, props: { @@ -90,109 +91,131 @@ export default { } }, }, + beforeDestroy() { + // 组件销毁前清除定时器 + if (this.scrollTimer) { + clearTimeout(this.scrollTimer); + this.scrollTimer = null; + } + }, methods: { changeStationLog(item) { this.leftValue = item; this.rightValue = item.children; this.scrollTop = 0; - // 确保左侧列表滚动到正确位置,让当前选中的标签可见 - this.$nextTick(() => { + // 使用更激进的防抖策略,避免频繁的左侧滚动 + if (this.scrollTimer) { + clearTimeout(this.scrollTimer); + } + + this.scrollTimer = setTimeout(() => { + // 确保左侧列表滚动到正确位置,让当前选中的标签可见 const index = this.copyTree.findIndex(i => i.id === item.id); if (index !== -1 && this.$refs.leftScroll) { - // 计算需要滚动的距离(每个选项高度约160rpx) - const scrollTop = index * 160; + const itemHeight = 160; // 每个选项高度 + const visibleHeight = 4 * itemHeight; // 可见区域高度 - // 获取左侧列表的可见高度(假设可见区域能显示约3-4个选项) - const visibleHeight = 4 * 160; // 约4个选项的高度 + // 计算目标位置 + const targetTop = index * itemHeight; - // 确保选中的标签在可见区域内 - let targetScrollTop = scrollTop; + // 获取当前左侧列表的滚动位置 + const currentLeftScrollTop = this.$refs.leftScroll.scrollTop || 0; - // 如果选中的标签在底部,确保它不会滚动出可见区域 - if (scrollTop > this.$refs.leftScroll.scrollHeight - visibleHeight) { - targetScrollTop = Math.max(0, this.$refs.leftScroll.scrollHeight - visibleHeight); + // 只有当目标位置不在当前可见区域内时才滚动 + if (targetTop < currentLeftScrollTop || targetTop > currentLeftScrollTop + visibleHeight - itemHeight) { + let targetScrollTop = targetTop; + + // 如果选中的标签在底部,确保它不会滚动出可见区域 + if (targetTop > this.$refs.leftScroll.scrollHeight - visibleHeight) { + targetScrollTop = Math.max(0, this.$refs.leftScroll.scrollHeight - visibleHeight); + } + + this.$refs.leftScroll.scrollTo({ + top: targetScrollTop, + duration: 100 // 进一步减少滚动动画时间 + }); } - - this.$refs.leftScroll.scrollTo({ - top: targetScrollTop, - duration: 300 - }); } - }); + }, 100); }, scrollTopBack(e) { - this.scrollTop = e.detail.scrollTop; + const currentTime = Date.now(); - // 滚动时自动选中对应的左侧标签 - const scrollTop = e.detail.scrollTop; - let currentSection = null; - let minDistance = Infinity; - - // 遍历所有右侧的二级标题,找到当前最接近顶部的那个 - this.rightValue.forEach((section, index) => { - // 估算每个section的位置(假设每个section高度大约为 200rpx) - const sectionTop = index * 200; - const distance = Math.abs(sectionTop - scrollTop); - - if (distance < minDistance) { - minDistance = distance; - currentSection = section; - } - }); - - // 如果找到了对应的section,并且不是当前选中的左侧标签,则切换左侧标签 - if (currentSection && this.leftValue.id !== currentSection.parentId) { - const parentItem = this.copyTree.find(item => item.id === currentSection.parentId); - if (parentItem) { - this.leftValue = parentItem; - - // 确保左侧列表滚动到正确位置,让当前选中的标签可见 - this.$nextTick(() => { - const index = this.copyTree.findIndex(i => i.id === parentItem.id); - if (index !== -1 && this.$refs.leftScroll) { - // 计算需要滚动的距离(每个选项高度约160rpx) - const scrollTop = index * 160; - - // 获取左侧列表的可见高度(假设可见区域能显示约3-4个选项) - const visibleHeight = 4 * 160; // 约4个选项的高度 - - // 确保选中的标签在可见区域内 - let targetScrollTop = scrollTop; - - // 如果选中的标签在底部,确保它不会滚动出可见区域 - if (scrollTop > this.$refs.leftScroll.scrollHeight - visibleHeight) { - targetScrollTop = Math.max(0, this.$refs.leftScroll.scrollHeight - visibleHeight); - } - - this.$refs.leftScroll.scrollTo({ - top: targetScrollTop, - duration: 300 - }); - } - }); - } + // 更严格的防抖处理:如果距离上次滚动时间太短,则跳过处理 + if (currentTime - this.lastScrollTime < 80) { + return; } - }, - handleWheel(e) { - // 处理鼠标滚轮事件,让右侧内容可以滚动 - e.preventDefault(); - const delta = e.deltaY || e.wheelDelta; + this.lastScrollTime = currentTime; - // 更平滑的滚动,根据滚轮速度调整滚动量 - const scrollAmount = Math.abs(delta) > 100 ? 80 : 40; - const direction = delta > 0 ? 1 : -1; + // 清除之前的定时器 + if (this.scrollTimer) { + clearTimeout(this.scrollTimer); + } - // 更新scrollTop来模拟滚动 - this.scrollTop += scrollAmount * direction; - - // 确保scrollTop在合理范围内 - this.scrollTop = Math.max(0, this.scrollTop); - - // 触发scroll事件来更新左侧标签选中状态 - this.$nextTick(() => { - this.scrollTopBack({ detail: { scrollTop: this.scrollTop } }); - }); + // 设置新的定时器,延迟处理滚动事件 + this.scrollTimer = setTimeout(() => { + this.scrollTop = e.detail.scrollTop; + + // 滚动时自动选中对应的左侧标签 + const scrollTop = e.detail.scrollTop; + let currentSection = null; + let minDistance = Infinity; + + // 遍历所有右侧的二级标题,找到当前最接近顶部的那个 + this.rightValue.forEach((section, index) => { + // 更精确地估算每个section的位置(考虑标题高度和内容高度) + const sectionTop = index * 280; // 增加估算高度,避免过于敏感 + const distance = Math.abs(sectionTop - scrollTop); + + if (distance < minDistance) { + minDistance = distance; + currentSection = section; + } + }); + + // 只有当距离足够近时才切换左侧标签,避免过于敏感 + if (currentSection && minDistance < 100 && this.leftValue.id !== currentSection.parentId) { + const parentItem = this.copyTree.find(item => item.id === currentSection.parentId); + if (parentItem) { + this.leftValue = parentItem; + + // 使用更激进的防抖策略,避免频繁的左侧滚动 + if (this.scrollTimer) { + clearTimeout(this.scrollTimer); + } + + this.scrollTimer = setTimeout(() => { + // 只在必要时滚动左侧列表,避免频繁滚动导致的抖动 + const index = this.copyTree.findIndex(i => i.id === parentItem.id); + if (index !== -1 && this.$refs.leftScroll) { + // 获取当前左侧列表的滚动位置 + const currentLeftScrollTop = this.$refs.leftScroll.scrollTop || 0; + const itemHeight = 160; // 每个选项高度 + const visibleHeight = 4 * itemHeight; // 可见区域高度 + + // 计算目标位置 + const targetTop = index * itemHeight; + + // 只有当目标位置不在当前可见区域内时才滚动 + if (targetTop < currentLeftScrollTop || targetTop > currentLeftScrollTop + visibleHeight - itemHeight) { + let targetScrollTop = targetTop; + + // 如果选中的标签在底部,确保它不会滚动出可见区域 + if (targetTop > this.$refs.leftScroll.scrollHeight - visibleHeight) { + targetScrollTop = Math.max(0, this.$refs.leftScroll.scrollHeight - visibleHeight); + } + + this.$refs.leftScroll.scrollTo({ + top: targetScrollTop, + duration: 100 // 进一步减少滚动动画时间 + }); + } + } + }, 150); // 增加延迟,避免滚动冲突 + } + } + }, 80); // 增加防抖延迟到80ms }, addItem(item) { let titiles = []; @@ -285,6 +308,10 @@ export default { .sex-content-left width: 198rpx; padding: 20rpx 0 0 0; + /* 添加硬件加速优化 */ + transform: translateZ(0); + -webkit-transform: translateZ(0); + will-change: transform; .left-list-btn padding: 0 40rpx 0 24rpx; display: grid; @@ -295,6 +322,9 @@ export default { font-size: 28rpx; position: relative margin-top: 60rpx + /* 优化渲染性能 */ + transform: translateZ(0); + -webkit-transform: translateZ(0); .left-list-btn:first-child margin-top: 0 // .positionNum @@ -323,6 +353,10 @@ export default { // border-left: 2px solid #D9D9D9; background: #F6F6F6; flex: 1; + /* 添加硬件加速优化 */ + transform: translateZ(0); + -webkit-transform: translateZ(0); + will-change: transform; .grid-sex display: grid; grid-template-columns: 50% 50%; @@ -340,6 +374,9 @@ export default { margin-top: 30rpx; background: #E8EAEE; color: #606060; + /* 优化渲染性能 */ + transform: translateZ(0); + -webkit-transform: translateZ(0); .sex-right-btned font-weight: 500 width: 224rpx; @@ -347,4 +384,7 @@ export default { background: rgba(37,107,250,0.06); border: 2rpx solid #256BFA; color: #256BFA + /* 优化渲染性能 */ + transform: translateZ(0); + -webkit-transform: translateZ(0); diff --git a/components/selectJobs/selectJobs.vue b/components/selectJobs/selectJobs.vue index bf438f2..1d1317c 100644 --- a/components/selectJobs/selectJobs.vue +++ b/components/selectJobs/selectJobs.vue @@ -17,6 +17,7 @@