小程序自定义日历

6 篇文章 0 订阅
1 篇文章 0 订阅

重点在于将数个月的日期拆分重组,然后再统一以月为输出。详细操作代码注释有说明。

<view class="flex box box-tb box-align-center">
<!--整体日期循环部分  -->
<block wx:for="{{allMan}}"  wx:for-item="item" >
  <view class="calendar pink-color box box-tb">
        <view class="top-handle fs28 box box-lr box-align-center box-pack-center">
            <view  class="date-area box box-lr box-align-center box-pack-center years-month">{{item.year || "--"}} 年 {{item.Month || "--"}} 月</view>
        </view>
        <!--展示星期几的头部  -->
        <view class="weeks box box-lr box-pack-center box-align-center day-week">
            <view class="flex week fs28" wx:for="{{weeks_ch}}" wx:key="{{index}}" data-idx="{{index}}">{{item}}</view>
        </view>
        <view class="days box box-lr box-wrap">
            <view class="grid white-color box box-align-center box-pack-center" wx:for="{{item.empyt}}" wx:key="{{index}}" data-idx="{{index}}">
            </view>
            <!--循环日期  -->
            <block  wx:for="{{item.day}}" wx:for-item="item" wx:key="{{index}}">
              <view class="grid white-color box box-align-center box-pack-center" data-idx="{{index}}" data-dayz="{{item.dayZ}}" bindtap="{{item.canChoosed ? 'tapDayItemX' : ''}}">
                <view class="day  {{item.dependence ? 'border-instinct pink-bg' : ''}} {{item.startDay ? 'border-radius dependence-bg' : ''}} {{item.endDay ? 'border-right-radius dependence-bg' : ''}} {{item.canChoosed ? '' : 'grays'}} box box-align-center box-pack-center">
                  {{item.today}}
                </view>
              </view>
            </block>
        </view>
    </view>
</block>
</view>
let choose_year = null,//选择的年
  choose_month = null;//选择的月
