微信小程序里实现自定义日期控件

最近在研究微信小程序,需要实现一个自定义日期的功能,类似于猫眼app上选择日期,可以按日、按周、按月、按年、自定义日期,为此特地将其写成了一个组件,供有需要的朋友参考。
本人所用框架是wepy,所以此组件结构为wepy代码结构。

大致介绍:
1.按日的日历控件采用的极点日历插件,详情请看:https://github.com/czcaiwj/calendar
2.组件中所用到的一些组件为ivew weapp组件,详情使用请看我的另一篇分享:https://www.jianshu.com/p/e07b7cf5e494
3.组件中按周选择,周我是从2017年至今取的,具体实现可看我另一篇分享:https://www.jianshu.com/p/5112df795162;在本篇onLoad()方法里也有实现;因本人开发需要,设定功能为按周可多选,这个可以根据自身开发需求调整;
4.本组件时间默认从17年开始至今,也可根据自身实际需求调整。

代码如下:

<style type="less">
    .home {
        height: 100%;
        .calendar-header {
            font-size: large;
            color: #406BF8;
         }
        .calendar-board {
            color: #406BF8;
        }
        .week_year_style {
            font-size: 30 rpx;
            padding: 20 rpx 15 rpx;
            text-align: center;
        }
        .week_selectyear_style {
            background-color: #fff;
            color: #406BF8;
        }
        .calendar {
            background-color: #fcfcfc;
            //padding-top: 10px;
        }
    }
</style>
<template>
    <view class="home page">
        <i-tabs current="{{ currentTab }}" color="#406BF8" bindchange="handleChangeTab">
            <i-tab key="按日" title="按日"></i-tab>
            <i-tab key="按周" title="按周"></i-tab>
            <i-tab key="按月" title="按月"></i-tab>
            <i-tab key="按年" title="按年"></i-tab>
            <i-tab key="自定义" title="自定义"></i-tab>
        </i-tabs>
        <view hidden="{{currentTab != '按日'}}" style="margin-top: 30rpx">
            <calendar cell-size="40"
                      show-more-days="true"
                      lunar="true"
                      weeks-type="cn"
                      calendar-style="calendar"
                      header-style="calendar-header"
                      board-style="calendar-board"
                      days-color="{{days_style}}"
                      start-date="2017-01"
                      end-date="2018-08"
                      binddayClick="dayClick"
                      bindnextMonth="next"
                      bindprevMonth="prev"
            />
        </view>
        <view hidden="{{currentTab != '按周'}}">
            <view style="display: flex">
                <view style="width: 160rpx;background-color: #f6f6f6;border-right: 1rpx solid #e6e6e6">
                    <block wx:for="{{yearArray}}" wx:for-item="item" wx:key="item">
                        <view class="week_year_style {{weeksYears==item?'week_selectyear_style':''}}"
                              bindtap='changeWeekYear({{item}})'>{{item + '年'}}
                        </view>
                    </block>
                </view>
                <scroll-view scroll-y style="height: 600px;">
                    <i-cell-group>
                        <block wx:for="{{weeksArray[weeksYears]}}" wx:for-item="category" wx:key="category">
                            <i-cell title="{{category.weeks}}" bindtap="handleWeeksChange('{{index}}')">
                                <i-icon wx:if="{{category.select}}" type="right" size="20" color="#406BF8"
                                        slot="footer"/>
                            </i-cell>
                        </block>

                    </i-cell-group>
                </scroll-view>
            </view>
        </view>

        <view hidden="{{currentTab != '按月'}}">
            <view style="display: flex">
                <view style="width: 160rpx;background-color: #f6f6f6;border-right: 1rpx solid #e6e6e6">
                    <block wx:for="{{yearArray}}" wx:for-item="item" wx:key="item">
                        <view class="week_year_style {{monthYear==item?'week_selectyear_style':''}}"
                              bindtap='changeMonthYear({{item}})'>{{item + '年'}}
                        </view>
                    </block>

                </view>
                <scroll-view scroll-y style="height: 600px;">
                    <i-cell-group>
                        <block wx:for="{{monthYear==year?currentMonthArray:fullMonthArray}}" wx:for-item="category"
                               wx:key="*this">
                            <i-cell title="{{category+'月'}}" bindtap="handleMonthChange('{{category}}')">
                                <i-icon wx:if="{{category==selectMonth}}" type="right" size="20" color="#406BF8"
                                        slot="footer"/>
                            </i-cell>
                        </block>

                    </i-cell-group>
                </scroll-view>
            </view>
        </view>

        <view hidden="{{currentTab != '按年'}}">
            <i-cell-group>
                <block wx:for="{{yearArray}}" wx:for-item="category" wx:key="category">
                    <i-cell title="{{category+'年'}}" bindtap="handleYearChange('{{category}}')">
                        <i-icon wx:if="{{category==selectYear }}" type="right" size="20" color="#406BF8" slot="footer"/>
                    </i-cell>
                </block>

            </i-cell-group>
        </view>

        <view hidden="{{currentTab != '自定义'}}" style="margin-top: 30rpx">
            <calendar cell-size="40"
                      show-more-days="true"
                      lunar="true"
                      weeks-type="cn"
                      calendar-style="calendar"
                      header-style="calendar-header"
                      board-style="calendar-board"
                      days-color="{{define_days_style}}"
                      start-date="2017-01"
                      end-date="2018-08"
                      binddayClick="dayClick_define"
                      bindnextMonth="next_define"
                      bindprevMonth="prev_define"

            />
        </view>

    </view>
