1***@qq.com
1***@qq.com
  • 发布:2026-05-13 19:37
  • 更新:2026-05-13 19:38
  • 阅读:21

【报Bug】,picker-view,当滚动选择时,无法选中最后一项数据,但直接点击可以正常选中

分类:鸿蒙Next

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: 64

HBuilderX类型: 正式

HBuilderX版本号: 5.05

手机系统: HarmonyOS NEXT

手机系统版本号: HarmonyOS 6.0.0

手机厂商: 华为

手机机型: huawei pura 70

页面类型: vue

vue版本: vue3

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
<template> <view :class="{ pickerMask: visable }" @tap="maskClick" @touchmove.stop.prevent="returnHandle"> <view class="picker-box" :class="{ 'picker-show': visable }"> <view class="operate-box" @touchmove.stop.prevent="returnHandle" @tap.stop="returnHandle"> <view class="time-box"> <view @tap="touchSelect(0)" class="time-item" :style="{ color: touchIndex ? '#000000' : themeColor }"> <view>{{ startText }}</view> <view>{{ resultDate[0] }}</view> </view> <text>至</text> <view @tap="touchSelect(1)" class="time-item" :style="{ color: touchIndex ? themeColor : '#000000' }"> <view>{{ endText }}</view> <view>{{ resultDate[1] }}</view> </view> </view> <view :style="{ color: themeColor }" @tap="pickerConfirm">确定</view> </view> <picker-view value="pickerValue" @change="pickerChange"
class="picker-view" indicator-style="indicatorStyle" @tap.stop="returnHandle"
>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
</picker-view-column>
<picker-view-column v-if="days.length > 0">
<view class="picker-item" v-for="(item, index) in days" :key="index">{{ item }}日</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>

<script>
import day from '../../../utils/day.js';
export default {
name: 'termPicker',
props: {
visable: {
type: Boolean,
default: false,
},
defaultDate: {
type: Array,
default: () => [],
},
minYear: {
type: Number,
default: 1990,
},
timeLimit: {
type: Boolean,
default: false,
},
deferYear: {
type: Number,
default: 0,
},
themeColor: {
type: String,
default: '#10BE9D',
},
startText: {
type: String,
default: '开始时间',
},
endText: {
type: String,
default: '结束时间',
},
// 范围限制
maxRange: {
type: String,
default: '',
},
},
data() {
const date = new Date();
const years = [];
const year = date.getFullYear();
const months = [];
const month = date.getMonth() + 1;
const day = date.getDate();
const maxYear = this.timeLimit ? year : year + this.deferYear;
for (let i = this.minYear; i <= maxYear; i++) {
years.push(i);
}
for (let i = 1; i <= 12; i++) {
months.push(i);
}
return {
indicatorStyle: 'height: 100rpx;',
touchIndex: 0,
year,
month,
day,
years,
months,
days: [],
pickerValue: [],
resultDate: [],
};
},
mounted() {
this.setDate();
},
methods: {
returnHandle() {},
setDate() {
if (this.defaultDate.length > 0) {
let date = this.defaultDate[0];
this.resultDate = this.defaultDate;
this.setPicker(date);
} else {
let month = this.month < 10 ? '0' + this.month : this.month;
let day = this.day < 10 ? '0' + this.day : this.day;
let nowTime = this.year + '-' + month + '-' + day;
this.resultDate = [nowTime, nowTime];
this.setPicker(nowTime);
}
},
setPicker(date) {
const splitVal = date.split('-');
let year = this.years.indexOf(Number(splitVal[0]));
let month = Number(splitVal[1]) - 1;
let day = Number(splitVal[2]) - 1;
this.pickerChange({
detail: {
value: [year, month, day],
},
});
},
touchSelect(val) {
let date = this.resultDate[val];
this.touchIndex = val;
this.setPicker(date);
},
getDateTime(date) {
let year = this.years[date[0]];
let month = this.months[date[1]];
let day = this.days[date[2]];
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
this.resultDate[this.touchIndex] = year + '-' + month + '-' + day;
},
pickerChange(e) {
const currents = e.detail.value;
if (currents[1] + 1 === 2) {
this.days = [];
if (
((currents[0] + this.minYear) % 4 === 0 && (currents[0] + this.minYear) % 100 !== 0) ||
(currents[0] + this.minYear) % 400 === 0
) {
for (let i = 1; i < 30; i++) {
this.days.push(i);
}
} else {
for (let i = 1; i < 29; i++) {
this.days.push(i);
}
}
} else if ([4, 6, 9, 11].some((item) => currents[1] + 1 === item)) {
this.days = [];
for (let i = 1; i < 31; i++) {
this.days.push(i);
}
} else if ([1, 3, 5, 7, 8, 10, 12].some((item) => currents[1] + 1 === item)) {
this.days = [];
for (let i = 1; i < 32; i++) {
this.days.push(i);
}
}
this.pickerValue = currents;
this.getDateTime(currents);
},
maskClick() {
this.$emit('update:visable', false);
},
pickerConfirm() {
const { resultDate, timeLimit } = this;
let startTime = new Date(resultDate[0]).getTime();
let endTime = new Date(resultDate[1]).getTime();
let nowTime = timeLimit ? new Date().getTime() : endTime;
if (startTime <= endTime && endTime <= nowTime) {
if (this.maxRange) {
let days = day(endTime).diff(startTime, 'day');
if (days > this.maxRange) {
uni.showToast({
title: 时间范围不能超过 ${this.maxRange}天!,
icon: 'none',
});
return;
} else {
this.$emit('confirm', resultDate);
this.maskClick();
}
} else {
this.$emit('confirm', resultDate);
this.maskClick();
}
} else {
uni.showToast({
title: '时间范围不正确!',
icon: 'none',
});
}
},
},
};
</script>