let clickNum=new Array();//点击日期的次数,做显示判断处理
let date = new Date();
let cur_year = date.getFullYear();
let cur_month = date.getMonth() + 1;
let weeks_ch = ['日', '一', '二', '三', '四', '五', '六']; //日历的显示
let allMan = new Array();//循环总日历容器
let haveClickNum=false;//是否可点击选择日期
let havInitDate = false;//是否已经重置数据
let conf = {//拿去给Page
	onLoad() {
    if (allMan.length != 0) {//重新进入界面发现已经有数据,直接渲染
      havInitDate = false;
      clickNum = new Array();
      haveClickNum = true;
      this.setData({
        allMan,
        weeks_ch
      })
    }else{
      allMan = new Array();//非常重要的主输出,计算好的每月数据都合拼在里面
      clickNum = new Array();
      let that = this;
      let empytGrids = this.calculateEmptyGrids(cur_year, cur_month);//计算空格
      let days = this.calculateDays(cur_year, cur_month);//计算日期总数
      let DogDays = { year: cur_year, Month: cur_month, empyt: empytGrids, day: days };//组装年、月、星期一前的空格、日
      allMan.push(DogDays);
      let newMonth = cur_month + 1;
      let newYear = cur_year;
      if (newMonth > 12) {//新年重置1月份
        newYear = cur_year + 1;
        newMonth = 1;
      }
      let empytGridsTwos = this.calculateEmptyGridsTwo(newYear, newMonth);//计算新月份的空格
      let dayTwos = this.calculateDaysTwo(newYear, newMonth);//计算日期总数
      let catDays = { year: newYear, Month: newMonth, empyt: empytGridsTwos, day: dayTwos };
      allMan.push(catDays);
      let sakura = days.concat(dayTwos);//将存放日期的内容统一合并为数组,单独处理是否可选等展示状态,属于中间件数组
      let isTrue = new Array();//存放可选
      for (var i = 0; i < sakura.length; i++) {//循环处理
        if (sakura[i].canChoosed == true) {
          isTrue.push(sakura[i]);
        } else {
          continue
        }
      }
      let addMoreMonth = function () {//添加更多的月份
        let isTrue = new Array();//是否可选的日期数组,为N个月等可选日期总日输做判断
        for (var i = 0; i < sakura.length; i++) {
          if (sakura[i].canChoosed == true) {
            isTrue.push(sakura[i]);
          } else {
            continue
          }
        }
        let newMonthThree = newMonth + 1;
        let newYearThree = newYear;
        if (newMonthThree > 12) {
          newYearThree = newYear + 1;
          newMonthThree = 1;
        }
        let empytGridsThree = that.calculateEmptyGridsTwo(newYearThree, newMonthThree);//计算空格
        let dayThree = that.calculateDaysTwo(newYearThree, newMonthThree, 91 - isTrue.length);//计算日期总数,61减,今天不算
        let duckDays = { year: newYearThree, Month: newMonthThree, empyt: empytGridsThree, day: dayThree };
        sakura = sakura.concat(dayThree);
        allMan.push(duckDays);
        if (parseInt(91 - isTrue.length) > parseInt(dayThree.length)) {//第n个月是否足够显示需要的可选日期长度
          for (var i = 0; i < dayThree.length; i++) {
            if (dayThree[i].canChoosed == true) {
              isTrue.push(dayThree[i]);
            } else {
              continue
            }
          }
          let newMonthFour = newMonthThree + 1;
          let newYearFour = newYearThree;
          if (newMonthFour > 12) {
            newYearFour = newYearThree + 1;
            newMonthFour = 1;
          }
          let empytGridsFour = that.calculateEmptyGridsTwo(newYearFour, newMonthFour);//计算空格
          let dayFour = that.calculateDaysTwo(newYearFour, newMonthFour, 91 - isTrue.length);//计算日期总数,61减,今天不算
          let wolfDays = { year: newYearFour, Month: newMonthFour, empyt: empytGridsFour, day: dayFour };
          sakura = sakura.concat(dayFour);
          allMan.push(wolfDays);
        } else {//不足够继续增加第n+1个月
          let newMonthFour = newMonthThree + 1;
          let newYearFour = newYearThree;
          if (newMonthFour > 12) {
            newYearFour = newYearThree + 1;
            newMonthFour = 1;
          }
          let empytGridsFour = that.calculateEmptyGridsTwo(newYearFour, newMonthFour);//计算空格
          let dayFour = that.calculateDaysTwo(newYearFour, newMonthFour, -1);//计算日期总数,61减,今天不算
          let wolfDays = { year: newYearFour, Month: newMonthFour, empyt: empytGridsFour, day: dayFour };
          sakura = sakura.concat(dayFour);
          allMan.push(wolfDays);
        }
      }
      if (isTrue.length < 90) {
        addMoreMonth();
      }
      this.setData({
        allMan,
        weeks_ch
      })
    }
	},
  onShow: function () {
    // console.log(allMan);
    // allMan = new Array();//循环总日历容器
    // 页面显示
  },
	getThisMonthDays(year, month) {
		return new Date(year, month, 0).getDate();
	},
	getFirstDayOfWeek(year, month) {
		return new Date(Date.UTC(year, month - 1, 1)).getDay();
	},
	calculateEmptyGrids(year, month) {
    let firstDayOfWeek = this.getFirstDayOfWeek(year, month);
		let empytGrids = [];
		if (firstDayOfWeek > 0) {
			for (let i = 0; i < firstDayOfWeek; i++) {
				empytGrids.push(i);
			}
		}
    return (empytGrids);
	},
  calculateEmptyGridsTwo(year, month) {
    let firstDayOfWeek = this.getFirstDayOfWeek(year, month);
    let empytGridsTwo = [];
    if (firstDayOfWeek > 0) {
      for (let i = 0; i < firstDayOfWeek; i++) {
        empytGridsTwo.push(i);
      }
    }
    return (empytGridsTwo);
  },
	calculateDays(year, month) {
		let days = [];
    let date = new Date();
    let thisMonthDays = this.getThisMonthDays(year, month);//这个月的总日数
    let d = date.getDate();
    let weeHours=date.getHours();
    let zaa = year+month+date.getDate();
		for (let i = 1; i <= thisMonthDays; i++) {
      if (year+month+i == zaa){
        days.push({
          day: i,
          dayZ: cur_year+"-"+cur_month+"-"+i,
          choosed: false,
          canChoosed: true,
          today: i
        });
      } else if (year + month + i < zaa){
        if (weeHours <= 2 && year + month + i == zaa-1){//加个判断:是否凌晨3点之前,是的话就拿日期集-1来对前一日可选
          days.push({
            day: i,
            dayZ: cur_year + "-" + cur_month + "-" + i,
            choosed: false,
            canChoosed: true,
            today: i
          });
          }else{
          days.push({
            day: i,
            dayZ: cur_year + "-" + cur_month + "-" + i,
            choosed: false,
            canChoosed: false,
            today: i
          });
          }
      } else{
        days.push({
          day: i,
          dayZ: cur_year + "-" + cur_month + "-" + i,
          choosed: false,
          canChoosed: true,
          today: i
        });
      }
		}
		this.setData({
			// days
		});
    return (days);
	},
  calculateDaysTwo(year, month,takeNum) {
    let days_two = [];
    let date = new Date();
    let thisMonthDays = this.getThisMonthDays(year, month);
    let d = date.getDate();
    let zaa = year+"-"+month+"-"+date.getDate();
    if (takeNum) {
      console.log(takeNum);
    }
    for (let i = 1; i <= thisMonthDays; i++) {
      takeNum--;
      if (takeNum<0){
        days_two.push({
          day: i,
          dayZ: year + "-" + month + "-" + i,
          choosed: false,
          canChoosed: false,
          today: i
        });
      }else{
        days_two.push({
          day: i,
          dayZ: year + "-" + month + "-" + i,
          choosed: false,
          canChoosed: true,
          today: i
        });
      }
    }
    this.setData({
      // days_two
    });
    return (days_two);
  },

	handleCalendar(e) {
    let handle = e.currentTarget.dataset.handle;
    let cur_year = this.data.cur_year;
    let cur_month = this.data.cur_month;
		if (handle === 'prev') {
			let newMonth = cur_month - 1;
			let newYear = cur_year;
			if (newMonth < 1) {
				newYear = cur_year - 1;
				newMonth = 12;
			}

			this.calculateDays(newYear, newMonth);
			this.calculateEmptyGrids(newYear, newMonth);

			this.setData({
				cur_year: newYear,
				cur_month: newMonth
			});

		} else {
			let newMonth = cur_month + 1;
			let newYear = cur_year;
			if (newMonth > 12) {
				newYear = cur_year + 1;
				newMonth = 1;
			}

			this.calculateDays(newYear, newMonth);
			this.calculateEmptyGrids(newYear, newMonth);

			this.setData({
				cur_year: newYear,
				cur_month: newMonth
			});
		}
	},
  tapDayItemX(e) {//点击日期处理
    if (clickNum.length >= 2)//点了两次,不可再点
      return;
    if (haveClickNum){//是否已经选择过日期
      this.initChosedDate();//重置选择过的样式
      let dayZ = e.currentTarget.dataset.dayz;
      for (let i = 0; i < allMan.length; i++) {
        let li = allMan[i].day;
        for (let k = 0; k < li.length; k++) {
          if (li[k].dayZ == dayZ) {
            if (clickNum.length == 0) {
              li[k].startDay = true;
            }
            if (clickNum.length == 1) {
              li[k].endDay = true;
            }
          }else{//已选择的区间日期重置
            li[k].dependence = false;
          }
        }
      }
      this.setData({//渲染
        allMan
      })
      clickNum.push(integerDate(dayZ));//格式化日期,准备拿去比较函数处理
    }else{//第一次进入生命周期,从没选择过的处理
      let dayZ = e.currentTarget.dataset.dayz;
      for (let i = 0; i < allMan.length; i++) {
        let li = allMan[i].day;
        for (let k = 0; k < li.length; k++) {
          if (li[k].dayZ == dayZ) {
            if (clickNum.length == 0) {
              li[k].startDay = true;
            }
            if (clickNum.length == 1) {
              li[k].endDay = true;
            }
          }
        }
      }
      this.setData({//渲染
        allMan
      })
      clickNum.push(integerDate(dayZ));//格式化日期,准备拿去比较函数处理
    }
    if (clickNum.length < 2)//点击了第二次,进行teturn下面的渲染操作
      return
    clickNum.sort(compare);//拿去比较函数处理
    let dayDiff = GetDateDiff(clickNum[0], clickNum[1]);
    let startDay = clickNum[0];//第一位为开始日期
    let startMonth = new Date(clickNum[0]).getMonth() + 1;//开始的月,跨月显示用
    let formatStartDay = new Date(clickNum[0]).getFullYear() + '-' + startMonth + '-' + new Date(clickNum[0]).getDate();//格式化开始日期,后面用于给总输出allman做判断
    let endMonth = new Date(clickNum[1]).getMonth() + 1;//结束的月,跨月显示用
    let formatEndDay = new Date(clickNum[1]).getFullYear() + '-' + endMonth + '-' + new Date(clickNum[1]).getDate();//格式化结束日期,后面用于给总输出allman做判断
    let endDay = clickNum[1];//第二位为结束日期
    for (let i = 0; i < allMan.length; i++) {//循环总输出allMan数组得出每月的日期数组,将开始、结束日期带进去做改变显示状态处理
      let li = allMan[i].day;
      for (let k = 0; k < li.length; k++) {//每个月的日期数组,拆分更细
        let foxDay = integerDate(li[k].dayZ);
        if (startDay < foxDay && foxDay < endDay){
          li[k].dependence = true;//已选择的区间日期
        } else if (li[k].dayZ == formatStartDay){//开始日期状态处理
          li[k].startDay = true;
          li[k].endDay = false;
        } else if (li[k].dayZ == formatEndDay) {//结束日期状态处理
          li[k].startDay = false;
          li[k].endDay = true;
        }
      }
    }
    this.setData({//再渲染
      allMan
    })
     wx.navigateBack({
       delta: 1,
     })
  },
  initChosedDate(){
    if (havInitDate)
    return
    for (let i = 0; i < allMan.length; i++) {
      let li = allMan[i].day;
      for (let k = 0; k < li.length; k++) {
          li[k].startDay = false;
          li[k].endDay = false;
      }
    }
    havInitDate=true;
  },
};

