wepy 微信小程序日历组件(原生需修改)

效果:在这里插入图片描述

<style lang="less" src='./calendar.less' scoped></style>

<template>
  <view class="calendar-bg" wx:if="{{ visible }}">
    <view class="calendar-wrapper">
      <view class="calendar-content">
        <!-- 星期 -->
        <view class="week flex-center">
          <block wx:for="{{ weeksCh }}" wx:key="item">
            <view class="flex-center">{{ item }}</view>
          </block>
        </view>
        <!-- 双层循环 -->
        <scroll-view scroll-y style="height: 600px;" scroll-into-view="{{ scroll_view }}">
          <view wx:for="{{ allDays }}" wx:for-index="idx" wx:key="indx" wx:for-item="month" id="{{ 'month' + idx }}">
            <!-- 年份和月份 -->
            <view class="pick-view">
              <view class="flex-center">
                {{months[idx].format_date}}
              </view>
            </view>
            <!-- 日期循环 -->
            <view class="day clearfix">
              <block wx:for="{{ month }}" wx:key="{{ item.key }}" wx:for-index="d">
                <view data-monthIndex="{{ idx }}" data-dayIndex="{{ d }}" @tap="changeResultTime" data-item="{{ item }}"
                      data-monthview="{{ month[15].month }}" class="flex-center ">
                  <view data-month="{{ item.month }}"
                        class="day-item {{ item.month !== month[15].month ? 'not-view-month':'' }} {{ item.active && item.month === month[15].month ? 'day-item-active':'' }} {{ item.month == (current.months + 1) && item.year == current.years && item.day < current.date ? 'view-month-future':'' }} {{ item.year < current.years ? 'view-month-future':'' }} {{ item.year == current.years && item.month < (current.months + 1) ? 'view-month-future':'' }}">
                    {{ item.day }}
                  </view>
                  <view style="background-color: {{ color }}"
                        wx-if="{{ item.active && item.month === month[15].month }}" class="round"></view>
                </view>
              </block>
            </view>
          </view>
        </scroll-view>
      </view>
      <view class="confirm">
        <view @tap="confirm" class="confirm_btn {{ selectArr.length? 'confirm_btn_active' : '' }}">确定</view>
      </view>
    </view>
  </view>

</template>

