小程序日历组件(选择区间日期)

.wxml

<view class="calendar">

    <view class="calendar_header_box">

        <view class="cuIcon-back btn btnl {{prevBtn ? '' : 'cannot_edit'}}" bindtap="prevMonth"></view>

        <view class="time">{{year}}年{{month}}月</view>

        <view class="cuIcon-right btn btnr {{nextBtn ? '' : 'cannot_edit'}}" bindtap="nextMonth"></view>

    </view>

    <!--周标题-->

    <view class="calendar_weeks">

        <text wx:for="{{weekTitle}}" wx:key="index">{{item}}</text>

    </view>

    <!--日期-->

    <view class="calendar_days">

        <block wx:for="{{days_array}}" wx:for-item="item" wx:key="index" wx:for-index="i">

            <!--日期行-->

            <view class="calendar_row">

                <block wx:for="{{days_array[i]}}" wx:for-item="dayItem" wx:key="index">

                    <view class="calendar_cell {{dayItem.abled ? '' : 'cannot_edit'}} {{dayItem.isStart || dayItem.isEnd || dayItem.isToday ? 'flag_color' : ''}}" bindtap="dayClick" data-day="{{dayItem}}">

                        {{dayItem.day}}

                        <view class="flag_style {{dayItem.isToday ? 'today' : ''}} {{dayItem.isStart || dayItem.isEnd ? 'select_time' : ''}}" wx:if="{{dayItem.isStart || dayItem.isEnd || dayItem.isToday}}"></view>

                        <view class="during_style" wx:if="{{dayItem.during && dunringStyle}}"></view>

                        <view class="during_left" wx:if="{{dayItem.isStart && dunringStyle}}"></view>

                        <view class="during_right" wx:if="{{dayItem.isEnd && dunringStyle}}"></view>

                    </view>

                </block>

            </view>

        </block>

    </view>

</view>




.wxss

.calendar {

  width: 750rpx;

  height: 650rpx;

}

.calendar .calendar_header_box {

  width: 750rpx;

  height: 60rpx;

  display: flex;

  justify-content: center;

  align-items: center;

  font-size: 42rpx;

  color: #333333;

  text-align: center;

  margin-bottom: 30rpx;

}

.calendar .calendar_header_box .btn {

  width: 250rpx;

  height: 60rpx;

}

.calendar .calendar_header_box .btnl {

  text-align: right;

}

.calendar .calendar_header_box .btnr {

  text-align: left;

}

.calendar .calendar_header_box .time {

  width: 270rpx;

  position: relative;

  top: 5rpx;

  margin: 0 20rpx;

}

.calendar .calendar_weeks {

  width: 750rpx;

  height: 80rpx;

  padding: 0 60rpx;

  display: flex;

  justify-content: space-between;

  align-items: center;

  color: #999999;

  font-size: 37rpx;

}

.calendar .calendar_days {

  width: 750rpx;

  padding: 0 30rpx;

}

.calendar .calendar_days .calendar_row {

  width: 100%;

  height: 80rpx;

  display: flex;

  justify-content: space-between;

  align-items: center;

}

.calendar .calendar_days .calendar_row .calendar_cell {

  position: relative;

  height: 80rpx;

  flex: 1;

  text-align: center;

  line-height: 80rpx;

  font-size: 34rpx;

}

.calendar .calendar_days .calendar_row .calendar_cell .flag_style {

  width: 60rpx;

  height: 60rpx;

  border-radius: 50%;

  position: absolute;

  left: 50%;

  top: 50%;

  transform: translateX(-50%) translateY(-50%);

  z-index: -1;

}

.calendar .calendar_days .calendar_row .calendar_cell .during_style {

  width: 110rpx;

  height: 60rpx;

  border-radius: 10rpx;

  background-color: #D1F9D3;

  position: absolute;

  left: 50%;

  top: 50%;

  transform: translateX(-50%) translateY(-50%);

  z-index: -2;

}

.calendar .calendar_days .calendar_row .calendar_cell .during_left {

  width: 55rpx;

  height: 60rpx;

  background-color: #D1F9D3;

  position: absolute;

  left: 50%;

  top: 50%;

  transform: translateY(-50%);

  z-index: -2;

  border-radius: 10rpx;

}

.calendar .calendar_days .calendar_row .calendar_cell .during_right {

  width: 55rpx;

  height: 60rpx;

  background-color: #D1F9D3;

  position: absolute;

  right: 50%;

  top: 50%;

  transform: translateY(-50%);

  z-index: -2;

  border-radius: 10rpx;

}

.cannot_edit {

  color: #e7e7e7;

}

.today {

  background-color: var(--basecolor);

}

.select_time {

  background-color: #5BAC60;

}

.flag_color {

  color: #ffffff;

}



.js