Page(conf);
let compare = function (x, y) {//比较函数,那个日期谁先谁后,star/end
  if (x < y) {
    return -1;
  } else if (x > y) {
    return 1;
  } else {
    return 0;
  }
}

function GetDateDiff(startDate, endDate) {
  let dates = Math.abs((startDate - endDate)) / (1000 * 60 * 60 * 24);
  return dates;
}

function integerDate(choseDate){
  let integerDay = new Date(Date.parse(choseDate.replace(/-/g, "/"))).getTime();
  return integerDay;
}

/* pages/calendar/calendar.wxss */
.top-handle {
    height: 80rpx;
}
.prev {
    text-align: right;
    height: 80rpx;
}
.next {
    height: 80rpx;
}
.prev-handle {
    width: 80rpx;
    height: 100%;
}
.next-handle {
    width: 80rpx;
    height: 100%;
}
.date-area {
    width: 50%;
    height: 80rpx;
    text-align: center;
}
.weeks {
    height: 50rpx;
    line-height: 50rpx;
    opacity: 0.5
}
.week {
    text-align: center;
}
.days {
    height: 500rpx;
}
.grid {
    width: 107.1428571429rpx;
}
.day {
    width: 100%;
    height: 100%;
    color: #000;
    font-size: 26rpx;
    font-weight: 200;
}
.border-instinct{
    position: relative;
    left: 0;
    top: 0;
    color: #fff;
}
.border-radius {
    border-radius:5px 0 0 5px;
    position: relative;
    left: 0;
    top: 0;
    color: #fff;
}
.border-right-radius {
    border-radius:0 5px 5px 0;
    position: relative;
    left: 0;
    top: 0;
    color: #fff;
}
.pink-bg {
    background-color: #ffe5b4;
        color: #f6ac1d;
}
.dependence-bg {
    background-color: #d9246b;
}
.purple-bg {
    background-color: #b8b8f1;
}

