hookehuyr

fix(BrandModelPicker): 修复内容高度计算问题并优化滚动体验

动态计算品牌选择器内容区域高度,替代原有固定值
添加 catch-move 属性防止滚动冲突
增加底部内边距确保最后一个项目可见
添加错误处理机制和降级方案
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
3 <!-- 品牌选择弹框 --> 3 <!-- 品牌选择弹框 -->
4 <nut-popup v-model:visible="brandPickerVisible" position="bottom" :style="{ height: '80%' }"> 4 <nut-popup v-model:visible="brandPickerVisible" position="bottom" :style="{ height: '80%' }">
5 <view class="brand-model-picker"> 5 <view class="brand-model-picker">
6 - <view class="picker-header"> 6 + <view id="picker-header" class="picker-header">
7 <text class="picker-title">选择品牌型号</text> 7 <text class="picker-title">选择品牌型号</text>
8 <nut-button size="small" type="primary" @click="closePicker">关闭</nut-button> 8 <nut-button size="small" type="primary" @click="closePicker">关闭</nut-button>
9 </view> 9 </view>
10 - <view class="search-container"> 10 + <view id="search-container" class="search-container">
11 <nut-searchbar 11 <nut-searchbar
12 v-model="searchKeyword" 12 v-model="searchKeyword"
13 placeholder="搜索品牌名称" 13 placeholder="搜索品牌名称"
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
21 class="brand-content" 21 class="brand-content"
22 :scroll-y="true" 22 :scroll-y="true"
23 :style="{ height: contentHeight + 'rpx' }" 23 :style="{ height: contentHeight + 'rpx' }"
24 + :catch-move="true"
24 ref="brandContentRef" 25 ref="brandContentRef"
25 > 26 >
26 <view class="brand-list"> 27 <view class="brand-list">
...@@ -68,8 +69,10 @@ ...@@ -68,8 +69,10 @@
68 </template> 69 </template>
69 70
70 <script setup> 71 <script setup>
71 -import { ref, computed } from 'vue' 72 +import { ref, computed, onMounted } from 'vue'
73 +import Taro from '@tarojs/taro'
72 import { Right } from '@nutui/icons-vue-taro' 74 import { Right } from '@nutui/icons-vue-taro'
75 +import { $ } from '@tarojs/extend'
73 76
74 // 定义事件 77 // 定义事件
75 const emit = defineEmits(['confirm', 'cancel']) 78 const emit = defineEmits(['confirm', 'cancel'])
...@@ -210,11 +213,37 @@ const filteredBrands = computed(() => { ...@@ -210,11 +213,37 @@ const filteredBrands = computed(() => {
210 }) 213 })
211 214
212 // 计算内容高度 215 // 计算内容高度
213 -const calculateContentHeight = () => { 216 +const calculateContentHeight = async () => {
214 - // 弹框总高度 - 头部高度 217 + try {
215 - const popupHeight = 1200 // rpx 218 + // 获取窗口信息
216 - const headerHeight = 120 // rpx (头部标题和按钮的高度) 219 + const windowInfo = Taro.getWindowInfo()
217 - contentHeight.value = popupHeight - headerHeight 220 + const windowHeight = windowInfo.windowHeight
221 +
222 + // 使用 setTimeout 确保 DOM 元素已渲染
223 + setTimeout(async () => {
224 + try {
225 + // 获取弹框头部高度
226 + const headerHeight = await $('.picker-header').height() || 120
227 + // 获取搜索框高度
228 + const searchHeight = await $('.search-container').height() || 100
229 +
230 + // 计算可用高度:窗口高度的80% - 头部高度 - 搜索框高度 - 额外边距
231 + const availableHeight = windowHeight * 0.8 - headerHeight - searchHeight - 40
232 +
233 + // 转换为 rpx 单位 (假设设计稿宽度为750rpx)
234 + const factor = 750 / windowInfo.windowWidth
235 + contentHeight.value = Math.max(availableHeight * factor, 600) // 最小高度600rpx
236 + } catch (error) {
237 + console.warn('计算高度时出错,使用默认值:', error)
238 + // 降级方案:使用相对安全的默认值
239 + contentHeight.value = windowHeight * 0.5 * (750 / windowInfo.windowWidth)
240 + }
241 + }, 100)
242 + } catch (error) {
243 + console.warn('获取窗口信息失败,使用固定高度:', error)
244 + // 完全降级方案:使用固定值
245 + contentHeight.value = 800
246 + }
218 } 247 }
219 248
220 // 显示品牌选择器 249 // 显示品牌选择器
...@@ -268,6 +297,12 @@ const closeAllPickers = () => { ...@@ -268,6 +297,12 @@ const closeAllPickers = () => {
268 currentBrandModels.value = [] 297 currentBrandModels.value = []
269 } 298 }
270 299
300 +// 组件挂载时初始化
301 +onMounted(() => {
302 + // 初始化高度计算
303 + calculateContentHeight()
304 +})
305 +
271 // 暴露方法给父组件 306 // 暴露方法给父组件
272 defineExpose({ 307 defineExpose({
273 show, 308 show,
...@@ -358,6 +393,7 @@ defineExpose({ ...@@ -358,6 +393,7 @@ defineExpose({
358 393
359 .brand-list { 394 .brand-list {
360 padding: 20rpx; 395 padding: 20rpx;
396 + padding-bottom: 60rpx; /* 增加底部内边距,确保最后一个项目完全可见 */
361 397
362 .brand-item { 398 .brand-item {
363 display: flex; 399 display: flex;
......