微信小程序可滑动月日历组件

微信小程序@TOC

微信小程序可滑动月日历组件

此日历可进行左右滑动,展示签到打卡信息,和大家分享一下。
如果样式变形,请检查是否有共用样式起冲突

展示一下效果图

在这里插入图片描述

在components组件文件夹下新建calendarMonth文件夹
直接上代码吧:
index.wxml

<!--components/calendar/index.wxml-->
<view class='month'>
    <!-- <view class='arrow' bindtap='prevMonth'>《 </view> -->
    <view>
        <picker mode="date" value="{{date}}" start="2015-09" end="2020-09" fields='month' bindchange="bindDateChange">
        <view >
            {{date}}
        </view>
        </picker>
    </view>
    <!-- <view class='arrow' bindtap='nextMonth'> 》</view> -->
</view>
<view class='container'>
<view class='calendar flex column s-center'>
  <view class='week-row flex m-around wid100'>
    <view class='grid' wx:for="{{week}}" wx:key='item'>{{item}}</view>
  </view>
  <swiper class='swpier-box' circular="true" current="{{swiperIndex}}" bindchange='swiperChange'>
    <swiper-item class='flex m-around days-table '>
      <view wx:for="{{calendar.first}}" wx:for-item='x' wx:key='x.date'
        class='grid  fw {{x.month === month?"":"notCurrent"}} {{x.date === today?"today":""}} {{x.date == beSelectDate ? "choice":""}}' data-month='{{x.month}}' data-day='{{x.day}}' data-date='{{x.date}}' bindtap='bindDayTap'>
         <view class='view {{x.year+"-"+x.month+"-"+x.day === date+"-01"?"choice2":""}}'>{{x.date === today?'今天':x.day}}</view>
            <block wx:if="{{workerClockData.length>0}}">
             <view wx:for="{{workerClockData}}" wx:key="{{index}}">
              <text class='da' wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">记</text>
              <text class='da2'wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">+{{item.actualDayWage}}</text>
             </view>
            </block>
      </view>
    </swiper-item>
    <swiper-item class='flex m-around days-table '>
      <view wx:for="{{calendar.second}}" wx:for-item='x' wx:key='x.date'
        class='grid fw {{x.month === month?"":"notCurrent"}} {{x.date === today?"today":""}} {{x.date == beSelectDate ? "choice":""}}' data-month='{{x.month}}' data-day='{{x.day}}' data-date='{{x.date}}' data-test='{{(year + "-" +month + "-" + day)}}'  bindtap='bindDayTap'>
        <view class='view {{x.year+"-"+x.month+"-"+x.day === date+"-01"?"choice2":""}}'>{{x.date === today?'今天':x.day}}</view>
        <block wx:if="{{workerClockData.length>0}}">
         <view wx:for="{{workerClockData}}" wx:key="{{index}}">
           <text class='da' wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">记</text>
           <text class='da2'wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">+{{item.actualDayWage}}</text>
         </view>
        </block>
      </view>
    </swiper-item>
    <swiper-item class='flex m-around days-table'>
      <view wx:for="{{calendar.third}}" wx:for-item='x' wx:key='x.date'
        class='grid fw  {{x.date === today?"today":""}} {{x.date == beSelectDate ? "choice":""}}' data-month='{{x.month}}' data-day='{{x.day}}' data-date='{{x.date}}' bindtap='bindDayTap'>
         <view class='view {{x.year+"-"+x.month+"-"+x.day === date+"-01"?"choice2":""}}{{x.month === month?"":"notCurrent"}}'>{{x.date === today?'今天':x.day}}</view>
         <block wx:if="{{workerClockData.length>0}}">
         <view wx:for="{{workerClockData}}" wx:key="{{index}}">
           <text class='da' wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">记</text>
           <text class='da2'wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">+{{item.actualDayWage}}</text>
         </view>
        </block>
      </view>
    </swiper-item>
    <swiper-item class='flex m-around days-table '>
      <view wx:for="{{calendar.fourth}}" wx:for-item='x' wx:key='x.date'
        class='grid fw {{x.month === month?"":"notCurrent"}} {{x.date === today?"today":""}} {{x.date == beSelectDate ? "choice":""}}' data-month='{{x.month}}' data-day='{{x.day}}' data-date='{{x.date}}' bindtap='bindDayTap'>
         <view class='view {{x.year+"-"+x.month+"-"+x.day === date+"-01"?"choice2":""}}'>{{x.date === today?'今天':x.day}}</view>
          <block wx:if="{{workerClockData.length>0}}">
           <view wx:for="{{workerClockData}}" wx:key="{{index}}">
            <text class='da' wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">记</text>
            <text class='da2'wx:if="{{x.year+'-'+x.month+'-'+x.day==item.clockDate}}">+{{item.actualDayWage}}</text>
          </view>
        </block>
      </view>
    </swiper-item>
  </swiper>