<style lang="scss" scoped>
.pickerMask {
position: fixed;
z-index: 10071;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}

.picker-box {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 998;

.operate-box {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18rpx 30rpx;
background-color: #ffffff;
text-align: center;
font-size: 30rpx;
border-bottom: 2rpx solid #e5e5e5;

.time-box {  
  width: 60%;  
  display: flex;  
  align-items: center;  
  justify-content: space-between;  

  .time-item {  
    display: flex;  
    flex-direction: column;  
  }  
}  

}
}

.picker-show {
transform: translateY(0);
}

.picker-view {
width: 750rpx;
height: 600rpx;
background-color: #ffffff;

.picker-item {
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
}
</style>

操作步骤:

<termPicker v-model:visable="showCalendar" :defaultDate="defaultDate" :deferYear="6" @confirm="onConfirmCalendar">
</termPicker>

预期结果:

1

实际结果:

1

bug描述:

2026-05-13 19:37 负责人:无 分享
已邀请:
Ask小助手

Ask小助手

知识库缺失鸿蒙picker-view滚动选中最后一项的修复方案。请补充HBuilderX版本、示例代码及详细报错信息。

作为 DCloud 官方人员,我对你提交的这个 bug 反馈进行评审,结论如下:

评审结论:反馈内容不完整,无法确认 bug 是否成立,需要进一步补充信息。

具体分析如下:

1. 反馈内容完整性分析

  • 预期结果与实际结果描述严重缺失:你在“预期结果”和“实际结果”栏均只填写了“1”,这无法让任何人理解问题所在。预期结果应详细描述你期望的正确行为(例如:“滚动选择时,滚动到列表最后一项松手后,该项应被选中并显示在指示框内”)。实际结果应描述具体发生的错误现象(例如:“滚动选择最后一项时,松手后列表回弹,实际选中的是倒数第二项”)。
  • 代码示例不完整:提供的代码片段中引用了 ../../../utils/day.js,这是一个外部依赖,我们无法获取。没有这份代码,项目无法直接运行,也就无法复现问题。请提供一个最简化的、可独立运行的完整代码示例。
  • 复现步骤不清晰:你提供的复现步骤为 <termPicker v-model:visable="showCalendar" ...>,这只是组件的调用方式,并非操作步骤。应描述具体的操作过程,例如:“1. 点击按钮打开日期选择器。2. 在‘日’这一列向上滚动,尝试选择最后一天(如31日)。3. 观察松手后的选中结果。”

2. Bug 是否成立分析

  • 在现有知识库中,我找到了 picker-view 组件支持鸿蒙平台(HarmonyOS)的记录,起始支持版本为 HBuilderX 4.23。
  • 同时,在 ask 社区知识库中,我找到了一个关于 picker-view 在 Android 平台上不居中显示的已确认 bug,其原因是“极小的数字内容,有小数长度”。但你反馈的问题是“鸿蒙平台无法滚动选中最后一项”,这与已知的 Android 端 bug 不完全一致。
  • 由于你提供的信息过于简略,特别是缺少了“预期结果”和“实际结果”的详细描述,我在知识库中没有找到与你描述完全匹配的已知问题或修复方案。因此,无法确认这是一个新 bug,还是你的代码逻辑、样式设置或使用方式导致的问题。

3. 基本概念检查

  • 你的反馈涉及 picker-view 组件在 uni-app (Vue3) 项目中的使用,目标是鸿蒙(HarmonyOS)平台。这些均在 uni-app 的支持范围内,不存在概念性冲突。需要注意的是,鸿蒙平台不支持 app-plus 相关的 API。

建议操作

为了帮助我们定位和解决问题,请务必完善反馈信息:

  1. 详细描述现象:请清晰、具体地填写“预期结果”和“实际结果”。
  2. 提供可运行示例:提供一个不依赖 day.js 等外部文件的、完整且最简化的代码示例,让我们能直接运行并复现问题。
  3. 细化复现步骤:一步步描述从打开页面到问题发生的所有操作。
  4. 尝试定位:你可以尝试使用 HBuilderX 官方模板 Hello uni-app 中的 picker-view 示例进行测试,看是否能复现,这有助于判断问题是否与你的自定义组件有关。

感谢你的反馈,期待你提供更完整的信息,以便我们进一步排查。

内容为 AI 生成,仅供参考
1***@qq.com

1***@qq.com (作者)

能不能快点修复啊!只有鸿蒙有问题,安卓,ios,以及h5都正常!!!!

要回复问题请先登录注册