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 @@