Component({

  properties: {

    // 时间的性质 ‘start’ 选择开始时间 ‘end’ 选择结束时间

    type: {

      type: String,

      value: '',

      observer(newVal, oldVal, changedPath) {

        this.setData({

          typeOfTime: newVal,

          days_array: this.setCalendarData(this.data.year, this.data.month)

        })

      }

    },

    // 开始时间

    start: {

      type: String,

      value: '',

      observer(newVal, oldVal, changedPath) {

        this.setData({

          timeStart: new Date(newVal).getTime()

        })

      }

    },

    // 结束时间

    end: {

      type: String,

      value: '',

      observer(newVal, oldVal, changedPath) {

        this.setData({

          timeEnd: new Date(newVal).getTime()

        })

      }

    }

  },

  data: {

    year: new Date().getFullYear(), // 年份

    month: new Date().getMonth() + 1, // 月份

    day: new Date().getDate(), // 天

    days_array: [], // 日期数组

    weekTitle: ['日', '一', '二', '三', '四', '五', '六'], // 星期

    max_year: 2099, // 最大年份

    max_month: 12,  // 最大月份

    min_year: 1900, // 最小年份

    min_month: 1,  // 最小月份

    toyear: new Date().getFullYear(), // 今年

    tomonth: new Date().getMonth() + 1, // 今月

    today: new Date().getDate(), // 今天

    todayStamp: new Date().setHours(8, 0, 0, 0), // 今天的时间戳

    typeOfTime: '', // 时间的性质 ‘start’ 选择开始时间 ‘end’ 选择结束时间

    timeStart: null, // 开始服务时间戳

    timeEnd: null, // 结束服务时间戳

    dunringStyle: false, // 是否显示区间样式

    prevBtn: true, // 上个月是否可点

    nextBtn: true // 下个月是否可点

  },

  methods: {

    // 日历显示循环

    setCalendarData: function (year, month) {

      // 本月第一天是周几,0是星期日,6是星期六

      const empty_days_count = new Date(year, month - 1, 1).getDay()

      let empty_days = new Array

      const prev_month = month - 1 == 0 ? 12 : month - 1 // 上个月的月份数

      const prev_year = month - 1 == 0 ? this.data.year - 1 : this.data.year

      // 上个月的日期

      for (let i = 0; i < empty_days_count; i++) {

        empty_days.push({

          day: -1,

          month: prev_month,

          year: prev_year,

          info: 'prev',

          date:`${prev_year}-${prev_month<10?`0${prev_month}`:prev_month}`

        })

      }

      // 下个月的日期

      const last_day = new Date(year, month, 0) // 本月最后一天

      const days_count = last_day.getDate() // 本月最后一天是几号

      const last_date = last_day.getDay() // 本月最后一天是星期几

      const next_month = month + 1 == 13 ? 1 : month + 1 // 下个月的月份数

      const next_year = month + 1 == 13 ? this.data.year + 1 : this.data.year

      let empty_days_last = new Array

      for (let i = 0; i < 6 - last_date; i++) {

        empty_days_last.push({

          day: -2,

          month: next_month,

          year: next_year,

          info: 'next',

          date:`${next_year}-${next_month<10?`0${next_month}`:next_month}`

        })

      }

      // 本月的日期

      let temp = new Array

      for (let i = 1; i <= days_count; i++) {

        temp.push({

          day: i,

          month: month,

          year: year,

          info: 'current',

          date:`${year}-${month<10?`0${month}`:month}-${i<10?`0${i}`:i}`,

        })

      }

      let days = empty_days.concat(temp, empty_days_last) // 上个月 + 本月 + 下个月

      // 显示下月的日期

      let index = days.findIndex(element => { return element.day == -2 })

      if (index != -1) {

        const length = days.length

        const count = length - index

        for (let i = 1; i <= count; i++) {

          days[index + i - 1].day = i

          days[index+i-1].date = `${days[index+i-1].date}-${i<10?`0${i}`:i}`

        }

      }

      // 显示上月的日期

      index = days.findIndex(element => { return element.day == 1 }) - 1

      if (index != -1) {

        // 获取上个月有多少天

        const last_month_day = new Date(year, month - 1, 0).getDate()

        for (let i = 0; i <= index; i++) {

          days[i].day = last_month_day - index + i

          days[i].date = `${days[i].date}-${days[i].day<10?`0${days[i].day}`:days[i].day}`

        }

      }

      days.forEach(item => {

        item.stamp = new Date(item.date).getTime()

        // 判断是否是今天

        if (item.stamp == this.data.todayStamp) {

          item.isToday = true

        } else {

          item.isToday = false

        }

        // 判断是否可操作

        if (this.properties.type == 'start') {

          if (item.stamp < this.data.todayStamp || item.stamp > (this.data.timeEnd || 9999999999999)) {

            item.abled = false

          } else {

            item.abled = true

          }

        } else if (this.properties.type == 'end') {

          if (item.stamp < this.data.todayStamp || item.stamp < (this.data.timeStart || 0)) {

            item.abled = false

          } else {

            item.abled = true

          }

        } else {

          if (item.stamp < this.data.todayStamp) {

            item.abled = false

          } else {

            item.abled = true

          }

        }

        // 判断是否为开始日期或结束日期

        if (item.stamp == this.data.timeStart) {

          item.isStart = true

        } else {

          item.isStart = false

        }

        if (item.stamp == this.data.timeEnd) {

          item.isEnd = true

        } else {

          item.isEnd = false

        }

        // 判断是否为开始与结束之间的值

        if (this.data.timeEnd && this.data.timeStart) {

          if (item.stamp < this.data.timeEnd && item.stamp > this.data.timeStart) {

            item.during = true

          } else {

            item.during = false

          }

        } else {

          item.during = false

        }

      })

      // 判断是否显示区间样式

      if (this.data.timeStart && this.data.timeEnd && this.data.timeStart != this.data.timeEnd) {

        this.setData({

          dunringStyle: true

        })

      } else {

        this.setData({

          dunringStyle: false

        })

      }

      // 判断切换月份按钮是否可点

      let theNextYear

      let theNextMonth

      if (this.data.month == 12) {

        theNextYear = this.data.year + 1

        theNextMonth = 1

      } else {

        theNextYear = this.data.year

        theNextMonth = this.data.month + 1

      }

      const thisMonth = `${this.data.year}-${this.data.month<10?`0${this.data.month}`:this.data.month}-01`

      const nextMonth = `${theNextYear}-${theNextMonth<10?`0${theNextMonth}`:theNextMonth}-01`

      const thisMonthStamp = new Date(thisMonth).getTime()

      const nextMonthStamp = new Date(nextMonth).getTime()

      if (this.properties.type == 'start') {

        if (thisMonthStamp <= this.data.todayStamp) {

          this.setData({

            prevBtn: false

          })

        } else {

          this.setData({

            prevBtn: true

          })

        }

        if (nextMonthStamp > (this.data.timeEnd || 9999999999999)) {

          this.setData({

            nextBtn: false

          })

        } else {

          this.setData({

            nextBtn: true

          })

        }

      } else if (this.properties.type == 'end') {

        this.setData({

          nextBtn: true

        })

        if (thisMonthStamp <= this.data.todayStamp || thisMonthStamp < (this.data.timeStart || 0)) {

          this.setData({

            prevBtn: false

          })

        } else {

          this.setData({

            prevBtn: true

          })

        }

      }

      let days_array = new Array

      let week = new Array

      for (let i = 0; i < days.length; i++) {

        week.push(days[i])

        if (i % 7 == 6) {

          days_array.push(week)

          week = new Array

        }

      }

      if (week.length > 0) {

        days_array.push(week)

      }

      return days_array

    },

    // 点击下个月

    nextMonth: function () {

      if (!this.data.nextBtn) return

      const eventDetail = {

        prevYear: this.data.year,

        prevMonth: this.data.month

      }

      if (this.data.month == 12) {

        this.setData({

          year: this.data.year + 1,

          month: 1

        })

      } else {

        this.setData({

          month: this.data.month + 1

        })

      }

      this.setData({

        days_array: this.setCalendarData(this.data.year, this.data.month)

      })

      eventDetail['currentYear'] = this.data.year

      eventDetail['currentMonth'] = this.data.month

      this.triggerEvent('nextMonth', eventDetail)

    },

    //点击上个月

    prevMonth: function () {

      if (!this.data.prevBtn) return

      if (this.data.month == 1) {

        this.setData({

          year: this.data.year - 1,

          month: 12

        })

      } else {

        this.setData({

          month: this.data.month - 1

        })

      }

      this.setData({

        days_array: this.setCalendarData(this.data.year, this.data.month)

      })

    },

    //日期选择器变化

    dateChange: function (event) {

      const value = event.detail.value

      const date = new Date(value)

      const year = date.getFullYear()

      const month = date.getMonth() + 1

      this.setData({

        year: year,

        month: month,

        days_array: this.setCalendarData(year, month)

      })

    },

    //点击具体日期

    dayClick: function (event) {

      const click_day = event.currentTarget.dataset.day

      if (!click_day.abled) return

      this.triggerEvent('daysclick', click_day)

      this.setData({

        days_array: this.setCalendarData(this.data.year, this.data.month)

      })

    }

  },

  lifetimes: {

    created: function () {

    },

    attached: function () {

      this.setData({

        days_array: this.setCalendarData(this.data.year, this.data.month)

      })

    },

    ready: function () {

    },

  }

})




.json

{

  "component": true,

  "usingComponents": {}

}

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