</view>
</view>


index.wxss

/* pages/calendar/calendar.wxss */
.container{
  width: 100%;
  height: auto;
  padding: 6rpx;
  font-size: 28rpx;
}
 .month{
  width: 100%;
  height: 100rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32rpx;
   color:#333333;
   font-weight: 700;
  border-bottom: 1px solid #f5f5f5;
}
.days-table {
  flex-wrap: wrap;
  align-content: flex-start;
}
.wid100{
  width: 100%;
}
.calendar{
  z-index:10000;
  
}

.grid {
  /* width: 107.14rpx; */
  height: 100rpx;
  text-align: center;
  line-height: 100rpx;
  font-size:.7rem;
  color:#333333;
  flex: 1;
}
.today {
  color: red;
}
.grid view {
  height:85rpx;
  line-height: 85rpx;
  width:85rpx;
  flex: 1
}
.choice2 {
  /* border-radius: 50%; */
  background: silver;
  background-position:center;
  color: white;
}
.choice .view{
  flex: 1;
  border-radius: 50%;
  background: #88a1fd;
  background-position:center;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center
}
.fw {
  font-weight: 700;
  font-size: 28rpx;
  position: relative;
}
.grid text.da{
  display: flex;
  width: 32rpx;
  height: 32rpx;
  position: absolute;
  right:12rpx;
  top:1rpx;
  font-weight: 1000;
  background: red;
  border-radius: 50%;
  overflow: hidden;
  text-align: center;
  line-height: 24rpx;
  color: #ffffff;
  font-size: 8px;
align-items: center;
justify-content: center
}
.grid text.da2 {
  width: 100%;
  height: 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 800;
  color: red;
  position: absolute;
  bottom:-25rpx;
  display: flex;
  left: -4rpx;
  align-items: center;
  justify-content: center;
  
}
/* 非本月日期 */
.notCurrent {
  color: silver;
  font-weight: normal
}
.day-hover {
  background: red;
}
.container .corred {
  color: red;
}
.swpier-box {
  height: 600rpx;
  width: 100%;
}
.arrow {
  width: 100rpx;
  color: #88a1fd;
  text-align: center;
}

.flex {
  display: flex;
}
/* 轴向 */
.column {
  flex-direction: column;
}
/* 主轴方向 */
.m-start {
  justify-content: flex-start;
}

.m-end {
  justify-content: flex-end;
}

.m-around {
  justify-content: space-around;
   display: grid;
   grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}

.m-between {
  justify-content: space-between;
}
.m-center {
  justify-content: center;
}
/* 侧轴方向 */
.s-start {
  align-items: flex-start;
}
.s-end {
  align-items: flex-end;
}

.s-around {
  align-items: space-around;
}
.s-between {
  align-items: space-between;
}
.s-center {
  align-items: center;
}

index.js

