From cd03f0fa3d4c616ff68622ed58dace71a5c64bc0 Mon Sep 17 00:00:00 2001 From: liulong <18539103286> Date: Fri, 5 Jun 2026 13:50:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A0=B7=E5=BC=8F=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/index/views/gxnlpt/index.vue | 30 ++++- .../src/pages/index/views/home2/index.vue | 8 +- .../src/pages/index/views/hydt/index.vue | 119 ++++++------------ .../src/pages/index/views/hyzt/index.vue | 15 +-- .../src/pages/index/views/qych/index.vue | 9 ++ 5 files changed, 83 insertions(+), 98 deletions(-) diff --git a/txw-mhzc-web/src/pages/index/views/gxnlpt/index.vue b/txw-mhzc-web/src/pages/index/views/gxnlpt/index.vue index 3ba032c..aab660c 100644 --- a/txw-mhzc-web/src/pages/index/views/gxnlpt/index.vue +++ b/txw-mhzc-web/src/pages/index/views/gxnlpt/index.vue @@ -726,9 +726,21 @@ export default { this.$nextTick(() => this.scrollListContentToTop()); return true; } + // 首页带 anchor 跳转进入:从一开始就锁定高亮,不让 observer 参与本次定位, + // 避免侧边栏 activeTabIndex 在慢滚过程中从 0 一路闪到目标 tab。 + this.activeTabIndex = tabIndex; + this.suppressSectionObserver = true; this.initScrollSpy(); this.initSidebarSticky(); - this.scrollToSection(anchor, tabIndex); + // 等两帧:第 1 帧让 gxnlpt-block 节点挂载完毕, + // 第 2 帧让 layout/图片/字体把真实高度提交到 DOM, + // 此时 getBoundingClientRect 才能算出"一次定位准确"的目标位置。 + const jumpToAnchor = () => { + this.scrollToSection(anchor, tabIndex, { behavior: 'auto' }); + // 瞬时定位完成后恢复 observer,让用户后续手动滚动时侧边栏能正常高亮 + this.suppressSectionObserver = false; + }; + requestAnimationFrame(() => requestAnimationFrame(jumpToAnchor)); return true; }, getIconUrl(iconName) { @@ -993,11 +1005,15 @@ export default { this.activeTabIndex = tabIndex; } }, - scheduleScrollUnlock(tabIndex) { + scheduleScrollUnlock(tabIndex, options = {}) { this.clearScrollUnlock(); this.suppressSectionObserver = true; this.activeTabIndex = tabIndex; + // 瞬时定位路径:不依赖 900ms 定时器/scrollend 事件去延后解锁, + // 由调用方(典型是 navigateToRouteAnchor)直接控制解锁时机。 + if (options.skipObserverLock) return; + const scrollRoot = this.getScrollRoot(); let unlocked = false; const done = () => { @@ -1156,7 +1172,7 @@ export default { * 通过 getBoundingClientRect 获取目标元素在视口内的视觉位置, * 反算至滚动容器布局坐标后 scrollTo,不受 scale 变换影响。 */ - scrollToSection(sectionId, tabIndex) { + scrollToSection(sectionId, tabIndex, options = {}) { const el = document.getElementById(sectionId); const scrollRoot = this.getScrollRoot(); if (!el || !scrollRoot) return; @@ -1175,8 +1191,12 @@ export default { const OFFSET_DP = 88; // 设计稿像素 const target = Math.max(0, layoutTarget - OFFSET_DP); - scrollRoot.scrollTo({ top: target, behavior: 'smooth' }); - this.scheduleScrollUnlock(tabIndex); + // 默认仍是 smooth(用户手动点侧边栏时需要平滑过渡); + // 从首页带 anchor 跳转进入时,使用 'auto' 瞬时定位, + // 避免滚动过程中侧边栏 activeTabIndex 被 observer 反复改写造成的"跳变"。 + const behavior = options.behavior || 'smooth'; + scrollRoot.scrollTo({ top: target, behavior }); + this.scheduleScrollUnlock(tabIndex, { skipObserverLock: behavior === 'auto' }); }, /* ========== IntersectionObserver 驱动的 ScrollSpy ========== */ /** diff --git a/txw-mhzc-web/src/pages/index/views/home2/index.vue b/txw-mhzc-web/src/pages/index/views/home2/index.vue index 7b043ff..40442f2 100644 --- a/txw-mhzc-web/src/pages/index/views/home2/index.vue +++ b/txw-mhzc-web/src/pages/index/views/home2/index.vue @@ -787,10 +787,10 @@ export default { }, // 企业出海卡片点击 → 专题页对应区块 handleOverseasClick(item) { - if (item && item.comingSoon) { - this.showComingSoon('航运燃料专题'); - return; - } + // if (item && item.comingSoon) { + // this.showComingSoon('航运燃料专题'); + // return; + // } if (!item || !item.sectionId) { this.$router.push('/qych'); return; diff --git a/txw-mhzc-web/src/pages/index/views/hydt/index.vue b/txw-mhzc-web/src/pages/index/views/hydt/index.vue index 88efb16..01420b1 100644 --- a/txw-mhzc-web/src/pages/index/views/hydt/index.vue +++ b/txw-mhzc-web/src/pages/index/views/hydt/index.vue @@ -1,11 +1,7 @@