评论

快速实现一个自定义日期时间 picker

自定义日期时间,实现 picker 效果。

最近有个自定义时间选取功能需求,特此提取整理成代码片段,分享给可能有需要的小伙伴参考。

具体效果:

代码仓库:
https://git.weixin.qq.com/sg996/datetime-picker

分享链接:
https://developers.weixin.qq.com/s/YMM1Icmy7GDN

代码片段:
方式一:datetime-picker/index.js

const dayjs = require('../../utils/dayjs.min.js');

const HOUR_UNIT = '时';
const MINUTE_UNIT = '分';
const weekdaysShort = '周日_周一_周二_周三_周四_周五_周六'.split('_');
const getDateList = () => {
    let list = []
    // 获取未来三十天时间(实现来自百度参考)
    for (var i = 0; i < 30; i++) {
        let time = new Date(new Date()
            .setDate(new Date().getDate() + i)).toLocaleDateString();
        time = dayjs(time).format('YYYY/MM/DD'); // 兼容性差异处理
        const temp = {
            date: dayjs(time).format('YYYY/MM/DD'),
            year: dayjs(time).format('YYYY'),
            month: dayjs(time).format('MM'),
            text: `${dayjs(time).format('MM月DD日')} ${weekdaysShort[dayjs(time).day()]}`
        }
        list.push(temp)
    }
    return list;
}
const getHourList = (isToday = true) => {
    const hour = dayjs().hour();
    const minute = dayjs().minute();
    let list = []
    if (isToday) {
        list = [...new Array(24).keys()].filter(i => i >= +hour).map(i => (`00${i}`.substr(-2)));
        if (minute > 45 && list.length > 1) list.shift();
    } else {
        list = [...new Array(24).keys()].map(i => (`00${i}`.substr(-2)));
    }
    list = list.map(i => ({
        text: `${i}${HOUR_UNIT}`
    }))
    return list;
}
const getMinuteList = (isToday = true, isHour = true) => {
    const minute = dayjs().minute();
    let list = ['15', '30', '45'].filter(i => +i >= +minute).map(i => i);
    if (!isToday || !isHour || minute > 45) list = ['00', '15', '30', '45'];
    list = list.map(i => ({
        text: `${i}${MINUTE_UNIT}`
    }))
    return list;
}
const defaultHourList = [...new Array(24).keys()].map(i => (`00${i}`.substr(-2))).map(i => ({
    text: `${i}${HOUR_UNIT}`
}))
const defaultDateRange = [getDateList(), getHourList(), getMinuteList()]