<script>
  import wepy from '@wepy/core'
  import moment from 'moment'

  wepy.component({
    props: {
      value: {
        type: String,
        default: moment().format('YYYY-MM-DD')
      },
      color: {
        type: String,
        default: '#32B650'
      }
    },

    data: {
      month_length: 12, // 展示多少个月份的数据,5表示从当前月开始,往后五个月
      weeksCh: ['一', '二', '三', '四', '五', '六', '日'],
      months: [], // 所有要显示的月份
      scroll_view: 'month4',
      current: {},
      viewTime: {
        year: '',
        month: '',
        day: '',
        formatDay: '',
        weekCh: ''
      },
      // 当前视图的day数组
      viewDays: [], // 一个月的数据
      allDays: [], // 从当前日期开始,往前推五个月的数据
      visible: true,
      selectArr: [] // 已经选中的日期
    },
    methods: {

      show() {
        this.visible = true
      },
      // pick选择器改变了
      changePicker(e) {
        // 改变当前视图日期数组
        this.viewDays = this._getData(moment(e.detail.value, 'YYYY-MM'))
      },
      // 点击上个月
      toPreMonth() {
        console.log(this.selectArr)
        this.viewDays = this._getData(moment(this.viewTime.formatDay).subtract(1, 'days'))
      },
      // 点击下个月
      toNextMonth() {
        this.viewDays = this._getData(moment(this.viewTime.formatDay).endOf('month').add(1, 'days'))
      },

      // 点击某个日期
      changeResultTime(e) {
        // console.log(e)
        const {item, dayindex, monthindex, monthview} = e.currentTarget.dataset
        // 点击了同一天
        if (moment().isSame(item.formatDay, 'day')) {
          this._setTime(moment(item.formatDay), monthindex, dayindex)
        } else {
          // console.log('saf sdafsa54fs5a64f65a')
          // console.log(moment(item.formatDay), monthindex, dayindex)
          this._setTime(moment(item.formatDay), monthindex, dayindex)

        }
      },

      // 用户点击确定
      confirm() {
        if (!this.selectArr.length) {
          return false
        }
        this.selectArr.sort(function (a, b) {
          if (a.year < b.year) {
            return -1
          } else if (a.year === b.year) {
            if (a.month < b.month) {
              return -1
            } else if (a.month === b.month) {
              if (a.day < b.day) {
                return -1
              } else {
                return 1
              }
            } else {
              return 1
            }
          } else {
            return 1
          }
        })
        // console.log(this.selectArr)
        this.$parent.close(this.selectArr)
      },

      /**
       * _getData
       * 返回当前视图日期数组
       * @param time
       * @return [{day:31,month:3,year:2018},{day:1,month:4,year:2018},...]
       */
      _getData(time = moment()) {
        this._setViewTime(time)
        // 令时间变为当月1号的
        const firstDay = time.startOf('month')
        // 计算当月1号是星期几
        const firstDayOfWeek = firstDay.format('E')
        // 计算上个月多余时间
        const last = this._calDate(firstDay.subtract(firstDayOfWeek - 1, 'days'), firstDayOfWeek - 1)
        // 计算本月时间
        let current = this._calDate(firstDay, firstDay.daysInMonth())
        // 令时间变为本月末
        const endDay = time.subtract(1, 'days')
        // 当月末是星期几
        const endDayOfWeek = endDay.format('E')
        // 计算下个月多余时间
        const next = this._calDate(endDay.add(1, 'days'), 7 - endDayOfWeek)
        return [...last, ...current, ...next]
      },
      /**
       * _setTime
       * 设定导出的时间
       * 日期第一次点击选中,第二次点击取消
       * 选中第一个日期,选中第二个日期,中间的日期自动选中
       * @param time moment对象
       */
      _setTime(time = moment(), month_index, day_index) {
        let obj = this._dealMoment(time)
        let day = Object.assign({}, obj, {month_index: month_index, day_index: day_index})
        this.allDays = this.allDays.map(month => {
          month = month.map(day => {
            day.active = false
            return day
          })
          return month
        })
        console.log(this.selectArr)
        // console.log(this.allDays)
        // 当前日历中,已经选中了一个日期
        if (this.selectArr.length === 1) {
          if (this.selectArr[0].formatDay === obj.formatDay) {
            this.allDays[month_index][day_index].active = true
            this.selectArr = []
            this.selectArr.push(day)
          } else {
            console.log(22212)
            // console.log(this.allDays)
            this.allDays = this.allDays.map(month => {
              month = month.map(day => {
                day.active = false
                return day
              })
              return month
            })
            this.selectArr = []
            this.allDays[month_index][day_index].active = true
            this.selectArr.push(day)
            console.log(this.selectArr)
            // // 开始连选
            // let one_by_one = false
            // this.allDays = this.allDays.map(month => {
            //   month = month.map(day => {
            //     // 遍历到第一个被选中的日期
            //     if (day.active) {
            //       one_by_one = !one_by_one
            //     }
            //
            //     if (one_by_one) {
            //       day.active = true
            //     }
            //     return day
            //   })
            //   return month
            // })
          }
        } else if (this.selectArr.length >= 2) {
          this.allDays = this.allDays.map(month => {
            month = month.map(day => {
              day.active = false
              return day
            })
            return month
          })
          this.allDays[month_index][day_index].active = true
          this.selectArr = [day]
          // console.log(this.selectArr)

          // 当前还没有选中日期
        } else {
          console.log(11212)
          console.log(this.allDays)
          this.allDays[month_index][day_index].active = true
          this.selectArr.push(day)
        }
      },
      /**
       * _setTime
       * 设定当前日历的时间
       * @param time moment对象
       */
      _setViewTime(time = moment()) {
        let obj = this._dealMoment(time.startOf('month'))
        this.viewTime = obj
      },
      /**
       * _calDate
       * 计算日期函数
       * @param time moment对象
       * @param length 返回数组的长度
       * @return 返回日期数组
       */
      _calDate(time, length) {
        let arr = []
        for (let i = 0; i < length; i++) {
          arr.push(this._dealMoment(time))
          time.add(1, 'days')
        }
        return arr
      },
      /**
       * _dealMoment
       * 处理moment对象
       * @param time moment对象
       * @return 返回一个Object{year, month, day, formatDay}
       */
      _dealMoment(time) {
        let {years, months, date} = time.toObject()
        return {
          year: years,
          month: months + 1,
          day: date,
          weekCh: '周' + this.weeksCh[time.format('E') - 1],
          formatDay: time.format('YYYY-MM-DD')
        }
      },
      /**
       * _init
       * 初始化
       * @param value '2018-02-02' YYYY-MM-DD
       */
      init(value) {
        // this.viewDays = this._getData(moment(value))
        this.months = []
        this.allDays = []
        this.current = moment().toObject()
        // 初始化日历开始的年月日
        let current_month = moment().format('YYYY-MM')
        let format_date = current_month.split('-')[0] + '年' + parseInt(current_month.split('-')[1]) + '月'
        this.months = [{
          date: current_month,
          format_date: format_date
        }]
        //
        for (var i = 1; i <= this.month_length; i++) {
          let date = moment().add(i, 'months').format('YYYY-MM')
          this.months.push({
            date: date,
            format_date: parseInt(date.split('-')[1]) + '月'
          })
        }
        this.months.map(item => {
          let days = this._getData(moment(item.date))
          this.allDays.push(days)
        })
        this.scroll_view = 'month4'
      }
    },
    created() {
      // 每次载入时,默认被选中的日期时当前这天
      this.init(this.value)
    }
  })