.right-triangle::after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border: 15rpx solid transparent;
    border-left-color: #ff629a;
    position: absolute;
    right: -22rpx;
    top: 18rpx;
}
.left-triangle::before {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border: 15rpx solid transparent;
    border-right-color: #ff629a;
    position: absolute;
    left: -22rpx;
    top: 18rpx;
}
.tips {
    text-align: center;
    margin-top: 20rpx;
    margin-bottom: 20rpx;
}
.types {
    background-color: #ffedf4;
    height: 50rpx;
}
.type-dot {
    width: 25rpx;
    height: 25rpx;
    border-radius: 50%;
    margin-right: 10rpx;
}
.type-dot-ymq {
    color:#FF7CA0;
    background-color: #FF7CA0;
}
.type-dot-ycq {
    color: rgb(255, 200, 202);
    background-color: rgb(255, 200, 202);
}
.type-dot-aqq {
    color: rgb(118, 191, 92);
    background-color: rgb(118, 191, 92);
}
.type-dot-yyq {
    color: #FF7CA0;
    background-color: #FF7CA0;
}
.type-dot-plr {
    color: rgb(211, 189, 215);
    background-color: rgb(211, 189, 215);
}
.types-desc {
    padding: 0 20rpx;
}
.type-name {
    margin-top: 50rpx;
    margin-bottom: 30rpx;
}
.type-desc {
    padding: 0 35rpx;
    line-height: 38rpx;
}
.explain {
    border-top: 1px solid #eee;
    width: 90%;
    margin: 20rpx 5% 20rpx 5%;
    padding: 20rpx 0;
}
.explain-title {
    font-weight: bold;
    margin-bottom: 15rpx;
}
.explain-item {
    padding: 8rpx 20rpx;
    color: #fff;
}
.left-border-radius {
    border-top-left-radius: 20rpx;
    border-bottom-left-radius: 20rpx;
}
.right-border-radius {
    border-top-right-radius: 20rpx;
    border-bottom-right-radius: 20rpx;
}
.picker-btns {
	height: 120rpx;
	line-height: 120rpx;
	border-bottom: 1rpx solid #FF7CA0;
}
.picker-confirm {
	margin-right: 50rpx;
}
.picker-cancel {
	margin-left: 50rpx;
}
.picker-view {
	color:#FF7CA0;
	text-align: center;
}