Component({
    properties: {
        currentDate: {
            type: String,
            value: dayjs(),
        },
    },
    data: {
        timeIndex: [0, 0, 0],
        dateRange: defaultDateRange,
        oldDateRange: defaultDateRange,
    },
    observers: {
        'currentDate': function (date) {
             // 时间格式
            if (isNaN(date) && !isNaN(Date.parse(date))) {
                // 回显时间小于当前时间按当前时间
                if (dayjs(date).isBefore(dayjs())) {
                    date = dayjs()
                }
            } else {
                date = dayjs()
            }
            // 回显数据(先转换整点时刻)
            let day = dayjs(date).format('YYYY/MM/DD')
            let hour = dayjs(date).format('HH')
            let minute = dayjs(date).format('mm')
            if (+minute > 45) {
                hour = (`00${+hour + 1}`.substr(-2));
                minute = '00';
                date = `${day} ${hour}:${minute}`;
            }
            if (+hour === 24) {
                hour = '00';
                date = dayjs(`${day} ${hour}:${minute}`).add(1, 'day').format('YYYY/MM/DD HH:mm');
                day = dayjs(date).format('YYYY/MM/DD');
            }
            const isToday = dayjs().isSame(date, 'day')
            const isHour = dayjs().isSame(date, 'hour')
            const dateList = getDateList()
            const dateHour = getHourList(isToday)
            let dateMinute = getMinuteList(isToday, isHour)
            let d0 = dateList.findIndex(i => i.date === day)
            d0 = d0 === -1 ? 0 : d0;
            let d1 = dateHour.findIndex(i => i.text === `${hour}${HOUR_UNIT}`)
            d1 = d1 === -1 ? 0 : d1;
            let d2 = dateMinute.findIndex(i => +minute <= +i.text.replace(MINUTE_UNIT, ''))
            d2 = d2 === -1 ? 0 : d2;
            // 更新对应数据
            this.setData({
                'dateRange[1]': dateHour,
                'dateRange[2]': dateMinute,
                timeIndex: [d0, d1, d2],
                oldDateRange: [getDateList(), dateHour, dateMinute],
            })
        }
    },
    methods: {
        bindMultiPickerColumnChange(e) {
            const {
                column,
                value,
            } = e.detail;
            // 第一列【不是】第一个时,第二列默认固定数据
            if (column === 0 && value !== 0) {
                this.setData({
                    'dateRange[1]': defaultHourList,
                })
            }
            // 第一列【是】第一个时,重置第二列
            if (column === 0 && value === 0) {
                this.setData({
                    'dateRange[1]': getHourList(),
                })
            }
            // 当第一列 【或】 第二列【不是】第一个时,第三列默认固定数据
            if ([0, 1].includes(column) && value !== 0) {
                this.setData({
                    'dateRange[2]': ['00', '15', '30', '45'].map(i => ({
                        text: `${i}${MINUTE_UNIT}`
                    }))
                })
            }
            // 当第一列 【和】 第二列【都是】第一个时,重置第三列
            const timeIndex = e.currentTarget.dataset.value;
            if (timeIndex[0] === 0 && timeIndex[1] === 0) {
                this.setData({
                    'dateRange[2]': getMinuteList()
                })
            }
        },
        bindPickerChange(e) {
            const timeIndex = e.detail.value;
            const [c1, c2, c3] = timeIndex;
            const dateRange = this.data.dateRange;
            const [l1, l2, l3] = dateRange;
            const hour = l2[c2].text.replace(HOUR_UNIT, '')
            const minute = l3[c3].text.replace(MINUTE_UNIT, '')

            const dateTime = `${l1[c1].date} ${hour}:${minute}`;
            const dateTimeText = `${l1[c1].text} ${hour}${HOUR_UNIT}${minute}${MINUTE_UNIT}`;
            this.setData({
                timeIndex,
            })
            this.triggerEvent('confirm', {
                dateTime,
                dateTimeText
            })
        },
        bindPickerCancel(e) {
            const timeIndex = e.target.dataset.value;
            const oldDateRange = this.data.oldDateRange;
            this.setData({
                timeIndex,
                dateRange: oldDateRange,
            })
        }
    }
})

datetime-picker/index.wxml

<picker mode="multiSelector" bindcolumnchange="bindMultiPickerColumnChange" bindchange="bindPickerChange" bindcancel="bindPickerCancel" value="{{timeIndex}}" data-value="{{timeIndex}}" data-key="timeIndex" range="{{dateRange}}" range-key="text">
    <slot />
</picker>
最后一次编辑于  2022-10-22  
点赞 4
收藏
评论

2 个评论

  • 🇨🇳
    🇨🇳
    2023-09-07

    你好,能获取到时间戳吗,采用picker-view自定义方式,如何获取到时间戳呢,伙现在只能通过e.detail获取到文字格式日期时间,不知道如何获取到对应胡时间戳

    2023-09-07
    赞同
    回复 1
    • 与光同行
      与光同行
      01-31
      很抱歉没能够及时回复帮助到你。为感谢关注和方便后续同学学习,还是做以下回复:
      picker-view 自定义方式(datetime-piker/index.js)的 handleConfirm 方法返回了当前时间可以直接转换时间戳
      01-31
      回复
  • Desperado
    Desperado
    2023-05-25

    示例代码有问题

    show 是干什么的

    2023-05-25
    赞同
    回复 1
登录 后发表内容