</script>

.flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}
.clearfix:after {
  content: '';
  height: 0;
  line-height: 0;
  display: block;
  visibility: hidden;
  clear: both;
}
.calendar-bg {
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.4);
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 100;
  transition: 0.3s;
}
.calendar-wrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  box-sizing: border-box;
  z-index: 101;
  background-color: white;
  .confirm {
    position: absolute;
    bottom: 30rpx;
    right: 50rpx;
    width: 100%;
    display: flex;
    justify-content: flex-end;
    width: 100%;
    align-items: center;
    font-size: 28rpx;
    // border-radius: 50%;
  }
  .confirm_btn {
    background-color: #efefef;
    color: #32B650;
    padding: 0 20rpx;
    line-height: 60rpx;
    box-shadow: 0 1px 2px rgba(150,150,150,0.3);
    border-radius: 30rpx;
    z-index: 999
  }
  .confirm_btn_active {
    background-color: #32B650;
    color: #FFF;
  }
}
.calendar-header {
  width: 100%;
  box-sizing: border-box;
  height: 130rpx;
  padding: 30rpx 30rpx;
  background-color: black;
  color: white;
  display: flex;
  justify-content: flex-start;
  align-content: center;
  flex-direction: column;
  font-size: 24rpx;
  > view:first-child {
    color: lightgray;
  }
}
.pick-view {
  width: 100%;
  height: 100rpx;
  position: relative;
  font-size: 40rpx;
  font-weight: 600;
  .pick-img {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    > view {
      width: 60rpx;
      height: 100%;
      position: relative;
      > image {
        width: 30rpx;
        height: 30rpx;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
}
picker {
  width: 130rpx;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.calendar-content {
  width: 100%;
  // padding: 10rpx 50rpx 30rpx 50rpx;
  // background-color: lightyellow;
  background-color: white;
  box-sizing: border-box;
  font-size: 24rpx;
  .week {
    margin: 40rpx 0;
    > view {
      flex: 1;
      color: gray;
    }
  }
  .day {
    width: 100%;
    margin-bottom: 40rpx;
    font-size: 36rpx;
    > view {
      position: relative;
      float: left;
      width: calc(100% / 7);
      height: 60rpx;
      padding: 20rpx;
      box-sizing: border-box;

      margin-bottom: 20rpx;
    }
    .day-item {
      z-index: 200;
    }
    .day-item-active {
      color: #FFF;
    }
    .not-view-month {
      color: #FFF;
    }
    .view-month-future {
      color: #efefef;
    }
    .round {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: black;
      width: 72rpx;
      height: 72rpx;
      border-radius: 50%;
      z-index: 102;
    }
    .restime {
      color: white;
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值