.box {
    display: flex;
}

.box-lr {
    flex-direction: row;
}

.box-rl {
    flex-direction: row-reverse;
}

.box-tb {
    flex-direction: column;
}

.box-bt {
    flex-direction: column-reverse;
}

.box-pack-center {
    justify-content: center;
}
.day-week{
  color:#ccc;

}

.box-pack-start {
    justify-content: flex-start;
}

.box-pack-end {
    justify-content: flex-end;
}

.box-pack-between {
    justify-content: space-between;
}

.box-pack-around {
    justify-content: space-around;
}

.box-align-center {
    align-items: center;
}
.years-month{
  color: #000;
}
.box-align-start {
    align-items: flex-start;
}

.box-align-end {
    align-items: flex-end;
}

.self-align-center {
    align-self: center;
    margin: 0 auto;
}

.self-align-start {
    align-self: flex-start;
}

.self-align-end {
    align-self: flex-end;
}

.self-align-stretch {
    align-self: stretch;
}

.box-wrap {
    flex-wrap: wrap;
}

.box-nowrap {
    flex-wrap: nowrap;
}

.flex {
    flex-grow: 1;
    background: #fff;
}

.shrink {
    flex-shrink: 1;
}
.bg {
  background-image: linear-gradient(to bottom, #faefe7, #ffcbd7);
  overflow: hidden;
}
.brown-color {
  color: #784344;
}
.pink-color {
  color: #ff629a;
}
.white-color {
  color: #fff;
}
.fs24 {
  font-size: 24rpx;
}
.fs28 {
  font-size: 28rpx;
}
.fs32 {
  font-size: 32rpx;
}
.fs36 {
  font-size: 36rpx;
}

/*灰色显示  */
.grays{
  color: #ccc;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值