</template>
<script>
    import wepy from 'wepy';

    const MONTHS = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'June.', 'July.', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'];

    export default class TabsContent extends wepy.component {
        props = {
            openDateModal: {
                type: Boolean,
                default: false,
                twoWay: true
            },
            dateSelect: {
                type: String,
                default: '',
                twoWay: true
            },
            dateFilter: {
                type: String,
                default: '',
                twoWay: true
            },
            filterWeekArray: {
                type: String,
                default: '',
                twoWay: true
            },
            filterWeekSelect: {
                type: String,
                default: '',
                twoWay: true
            }
        };
        data = {
            currentTab: '按日',  //Tabs页切换

            year: new Date().getFullYear(),      // 年份
            month: new Date().getMonth() + 1,    // 月份
            day: new Date().getDate(),
            str: MONTHS[new Date().getMonth()],  // 月份字符串

            days_style: [{month: 'current', day: new Date().getDate(), color: '#fff', background: '#eb4986'}],  //按日选中日期样式
            selectDate: [],   //按日选择的日期

            yearArray: [],  //从2017年起至今
            weeksYears: new Date().getFullYear(),  //按周选择了哪一年
            weeksArray: {},   //从2017年起至今的所有周
            selectWeekArray: [],   //选择的周

            fullMonthArray: [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
            currentMonthArray: [],  //今年过了几个月
            monthYear: new Date().getFullYear(),  //按月选择了哪一年
            selectMonth: 0,  //按月选择了哪一月

            selectYear: 0,  //按年选择了哪一年

            define_days_style: [{month: 'current', day: new Date().getDate(), color: '#fff', background: '#eb4986'}],  //自定义日期格式
            selectDate_define: []


        };

        methods = {
            handleChangeTab({detail}) {
                this.currentTab = detail.key
                this.dateFilter = this.currentTab
            },

            dayClick: function (event) {
                let style = (event.detail.year == this.year && event.detail.month == this.month) ?
                    [{month: 'current', day: new Date().getDate(), color: '#fff', background: '#eb4986'},
                        {month: 'current', day: event.detail.day, color: '#fff', background: '#406BF8'}] :
                    [{month: 'current', day: event.detail.day, color: '#fff', background: '#406BF8'}]
                this.days_style = style
                this.selectDate = [event.detail.year, event.detail.month, event.detail.day]
                this.openDateModal = false
                this.dateFilter = this.currentTab
                this.dateSelect = [event.detail.year, event.detail.month, event.detail.day]
            },
            next: function (event) {
                if (event.detail.currentYear == this.year && event.detail.currentMonth == this.month)
                    this.days_style = [{
                        month: 'current',
                        day: new Date().getDate(),
                        color: '#fff',
                        background: '#eb4986'
                    }]
                else this.days_style = [vent.detail.year, event.detail.month, event.detail.day]
            },
            prev: function (event) {
                this.days_style = []
            },

            changeWeekYear(year) {
                this.weeksYears = year
            },
            handleWeeksChange(weekIndex) {
                this.weeksArray[this.weeksYears][weekIndex].select = !this.weeksArray[this.weeksYears][weekIndex].select

                if (this.selectWeekArray[this.weeksYears]) {
                    let bool = this.selectWeekArray[this.weeksYears].some(index => index == weekIndex)
                    if (bool) { //真 已存在 delete
                        //if(this.selectWeekArray[this.weeksYears].length>1)
                        this.selectWeekArray[this.weeksYears].remove(weekIndex)
                    } else {   //假  push
                        this.selectWeekArray[this.weeksYears].push(weekIndex)
                        this.selectWeekArray[this.weeksYears].sort()
                    }
                } else {
                    let temp = {}
                    temp[this.weeksYears] = []
                    let a = [weekIndex]
                    temp[this.weeksYears] = a
                    this.selectWeekArray = temp
                }
                this.filterWeekSelect = this.selectWeekArray  //回调到父级页面
            },

            changeMonthYear(year) {
                this.monthYear = year
            },
            handleMonthChange(month) {
                this.selectMonth = month
                this.openDateModal = false
                this.dateFilter = this.currentTab
                this.dateSelect = [this.monthYear, this.selectMonth]
            },

            handleYearChange(year) {
                this.selectYear = year
                this.openDateModal = false
                this.dateFilter = this.currentTab
                this.dateSelect = [year]
            },

            dayClick_define: function (event) {
                let style = []
                if (this.selectDate_define.length == 0) {  //第一次点击
                    this.selectDate_define.push([event.detail.year, event.detail.month, event.detail.day])
                    if (event.detail.year == this.year && event.detail.month == this.mounth) {
                        style = [{month: 'current', day: new Date().getDate(), color: '#fff', background: '#eb4986'},
                            {month: 'current', day: event.detail.day, color: '#fff', background: '#406BF8'}]
                    }
                    this.define_days_style = style
                } else if (this.selectDate_define.length == 1) {   //选中第二个日期就关闭页面
                    this.selectDate_define.push([event.detail.year, event.detail.month, event.detail.day])
                    this.define_days_style.push({
                        month: 'current',
                        day: event.detail.day,
                        color: '#fff',
                        background: '#406BF8'
                    })

                    this.openDateModal = false
                    this.dateFilter = this.currentTab
                    this.dateSelect = this.selectDate_define
                } else {   //重新自定义日期
                    this.selectDate_define = [[event.detail.year, event.detail.month, event.detail.day]]
                    style = [{month: 'current', day: new Date().getDate(), color: '#fff', background: '#eb4986'},
                        {month: 'current', day: event.detail.day, color: '#fff', background: '#406BF8'}]
                    this.define_days_style = style
                }
            },
            next_define: function (event) {
                if (event.detail.currentYear == this.year && event.detail.currentMonth == this.month)
                    this.define_days_style = [{
                        month: 'current',
                        day: new Date().getDate(),
                        color: '#fff',
                        background: '#eb4986'
                    }]
                else this.define_days_style = [event.detail.year, event.detail.month, event.detail.day]
            },
            prev_define: function (event) {
                this.define_days_style = []
            },

        };

        onLoad() {
            let currentYear = new Date().getFullYear()
            let currentMonth = new Date().getMonth() + 1
            for (var i = currentYear; i >= 2017; i--) {
                this.yearArray.push(i)
            }
            for (var i = currentMonth; i >= 1; i--) {
                this.currentMonthArray.push(i)
            }

            let weeksArray = {}   //计算2017年至今的所有周
            for (var i = 0; i <= this.yearArray.length; i++) {
                let index = 1;
                let temp = []
                if (i == 0) {  //今年
                    for (let i of createWeeks(this.yearArray[i])) {
                        let start = i[0],
                            end = i[1];
                        if (end <= new Date().getTime() || (start <= new Date().getTime() && end >= new Date().getTime())) {
                            let a = start <= new Date().getTime() && end >= new Date().getTime() ?
                                '第' + formatDig(index++) + '周(' + formatDate(start) + '日-' + formatDate(end) + '日)' + ' 本周' :
                                '第' + formatDig(index++) + '周(' + formatDate(start) + '日-' + formatDate(end) + '日)'
                            temp.push({'weeks': a, 'select': false})
                        }
                    }
                } else {
                    for (let i of createWeeks(this.yearArray[i])) {
                        let start = i[0],
                            end = i[1];
                        let a = '第' + formatDig(index++) + '周(' + formatDate(start) + '日-' + formatDate(end) + '日)'
                        temp.push({'weeks': a, 'select': false})
                    }
                }
                if (this.yearArray[i] != undefined) {
                    weeksArray[this.yearArray[i]] = temp.reverse();
                }
            }
            this.weeksArray = weeksArray
            this.filterWeekArray = weeksArray

        }
    }

    function formatDig(num) {
        //return num>9?''+num:'0'+num;
        return num;
    }

    function formatDate(mill) {
        var y = new Date(mill);
        let raws = [
            //y.getFullYear(),
            formatDig(y.getMonth() + 1),
            formatDig(y.getDate()),
            //y.getDay()||7  //获取星期几
        ];
        //let format=['年','月','日 星期'];
        let format = ['月', '日'];
        return String.raw({raw: raws}, ...format);
    }

    function* createWeeks(year) {
        const ONE_DAY = 24 * 3600 * 1000;
        let start = new Date(year, 0, 1),
            end = new Date(year, 11, 31);
        let firstDay = start.getDay() || 7,
            lastDay = end.getDay() || 7;
        let startTime = +start,
            endTime = startTime + (7 - firstDay) * ONE_DAY,
            _endTime = end - (7 - lastDay) * ONE_DAY;
        yield [startTime, endTime];
        startTime = endTime + ONE_DAY;
        endTime = endTime + 7 * ONE_DAY;
        while (endTime < _endTime) {
            yield [startTime, endTime];
            startTime = endTime + ONE_DAY;
            endTime = endTime + 7 * ONE_DAY;
        }
        yield [startTime, +end];
    }

    Array.prototype.remove = function (val) {
        var index = this.indexOf(val);
        if (index > -1) {
            this.splice(index, 1);
        }
    };
</script>

效果如下:
1.jpeg
2.jpeg
3.jpeg
4.jpeg
WechatIMG267.jpeg
WechatIMG268.jpeg
WechatIMG274.jpeg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容