fix: 修复票据页面实机滚动卡死问题

问题描述:
- iOS/Android 实机测试时,票据页面下滑后无法上滑
- 必须切换 Tab Bar 才能恢复

根本原因:
- 页面容器未限制高度,Webview 弹性滚动与 scroll-view 手势冲突
- 页面级下拉刷新与 scroll-view 刷新机制并存,增加手势复杂度

修复方案:
- pages.json: 禁用页面级下拉刷新,开启 disableScroll
- ticket-wallet.css: 容器高度改为 100vh + overflow:hidden,滚动区高度简化为 100%

关联文档:
- docs/troubleshoot-ticket-wallet-scroll.md
master
Council 2026-06-26 08:12:54 +08:00
parent 02adc5f1c5
commit 6e80f6e9a6
3 changed files with 130 additions and 10 deletions

View File

@ -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`),使用 `<scroll-view>` 组件来实现页面内部滚动。问题根源在于**页面容器与 `<scroll-view>` 的滚动边界未被正确约束**,导致在移动端实机的 Webview 中:
- 系统级 Webview 的弹性滚动bounce scroll`<scroll-view>` 内部滚动产生**手势冲突**
- 当用户下滑至内容底部后,系统 Webview 的弹性滚动接管了手势,但 `<scroll-view>``scroll-y` 并未释放
- 再次上滑时,手势被系统拦截,导致**页面无法响应**
### 2.2 容器高度未限制
原代码中根容器 `.ticket-wallet-page` 使用了 `min-height: 100vh`,且未设置 `overflow: hidden`,使得容器可以超出视口高度,产生滚动空间,与内部 `<scroll-view>` 的滚动区域重叠。
### 2.3 下拉刷新配置冲突
`pages.json` 中对 `ticket-wallet` 页面同时配置了:
- `enablePullDownRefresh: true`(页面级下拉刷新)
- `<scroll-view>` 组件内部的 `refresher-enabled: true`
两套下拉刷新机制并存,增加了手势处理的复杂度。
---
## 3. 修复方案
### 3.1 修改 `pages.json`
**文件**: `pages.json` 第 22322244 行
**改动**:
```diff
{
"path": "ticket-wallet",
"style": {
"navigationStyle": "custom",
- "enablePullDownRefresh": true,
+ "enablePullDownRefresh": false,
+ "disableScroll": true,
"navigationBarTitleText": "",
...
}
}
```
- **禁用页面级下拉刷新**`enablePullDownRefresh: false`):避免页面级滚动与 `<scroll-view>` 冲突
- **开启禁止页面滚动**`disableScroll: true`):彻底禁止系统 Webview 的弹性滚动,将手势控制权完全交给 `<scroll-view>`
> [!NOTE]
> 下拉刷新功能并未丢失——`<scroll-view>` 组件自身提供的 `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. 执行下拉刷新——`<scroll-view>` 自带的刷新指示器应正常触发
5. 切换 Tab Bar 至其他页面后返回——滚动状态应正常保留
---
## 5. 相关文件
| 文件 | 改动类型 |
|------|----------|
| `pages.json` | 修改 |
| `pages/plugins/vr-ticket-wallet/ticket-wallet.css` | 修改 |
---
## 6. 预防措施
- 在使用自定义 `<scroll-view>` 作为主要滚动容器的页面中,统一添加 `"disableScroll": true``pages.json`
- 确保根容器使用 `height: 100vh` + `overflow: hidden` 约束,避免与 Webview 滚动冲突
- 避免在同一页面中混用页面级下拉刷新与 `<scroll-view>` 下拉刷新

View File

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

View File

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