diff --git a/docs/troubleshoot-ticket-wallet-scroll.md b/docs/troubleshoot-ticket-wallet-scroll.md new file mode 100644 index 00000000..449cb962 --- /dev/null +++ b/docs/troubleshoot-ticket-wallet-scroll.md @@ -0,0 +1,125 @@ +# 票据页面滚动卡死问题排查与修复 + +> **问题编号**: #0004 +> **问题类型**: 移动端实机交互异常 +> **影响页面**: `pages/plugins/vr-ticket-wallet/ticket-wallet`(我的票夹) +> **发现日期**: 2026-06-25 +> **修复状态**: ✅ 已修复并提交 + +--- + +## 1. 问题描述 + +在实机测试环境下(iOS/Android H5 或微信 Webview),用户进入「我的票夹」页面后,一旦页面发生下滑,之后往往**无法继续上滑操作**,必须通过底部 Tab Bar 切换到其他视图页面后,才能恢复正常滚动。 + +--- + +## 2. 问题原因分析 + +### 2.1 滚动容器层级冲突 + +票据页面采用了自定义导航栏(`navigationStyle: custom`),使用 `` 组件来实现页面内部滚动。问题根源在于**页面容器与 `` 的滚动边界未被正确约束**,导致在移动端实机的 Webview 中: + +- 系统级 Webview 的弹性滚动(bounce scroll)与 `` 内部滚动产生**手势冲突** +- 当用户下滑至内容底部后,系统 Webview 的弹性滚动接管了手势,但 `` 的 `scroll-y` 并未释放 +- 再次上滑时,手势被系统拦截,导致**页面无法响应** + +### 2.2 容器高度未限制 + +原代码中根容器 `.ticket-wallet-page` 使用了 `min-height: 100vh`,且未设置 `overflow: hidden`,使得容器可以超出视口高度,产生滚动空间,与内部 `` 的滚动区域重叠。 + +### 2.3 下拉刷新配置冲突 + +`pages.json` 中对 `ticket-wallet` 页面同时配置了: +- `enablePullDownRefresh: true`(页面级下拉刷新) +- `` 组件内部的 `refresher-enabled: true` + +两套下拉刷新机制并存,增加了手势处理的复杂度。 + +--- + +## 3. 修复方案 + +### 3.1 修改 `pages.json` + +**文件**: `pages.json` 第 2232–2244 行 + +**改动**: +```diff + { + "path": "ticket-wallet", + "style": { + "navigationStyle": "custom", +- "enablePullDownRefresh": true, ++ "enablePullDownRefresh": false, ++ "disableScroll": true, + "navigationBarTitleText": "", + ... + } + } +``` + +- **禁用页面级下拉刷新**(`enablePullDownRefresh: false`):避免页面级滚动与 `` 冲突 +- **开启禁止页面滚动**(`disableScroll: true`):彻底禁止系统 Webview 的弹性滚动,将手势控制权完全交给 `` + +> [!NOTE] +> 下拉刷新功能并未丢失——`` 组件自身提供的 `refresher-enabled` 属性已接管下拉刷新逻辑,行为保持一致。 + +### 3.2 修改 `ticket-wallet.css` + +**文件**: `pages/plugins/vr-ticket-wallet/ticket-wallet.css` + +#### 改动一:根容器高度约束 + +```diff + .ticket-wallet-page { +- min-height: 100vh; ++ height: 100vh; ++ overflow: hidden; + background: radial-gradient(circle at center, #fef4f4 0%, #f3e5e5 100%); + display: flex; + flex-direction: column; + } +``` + +- 使用固定高度 `100vh` 替代 `min-height`,配合 `overflow: hidden` 确保容器不会超出视口 + +#### 改动二:滚动区域高度简化 + +```diff + .wallet-scroll { + flex: 1; +- height: calc(100vh - 88rpx); ++ height: 100%; + } +``` + +- 移除硬编码的高度计算(`88rpx` 对应被注释掉的顶部导航栏高度) +- 使用 `height: 100%` 让滚动区域自适应父容器 + +--- + +## 4. 验证方法 + +1. 在 iOS Safari 或微信开发者工具中打开「我的票夹」页面 +2. 持续向下滑动至内容底部 +3. 尝试上滑——页面应能流畅响应,不会出现卡死现象 +4. 执行下拉刷新——`` 自带的刷新指示器应正常触发 +5. 切换 Tab Bar 至其他页面后返回——滚动状态应正常保留 + +--- + +## 5. 相关文件 + +| 文件 | 改动类型 | +|------|----------| +| `pages.json` | 修改 | +| `pages/plugins/vr-ticket-wallet/ticket-wallet.css` | 修改 | + +--- + +## 6. 预防措施 + +- 在使用自定义 `` 作为主要滚动容器的页面中,统一添加 `"disableScroll": true` 到 `pages.json` +- 确保根容器使用 `height: 100vh` + `overflow: hidden` 约束,避免与 Webview 滚动冲突 +- 避免在同一页面中混用页面级下拉刷新与 `` 下拉刷新 diff --git a/pages.json b/pages.json index 02ac1138..f8a99ff5 100644 --- a/pages.json +++ b/pages.json @@ -2233,7 +2233,8 @@ "path": "ticket-wallet", "style": { "navigationStyle": "custom", - "enablePullDownRefresh": true, + "enablePullDownRefresh": false, + "disableScroll": true, "navigationBarTitleText": "", "usingComponents": { "u-popup": "/components/u-popup/u-popup", diff --git a/pages/plugins/vr-ticket-wallet/ticket-wallet.css b/pages/plugins/vr-ticket-wallet/ticket-wallet.css index 01e4f4bf..d0da3be8 100644 --- a/pages/plugins/vr-ticket-wallet/ticket-wallet.css +++ b/pages/plugins/vr-ticket-wallet/ticket-wallet.css @@ -1,6 +1,7 @@ /* ========== 页面整体布局 ========== */ .ticket-wallet-page { - min-height: 100vh; + height: 100vh; + overflow: hidden; background: radial-gradient(circle at center, #fef4f4 0%, #f3e5e5 100%); display: flex; flex-direction: column; @@ -68,16 +69,9 @@ /* ========== 主滚动区域 ========== */ .wallet-scroll { flex: 1; - height: calc(100vh - 88rpx); + height: 100%; } -/* #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-KUAISHOU || H5 || APP */ -.wallet-scroll { - height: calc(100vh - 88rpx - constant(safe-area-inset-top)); - height: calc(100vh - 88rpx - env(safe-area-inset-top)); -} -/* #endif */ - /* ========== 顶部潮流 Banner ========== */ .brand-banner { position: relative;