2***@qq.com
2***@qq.com
  • 发布:2024-07-02 09:42
  • 更新:2024-07-15 13:47
  • 阅读:218

【报Bug】picker-view样式错乱,内附组件压缩包

分类:uni-app

产品分类: uniapp/H5

PC开发环境操作系统: Windows

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

HBuilderX类型: Alpha

HBuilderX版本号: 4.22

浏览器平台: Edge

浏览器版本: 最新

项目创建方式: HBuilderX

示例代码:

使用方法

<date-picker v-if="mode == 'date'" class="w-picker-wrapper" :from-data="fromData" :startYear="startYear"  
                :endYear="endYear" :value="value" :fields="fields" :item-height="itemHeight" :current="current"  
                :disabled-after="disabledAfter" @change="handlerChange" @touchstart="touchStart"  
                @touchend="touchEnd"></date-picker>

组件代码

<template>  
    <view class="w-picker-view">  
        <picker-view v-if="fields == 'year'" class="d-picker-view" :indicator-style="itemHeight" :value="pickerVal.list"  
            @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
        </picker-view>  
        <picker-view v-else-if="fields == 'month'" class="d-picker-view" :indicator-style="itemHeight"  
            :value="pickerVal.list" @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in months.list" :key="index">{{ item }}{{$t('月')}}</view>  
            </picker-view-column>  
        </picker-view>  
        <picker-view v-if="fields == 'day'" class="d-picker-view" :indicator-style="itemHeight" :value="pickerVal.list"  
            @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in months.list" :key="index">{{ item }}{{$t('月')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in days.list" :key="index">{{ item }}{{$t('日')}}</view>  
            </picker-view-column>  
        </picker-view>  
        <picker-view v-else-if="fields == 'hour'" class="d-picker-view" :indicator-style="itemHeight" :value="pickerVal.list"  
            @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in months.list" :key="index">{{ item }}{{$t('月')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in days.list" :key="index">{{ item }}{{$t('日')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in hours.list" :key="index">{{ item }}{{$t('时')}}</view>  
            </picker-view-column>  
        </picker-view>  
        <picker-view v-else-if="fields == 'minute'" class="d-picker-view" :indicator-style="itemHeight" :value="pickerVal.list" @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in months.list" :key="index">{{ item }}{{$t('月')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in days.list" :key="index">{{ item }}{{$t('日')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in hours.list" :key="index">{{ item }}{{$t('时')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in minutes.list" :key="index">{{ item }}{{$t('分')}}</view>  
            </picker-view-column>  
        </picker-view>  
        <picker-view v-else class="d-picker-view" :indicator-style="itemHeight" :value="pickerVal.list" @change="bindChange">  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in years.list" :key="index">{{ item }}{{$t('年')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in months.list" :key="index">{{ item }}{{$t('月')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in days.list" :key="index">{{ item }}{{$t('日')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in hours.list" :key="index">{{ item }}{{$t('时')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in minutes.list" :key="index">{{ item }}{{$t('分')}}</view>  
            </picker-view-column>  
            <picker-view-column>  
                <view class="w-picker-item" v-for="(item, index) in seconds.list" :key="index">{{ item }}{{$t('秒')}}</view>  
            </picker-view-column>  
        </picker-view>  
    </view>  
</template>  
<script setup>  
    import {  
        defineProps,  
        reactive,  
        ref,  
        watch,  
        onBeforeMount,  
        defineEmits,  
        nextTick  
    } from 'vue'  
    import {  
        dayjs  
    } from "@/uni_modules/iRainna-dayjs/js_sdk/dayjs.min.js";  

    const emits = defineEmits(['change'])  

    const props = defineProps({  
        startYear: {  
            type: [String, Number],  
            default: '2010/01/01 00:00',  
        },  
        endYear: {  
            type: [String, Number],  
            default: '2050/12/31 23:59',  
        },  
        fromData: {  
            // 自定义日期选择器返回格式  
            type: String,  
            default: '',  
        },  
        value: {  
            type: [String, Number],  
            default: '',  
        },  
        itemHeight: {  
            type: String,  
            default: '44px',  
        },  
        fields: {  
            type: String,  
            default: 'day',  
        },  
    });  

    const baseArr = {  
        list: ['', '']  
    };  
    var nowdate = ref('');  
    var presentTime = reactive(new Date());  
    var years = reactive({  
        list: ['', '']  
    });  
    var months = reactive({  
        list: ['', '']  
    });  
    var days = reactive({  
        list: ['', '']  
    });  
    var hours = reactive({  
        list: ['', '']  
    });  
    var minutes = reactive({  
        list: ['', '']  
    });  
    var seconds = reactive({  
        list: ['', '']  
    });  
    var days28 = reactive([]);  
    var pickerVal = reactive({  
        list:[]  
    });  
    var startObj = reactive({  
        months: [],  
        days: []  
    });  
    var endObj = reactive({  
        months: [],  
        days: []  
    });  
    var changeDisabled = ref(false);  
    var moveFlag = ref(false);  
    var showCover = ref(false);  
    var hasChange = ref(false);  

    watch(() => props.startYear, () => {  
        setStartEnd()  
        let date = props.value ? props.value : new Date()  
        initCurr(date)  
    })  

    watch(() => props.endYear, () => {  
        setStartEnd()  
        let date = props.value ? props.value : new Date()  
        initCurr(date)  
    })  

    watch(() => props.value, (val, oval) => {  
        let date = val ? val : new Date();  
        initCurr(date)  
        let {  
            y,  
            m,  
            d,  
            h,  
            minu,  
            sec  
        } = trimDate(props.value)  
        let trimN = trimNum  
        nowdate = `${y}-${trimN(m)}-${trimN(d)} ${trimN(h)}:${trimN(minu)}:${trimN(sec)}`  
    })  

    onBeforeMount(() => {  
        days28 = setArray(1, 28)  
        setStartEnd()  
        if (props.value) {  
            const {  
                y,  
                m,  
                d,  
                h,  
                minu,  
                sec  
            } = trimDate(props.value)  
            const trimN = trimNum  
            nowdate = `${y}-${trimN(m)}-${trimN(d)} ${trimN(h)}:${trimN(minu)}:${trimN(sec)}`  
        }  
        const date = props.value ? props.value : new Date()  
        initCurr(date)  
        nextTick(() => {  
            confirm()  
        })  
    });  

    // 当滚动选择  
    const bindChange = (e) => {  
        if (changeDisabled.value) return  
        changeDisabled.value = true  
        const prev = pickerVal.list  
        const val = e.detail.value  
        const y = years.list[val[0]] ? years.list[val[0]] : years.list[years.list.length - 1]  
        const m = months.list[val[1]] ? months.list[val[1]] : months.list[months.list.length - 1]  
        const d = days.list[val[2]] ? days.list[val[2]] : days.list[days.list.length - 1]  
        const h = hours.list[val[3]] >= 0 ? hours.list[val[3]] : hours.list[hours.list.length - 1]  
        const minu = minutes.list[val[4]] >= 0 ? minutes.list[val[4]] : minutes.list[minutes.list.length - 1]  
        const sec = seconds.list[val[5]] >= 0 ? seconds.list[val[5]] : seconds.list[seconds.list.length - 1]  
        const date = `${y}/${m}/${d} ${h}:${minu}:${sec}`  
        if (prev[1] != val[1]) {  
            initCurr(date, m, d)  
        } else {  
            initCurr(date)  
        }  
    }  
    // 点击确定  
    const confirm = () => {  
        const val = pickerVal.list  
        const trimN = trimNum  
        let date = ''  
        let obj = {}  
        switch (props.fields) {  
            case 'year':  
                date = `${years.list[val[0]]}`  
                obj = {  
                    year: years.list[val[0]],  
                }  
                break  
            case 'month':  
                date = `${years.list[val[0]]}-${trimN(months.list[val[1]])}`  
                obj = {  
                    year: years.list[val[0]],  
                    month: months.list[val[1]],  
                }  
                break  
            case 'day':  
                date = `${years.list[val[0]]}-${trimN(months.list[val[1]])}-${trimN(days.list[val[2]])}`  
                obj = {  
                    year: years.list[val[0]],  
                    month: months.list[val[1]],  
                    day: days.list[val[2]],  
                }  
                break  
            case 'hour':  
                date =  
                    `${years.list[val[0]]}-${trimN(months.list[val[1]])}-${trimN(days.list[val[2]])} ${trimN(hours.list[val[3]])}`  
                obj = {  
                    year: years.list[val[0]],  
                    month: months.list[val[1]],  
                    day: days.list[val[2]],  
                    hour: hours.list[val[3]],  
                }  
                break  
            case 'minute':  
                date =  
                    `${years.list[val[0]]}-${trimN(months.list[val[1]])}-${trimN(days.list[val[2]])} ${trimN(hours.list[val[3]])}:${trimN(minutes.list[val[4]])}`  
                obj = {  
                    year: years.list[val[0]],  
                    month: months.list[val[1]],  
                    day: days.list[val[2]],  
                    hour: hours.list[val[3]],  
                    minute: minutes.list[val[4]],  
                }  
                break  
            default:  
                date =  
                    `${years.list[val[0]]}-${trimN(months.list[val[1]])}-${trimN(days.list[val[2]])} ${trimN(hours.list[val[3]])}:${trimN(minutes.list[val[4]])}:${trimN(seconds.list[val[5]])}`  
                obj = {  
                    year: years.list[val[0]],  
                    month: months.list[val[1]],  
                    day: days.list[val[2]],  
                    hour: hours.list[val[3]],  
                    minute: minutes.list[val[4]],  
                    second: seconds.list[val[5]],  
                }  
                break  
        }  
        if (props.fromData.trim()) date = dayjs(date).format(props.fromData)  
        nowdate = date  
        emits('change', {  
            result: date,  
            value: date,  
            obj: obj,  
        })  
    }  
    const setDays = (year, month, start = 1) => {  
        let newDays = []  
        const monthReg = /^4|6|9|11$/  
        let maxDay = ''  
        if (monthReg.test(month)) {  
            maxDay = 30  
        } else if (month === 2) {  
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {  
                maxDay = 29  
            } else {  
                maxDay = 28  
            }  
        } else {  
            maxDay = 31  
        }  
        newDays = setArray(start, maxDay)  
        return newDays  
    }  
    // 设置最大最小月日时分  
    const setStartEnd = () => {  
        const {  
            sy,  
            ey,  
            sm,  
            em,  
            sd,  
            ed,  
            sh,  
            eh,  
            sminu,  
            eminu,  
            ssec,  
            esec  
        } = getSE()  
        years.list = setArray(sy, ey)  
        // 设置最大最小月  
        if (sy === ey) {  
            startObj.months = endObj.months = setArray(sm, em)  
        } else {  
            startObj.months = setArray(sm, 12)  
            endObj.months = setArray(1, em)  
        }  
        // 设置最大最小日  
        if (sy === ey && sm === em) {  
            startObj.days = endObj.days = setArray(sd, ed)  
        } else {  
            startObj.days = setDays(sy, sm, sd)  
            endObj.days = setArray(1, ed)  
        }  
        // 设置最大最小时  
        if (sy === ey && sm === em && sd === ed) {  
            startObj.hours = endObj.hours = setArray(sh, eh)  
        } else {  
            startObj.hours = setArray(sh, 23)  
            endObj.hours = setArray(0, eh)  
        }  
        // 设置最大最小分钟  
        if (sy === ey && sm === em && sd === ed && sh === eh) {  
            startObj.minutes = endObj.minutes = setArray(sminu, eminu)  
        } else {  
            startObj.minutes = setArray(sminu, 59)  
            endObj.minutes = setArray(0, eminu)  
        }  
        // 设置最大最小秒  
        if (sy === ey && sm === em && sd === ed && sh === eh && sminu === eminu) {  
            startObj.seconds = endObj.seconds = setArray(ssec, esec)  
        } else {  
            startObj.seconds = setArray(ssec, 59)  
            endObj.seconds = setArray(0, esec)  
        }  
    }  
    // 初始化选中项  
    const initCurr = (val, month, day) => {  
        const {  
            start,  
            end,  
            sy,  
            ey,  
            sm,  
            em,  
            sd,  
            ed,  
            sh,  
            eh,  
            sminu,  
            eminu,  
            ssec,  
            esec  
        } = getSE()  
        const {  
            val: curr,  
            y: cy,  
            m: cm,  
            d: cd,  
            h: ch,  
            minu: cminu,  
            sec: csec  
        } = trimDate(val, month, day)  
        let cyi = years.list.indexOf(cy)  
        let cmi = 0  
        let cdi = 0  
        let chi = 0  
        let cminui = 0  
        let cseci = 0  
        let endSIFlag = true // 是否在最后统一设置index  
        if (curr.getTime() >= end.getTime()) {  
            //  值大于等于结束时间  
            // console.log(11)  
            months.list = endObj.months  
            days.list = endObj.days  
            hours.list = endObj.hours  
            minutes.list = endObj.minutes  
            seconds.list = endObj.seconds  
            cyi = years.list.length - 1  
            cmi = months.list.length - 1  
            cdi = days.list.length - 1  
            chi = hours.list.length - 1  
            cminui = minutes.list.length - 1  
            cseci = seconds.list.length - 1  
            endSIFlag = false  
        } else if (curr.getTime() <= start.getTime()) {  
            // 值小于等于开始时间  
            // console.log(22)  
            months.list = startObj.months  
            days.list = startObj.days  
            hours.list = startObj.hours  
            minutes.list = startObj.minutes  
            seconds.list = startObj.seconds  
            cyi = cmi = cdi = chi = cminui = cseci = 0  
            endSIFlag = false  
        } else if (cy === ey && cm === em && cd === ed && ch === eh) {  
            // 值与结束时间年/月/日/时相同  
            // console.log(222)  
            months.list = endObj.months  
            days.list = endObj.days  
            hours.list = endObj.hours  
            minutes.list = endObj.minutes  
            seconds.list = endObj.seconds  
        } else if (cy === ey && cm === em && cd === ed) {  
            // 值与结束时间年/月/日相同  
            // console.log(111)  
            months.list = endObj.months  
            days.list = endObj.days  
            hours.list = endObj.hours  
            // console.log(hours)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else if (cy === ey && cm === em) {  
            // 值与结束时间年、月相同  
            // console.log(33)  
            months.list = endObj.months  
            days.list = endObj.days  
            hours.list = setArray(0, 23)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else if (cy === ey) {  
            // 值与结束时间年份相同  
            // console.log(44)  
            months.list = endObj.months  
            days.list = setDays(cy, cm)  
            hours.list = setArray(0, 23)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else if (cy === sy && cm === sm && cd === sd && ch === sh) {  
            // 值与开始时间年/月/日/时相同  
            // console.log(99)  
            months.list = startObj.months  
            days.list = startObj.days  
            hours.list = startObj.hours  
            minutes.list = startObj.minutes  
            seconds.list = startObj.seconds  
        } else if (cy === sy && cm === sm && cd === sd) {  
            // 值与开始时间年/月/日相同  
            // console.log(88)  
            months.list = startObj.months  
            days.list = startObj.days  
            hours.list = startObj.hours  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else if (cy === sy && cm === sm) {  
            // 值与开始时间年、月相同  
            // console.log(55)  
            months.list = startObj.months  
            days.list = startObj.days  
            hours.list = setArray(0, 23)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else if (cy === sy) {  
            // 值与开始时间年份相同  
            // console.log(66)  
            months.list = startObj.months  
            days.list = setDays(cy, cm)  
            hours.list = setArray(0, 23)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        } else {  
            // 值与开始时间、结束时间不同年月  
            // console.log(77)  
            months.list = setArray(1, 12)  
            days.list = setDays(cy, cm)  
            hours.list = setArray(0, 23)  
            minutes.list = setArray(0, 59)  
            seconds.list = setArray(0, 59)  
        }  
        if (endSIFlag) {  
            const di = days.list.indexOf(cd)  
            cmi = months.list.indexOf(cm)  
            cdi = di === -1 ? days.list.length - 1 : di  
            chi = hours.list.indexOf(ch)  
            cminui = minutes.list.indexOf(cminu)  
            cseci = seconds.list.indexOf(csec)  
        }  
        console.log(pickerVal.list);  
        setTimeout((item) => {  
            pickerVal.list = [cyi, cmi, cdi, chi, cminui, cseci]  
            confirm()  
            changeDisabled.value = false  
        }, 50)  
        // $nextTick(() => {  
        // pickerVal.list = [cyi, cmi, cdi, chi, cminui]  
        // confirm()  
        // changeDisabled.value = false  
        //   // showCover.value = false  
        //   // hasChange.value = false  
        // })  
    }  
    // 设置开始/结束时间相关变量  
    const getSE = () => {  
        let s = props.startYear  
        let e = props.endYear  
        s = s ? s : '2010-01-01 00:00:00'  
        e = e ? e : '2050-12-31 23:59:59'  
        const {  
            val: start,  
            y: sy,  
            m: sm,  
            d: sd,  
            h: sh,  
            minu: sminu,  
            sec: ssec  
        } = trimDate(s)  
        const {  
            val: end,  
            y: ey,  
            m: em,  
            d: ed,  
            h: eh,  
            minu: eminu,  
            sec: esec  
        } = trimDate(e)  
        return {  
            start,  
            sy,  
            sm,  
            sd,  
            sh,  
            sminu,  
            ssec,  
            end,  
            ey,  
            em,  
            ed,  
            eh,  
            eminu,  
            esec  
        }  
    }  
    const trimDate = (val, month, day) => {  
        // const reg = /^\d{4}-\d{1,2}-\d{1,2}( \d{1,2}:\d{1,2})?(:\d{1,2})?$/  
        let curr = ''  
        if (val == '现在') {  
            curr = presentTime  
        } else {  
            if (typeof val === 'string') {  
                curr = dayjs(val,   
                ['YYYY', 'YYYY-MM-DD', 'YYYY-MM-DD HH', 'YYYY-MM-DD HH:mm', props.fromData ? props.fromData : 'YYYY-MM-DD HH:mm:ss'], 'es', true).$d  
            } else {  
                curr = new Date(val)  
            }  
        }  
        return {  
            val: curr,  
            y: curr.getFullYear(),  
            m: month ? month : curr.getMonth() + 1,  
            d: day ? day : curr.getDate(),  
            h: curr.getHours(),  
            minu: curr.getMinutes(),  
            sec: curr.getSeconds(),  
        }  
    }  
    // 获取一个范围内的整数,返回数组  
    const setArray = (start, end) => {  
        const arr = []  
        for (let i = start; i <= end; i++) {  
            arr.push(i)  
        }  
        return arr  
    }  
    // 将数字转换成两位  
    const trimNum = (num) => {  
        num = num >= 10 ? num : `0${num}`  
        return num  
    }  
</script>  

<style scoped>  
    @import './w-picker.css';  
</style>

操作步骤:

粘贴代码运行

预期结果:

能够正常选择

实际结果:

无法正常选择,样式错乱

bug描述:

歪歪扭扭的,选不上。并且在三个不同的机型有不一样的表现,其中se的最正常

2024-07-02 09:42 负责人:DCloud_UNI_BFC 分享
已邀请:
DCloud_UNI_BFC

DCloud_UNI_BFC

你好可以通过 css + template 配合调整

// CSS   
.w-picker-item {  
     line-height: 88upx;  
}  
// template  
:indicator-style="{height: '88upx'}"  

indicator-style 属性详情 https://uniapp.dcloud.net.cn/component/picker-view.html

2***@qq.com

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

目前看起来是屏幕越宽,看起来越正常。求求各位老大帮忙看看吧

  • 2***@qq.com

    你是uni官方的测试人员吗,测这么仔细

    2024-07-03 10:48

  • 2***@qq.com (作者)

    回复 2***@qq.com: 不是,但是这个bug真的很恶心,好多年了

    2024-07-03 14:27

2***@qq.com

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

没有官方管了吗

DCloud_UNI_CHB

DCloud_UNI_CHB

你把屏幕大小设置成100%,不要故意缩小屏幕,然后再测试看看效果。

  • 2***@qq.com (作者)

    我真机运行也歪啊,

    2024-07-12 15:54

  • 2***@qq.com (作者)

    跟这个没啥关系,我在h5,小程序,真机都遇到了这个问题,真机总不能缩小屏幕吧

    2024-07-12 15:56

  • 2***@qq.com (作者)

    而且不是手机宽度问题,我只显示年月日也歪

    2024-07-12 15:57

  • 2***@qq.com (作者)

    上传组件压缩包了,可以试试看

    2024-07-12 16:22

  • 2***@qq.com (作者)

    使用最新版本的huilderx会这样,半年前的没事

    2024-07-13 08:41

  • 2***@qq.com (作者)

    4.15版本没这问题

    2024-07-13 09:16

2***@qq.com

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

真的服了,hbuilder的问题,我用同事电脑就好使,他的半年没更新了

要回复问题请先登录注册