// components/calendar/index.js
let choose_year = null,
  choose_month = null;
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    workerClockData: {
      type: Array,
      observer: function (newVal, oldVal, changedPath) {
        //  console.log(newVal, oldVal, changedPath,this)
      }

    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    day: '',
    year: '',
    month: '',
    date: '2017-01',
    today: '',
    week: ['日', '一', '二', '三', '四', '五', '六'],
    calendar: {
      first: [],
      second: [],
      third: [],
      fourth: []
    },
    swiperMap: ['first', 'second', 'third', 'fourth'],
    swiperIndex: 1,
    showCaldenlar: false
  },
  ready: function () {
    this.getinit()

  },

  /**
   * 组件的方法列表
   */
  methods: {
    getinit() { //初始化
      const date = new Date()
        , month = this.formatMonth(date.getMonth() + 1)
        , year = date.getFullYear()
        , day = this.formatDay(date.getDate())
        , today = `${year}-${month}-${day}`
      let calendar = this.generateThreeMonths(year, month)
      // console.log(calendar)
      this.setData({
        calendar,
        month,
        year,
        day,
        today,
        beSelectDate: today,
        date: `${year}-${month}`
      })
    },
    showCaldenlar() {
      this.setData({
        showCaldenlar: !this.data.showCaldenlar
      })
    },
    /**
     * 
     * 左右滑动
     * @param {any} e 
     */
    swiperChange(e) {
      const lastIndex = this.data.swiperIndex
        , currentIndex = e.detail.current

      let flag = false
        , { year, month, day, today, date, calendar, swiperMap } = this.data
        , change = swiperMap[(lastIndex + 2) % 4]
        , time = this.countMonth(year, month)
        , key = 'lastMonth'
      console.log(lastIndex, currentIndex)
      if (lastIndex > currentIndex) {
        lastIndex === 3 && currentIndex === 0
          ? flag = true
          : null

      } else {
        lastIndex === 0 && currentIndex === 3
          ? null
          : flag = true
      }
      if (flag) {
        key = 'nextMonth'
      }
      console.log(key)
      year = time[key].year
      month = time[key].month
      date = `${year}-${month}`
      day = ''

      if (today.indexOf(date) !== -1) {
        day = today.slice(-2)
      }

      time = this.countMonth(year, month)
      calendar[change] = null
      calendar[change] = this.generateAllDays(time[key].year, time[key].month)

      this.setData({
        swiperIndex: currentIndex,
        //文档上不推荐这么做,但是滑动并不会改变current的值,所以随之而来的计算会出错
        year,
        month,
        date,
        day,
        calendar
      })
      // console.log(calendar)
    },
    /**
     * 
     * 点击切换月份,生成本月视图以及临近两个月的视图
     * @param {any} year 
     * @param {any} month 
     * @returns {object} calendar
     */
    generateThreeMonths(year, month) {
      let { swiperIndex, swiperMap, calendar } = this.data
        , thisKey = swiperMap[swiperIndex]
        , lastKey = swiperMap[swiperIndex - 1 === -1 ? 3 : swiperIndex - 1]
        , nextKey = swiperMap[swiperIndex + 1 === 4 ? 0 : swiperIndex + 1]
        , time = this.countMonth(year, month)
      delete calendar[lastKey]
      calendar[lastKey] = this.generateAllDays(time.lastMonth.year, time.lastMonth.month)
      delete calendar[thisKey]
      calendar[thisKey] = this.generateAllDays(time.thisMonth.year, time.thisMonth.month)
      delete calendar[nextKey]
      calendar[nextKey] = this.generateAllDays(time.nextMonth.year, time.nextMonth.month)
      return calendar
    },
    bindDayTap(e) {
      let { month, year } = this.data
        , time = this.countMonth(year, month)
        , tapMon = e.currentTarget.dataset.month
        , day = e.currentTarget.dataset.day
      if (tapMon == time.lastMonth.month) {
        this.changeDate(time.lastMonth.year, time.lastMonth.month)
      } else if (tapMon == time.nextMonth.month) {
        this.changeDate(time.nextMonth.year, time.nextMonth.month)
      } else {
        this.setData({
          day
        })
      }
      let beSelectDate = e.currentTarget.dataset.date;
      this.setData({
        beSelectDate,
        showCaldenlar: false
      })
      // console.log(beSelectDate)
    },
    bindDateChange(e) {
      if (e.detail.value === this.data.date) {
        return
      }

      const month = e.detail.value.slice(-2)
        , year = e.detail.value.slice(0, 4)

      this.changeDate(year, month)
    },
    prevMonth(e) {
      let { year, month } = this.data
        , time = this.countMonth(year, month)
      this.changeDate(time.lastMonth.year, time.lastMonth.month)
    },
    nextMonth(e) {
      let { year, month } = this.data
        , time = this.countMonth(year, month)
      this.changeDate(time.nextMonth.year, time.nextMonth.month)
    },
    /**
     * 
     * 直接改变日期
     * @param {any} year 
     * @param {any} month 
     */
    changeDate(year, month) {
      let { day, today } = this.data
        , calendar = this.generateThreeMonths(year, month)
        , date = `${year}-${month}`
      date.indexOf(today) === -1
        ? day = '01'
        : day = today.slice(-2)

      this.setData({
        calendar,
        day,
        date,
        month,
        year,
      })
    },
    /**
     * 
     * 月份处理
     * @param {any} year 
     * @param {any} month 
     * @returns 
     */
    countMonth(year, month) {
      let lastMonth = {
        month: this.formatMonth(parseInt(month) - 1)
      }
        , thisMonth = {
          year,
          month,
          num: this.getNumOfDays(year, month)
        }
        , nextMonth = {
          month: this.formatMonth(parseInt(month) + 1)
        }

      lastMonth.year = parseInt(month) === 1 && parseInt(lastMonth.month) === 12
        ? `${parseInt(year) - 1}`
        : year + ''
      lastMonth.num = this.getNumOfDays(lastMonth.year, lastMonth.month)
      nextMonth.year = parseInt(month) === 12 && parseInt(nextMonth.month) === 1
        ? `${parseInt(year) + 1}`
        : year + ''
      nextMonth.num = this.getNumOfDays(nextMonth.year, nextMonth.month)
      return {
        lastMonth,
        thisMonth,
        nextMonth
      }
    },
    currentMonthDays(year, month) {
      const numOfDays = this.getNumOfDays(year, month)
      return this.generateDays(year, month, numOfDays)
    },
    /**
     * 生成上个月应显示的天
     * @param {any} year 
     * @param {any} month 
     * @returns 
     */
    lastMonthDays(year, month) {
      const lastMonth = this.formatMonth(parseInt(month) - 1)
        , lastMonthYear = parseInt(month) === 1 && parseInt(lastMonth) === 12
          ? `${parseInt(year) - 1}`
          : year
        , lastNum = this.getNumOfDays(lastMonthYear, lastMonth) //上月天数
      let startWeek = this.getWeekOfDate(year, month - 1, 1) //本月1号是周几
        , days = []
      if (startWeek == 7) {
        return days
      }

      const startDay = lastNum - startWeek

      return this.generateDays(lastMonthYear, lastMonth, lastNum, { startNum: startDay, notCurrent: true })
    },
    /**
     * 生成下个月应显示天
     * @param {any} year 
     * @param {any} month
     * @returns 
     */
    nextMonthDays(year, month) {
      const nextMonth = this.formatMonth(parseInt(month) + 1)
        , nextMonthYear = parseInt(month) === 12 && parseInt(nextMonth) === 1
          ? `${parseInt(year) + 1}`
          : year
        , nextNum = this.getNumOfDays(nextMonthYear, nextMonth)  //下月天数
      let endWeek = this.getWeekOfDate(year, month)						 //本月最后一天是周几
        , days = []
        , daysNum = 0
      if (endWeek == 6) {
        return days
      } else if (endWeek == 7) {
        daysNum = 6
      } else {
        daysNum = 6 - endWeek
      }
      return this.generateDays(nextMonthYear, nextMonth, daysNum, { startNum: 1, notCurrent: true })
    },
    /**
     * 
     * 生成一个月的日历
     * @param {any} year 
     * @param {any} month 
     * @returns Array
     */
    generateAllDays(year, month) {
      let lastMonth = this.lastMonthDays(year, month)
        , thisMonth = this.currentMonthDays(year, month)
        , nextMonth = this.nextMonthDays(year, month)
        , days = [].concat(lastMonth, thisMonth, nextMonth)
      // console.log("jin")
      // console.log(year, month, days)
      return days
    },
    /**
     * 
     * 生成日详情
     * @param {any} year 
     * @param {any} month 
     * @param {any} daysNum 
     * @param {boolean} [option={
     * 		startNum:1,
     * 		grey: false
     * 	}] 
     * @returns Array 日期对象数组
     */
    generateDays(year, month, daysNum, option = {
      startNum: 1,
      notCurrent: false
    }) {
      const weekMap = ['一', '二', '三', '四', '五', '六', '日']
      let days = []
      for (let i = option.startNum; i <= daysNum; i++) {
        let week = weekMap[new Date(year, month - 1, i).getUTCDay()]
        let day = this.formatDay(i)
        days.push({
          date: `${year}-${month}-${day}`,
          event: false,
          day,
          week,
          month,
          year
        })
      }
      return days
    },
    /**
     * 
     * 获取指定月第n天是周几		|
     * 9月第1天: 2017, 08, 1 |
     * 9月第31天:2017, 09, 0 
     * @param {any} year 
     * @param {any} month 
     * @param {number} [day=0] 0为最后一天,1为第一天
     * @returns number 周 1-7, 
     */
    getWeekOfDate(year, month, day = 0) {
      let dateOfMonth = new Date(year, month, 0).getUTCDay() + 1;
      dateOfMonth == 7 ? dateOfMonth = 0 : '';
      return dateOfMonth;
    },
    /**
     * 
     * 获取本月天数
     * @param {number} year 
     * @param {number} month 
     * @param {number} [day=0] 0为本月0最后一天的
     * @returns number 1-31
     */
    getNumOfDays(year, month, day = 0) {
      return new Date(year, month, day).getDate()
    },
    /**
     * 
     * 月份处理
     * @param {number} month 
     * @returns format month MM 1-12
     */
    formatMonth(month) {
      let monthStr = ''
      if (month > 12 || month < 1) {
        monthStr = Math.abs(month - 12) + ''
      } else {
        monthStr = month + ''
      }
      monthStr = `${monthStr.length > 1 ? '' : '0'}${monthStr}`
      return monthStr
    },
    formatDay(day) {
      return `${(day + '').length > 1 ? '' : '0'}${day}`
    }

  }
})

调用组件

//json文件调用
"usingComponents": {
     "calendarMonth": "../../components/calendarMonth/index"
}
页面调用组件
//workerClockData 传过去的数据 显示签到金额 和 记
  <calendarMonth workerClockData="{{workerClockData}}"></calendarMonth>

要显示打卡数据要传入参数,格式为如下,格式为数组
在这里插入图片描述

本组件仅为本人使用,如有问题希望大家及时反馈

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值