首页 > 课堂 > 小程序 > 正文

微信小程序实现打卡日历功能

2020-03-21 16:06:10
字体:
来源:转载
供稿:网友

生活中有各种可以打卡的app,例如背单词打卡什么的,本人觉得很有意思,于是本人在大二时做了一款诚信状打卡的微信小程序,这里讲述一下编写的过程。

先说一下开发环境:用的是微信web开发工具开发的,后台采用了Bmob后台,比较方便。

先展示一下成果:

微信小程序,打卡,日历

微信小程序,打卡,日历

话不多说,直接上代码,里面也有挺多的注释,以防自己忘记,当然各位如果直接复制过去肯定不能有当前的效果,注意后台数据的交互,不过做一个界面还是没有问题的。

Calendar.wxml 页面文件 

页面上显示出来的东西,布局上主要是一个年月栏、上一个月和下一个月的按钮;然后是星期栏,就是日一二三四五六,然后就是每个月的日期,注意每个月的前面可能有空的地方。这里面用wx:if标签来区分当前日期有无打卡的情况。

<!--pages/Calendar/Calendar.wxml--><!-- 打卡日历页面 --><view class='all'> <view class="bar">  <!-- 上一个月 -->  <view class="previous" bindtap="handleCalendar" data-handle="prev">   <image src='../../images/pre.png'></image>  </view>  <!-- 显示年月 -->  <view class="date">{{cur_year || "--"}} 年 {{cur_month || "--"}} 月</view>  <!-- 下一个月 -->  <view class="next" bindtap="handleCalendar" data-handle="next">   <image src='../../images/next.png'></image>  </view> </view> <!-- 显示星期 --> <view class="week">  <view wx:for="{{weeks_ch}}" wx:key="{{index}}" data-idx="{{index}}">{{item}}</view> </view> <view class='days'>  <!-- 列 -->  <view class="columns" wx:for="{{days.length/7}}" wx:for-index="i" wx:key="i">   <view wx:for="{{days}}" wx:for-index="j" wx:key="j">    <!-- 行 -->    <view class="rows" wx:if="{{j/7 == i}}">     <view class="rows" wx:for="{{7}}" wx:for-index="k" wx:key="k">      <!-- 每个月份的空的单元格 -->      <view class='cell' wx:if="{{days[j+k].date == null}}">       <text decode="{{true}}">  </text>      </view>      <!-- 每个月份的有数字的单元格 -->      <view class='cell' wx:else>       <!-- 当前日期已签到 -->       <view wx:if="{{days[j+k].isSign == true}}" style='background-color:#83C75D' class='cell'>        <text>{{days[j+k].date}}</text>       </view>       <!-- 当前日期未签到 -->       <view wx:else>        <text>{{days[j+k].date}}</text>       </view>      </view>     </view>    </view>   </view>  </view> </view> <!-- 坚持打卡天数 --> <view class='count'>  <text>截至目前,你已坚持打卡</text>  <view class='daynumber'>  <text class='number'>{{count}}</text>  <text class='day'>天</text>  </view>    <text>请再接再厉,继续努力</text> </view></view>

Calendar.wxss 样式文件 

这个就是让页面显示得更好看一点了,里面有些属性更改之后可能会导致整个页面的格式变得很乱,说明自己的功夫还是不到家。

 

/* pages/Calendar/Calendar.wxss *//* 打卡日历 */.all{ margin-top: 20rpx;}.all .bar{ display: flex; flex-direction: row; justify-content: space-between; margin: 30rpx 20rpx; padding: 10rpx;}.all .bar image{ width: 50rpx; height: 50rpx;}.all .week{ display: flex; flex-direction: row; justify-content: space-between; padding: 20rpx; padding-left: 40rpx; padding-right: 40rpx; margin: 20rpx; border-radius: 10px; background-color: #acd;}.all .days{ margin: 20rpx; padding: 10rpx; border-radius: 10px; background-color: #acd;}.all .columns{ display: flex; flex-direction: column; justify-content: space-between; }.all .columns .rows{ display: flex; flex-direction: row; justify-content: space-between;}.all .columns .rows .cell{ width: 84rpx; height: 88rpx; margin: 3rpx; text-align: center; border-radius: 50%; display: flex; flex-direction: column; justify-content: center;}.count .daynumber{ display: flex; flex-direction: row; justify-content: center;}.count .daynumber .day{ margin-top: 50rpx;}.count{ margin: 20rpx; padding: 30rpx; display: flex; text-align: center; border-radius: 10px; flex-direction: column; justify-content: center; background-color: #acd; align-items: center;}.count .number{ color: red; font-size: 60rpx; background-color: #fff; width: 100rpx; height: 100rpx; border-radius: 50%; display: flex; flex-direction: column; justify-content: center; margin: 20rpx;}.count text{ margin: 10rpx;}

Calendar.js JavaScript文件 

js文件里面涉及到Bmob的操作,这里就不多说Bmob的操作了,感兴趣的同学可以去参考它的官方文档。 
然后里面主要是对上一个月、下一个月的点击函数进行处理,以及对某年某月的每个日期进行初始化(尤其是每个月前的可能有的几个空格进行了处理),然后就是判断某个日期在后台数据中是否有打卡。

 

// pages/Calendar/Calendar.js//打卡日历页面var util = require('../../utils/util.js');var Bmob = require('../../utils/bmob.js');Page({ /**  * 页面的初始数据  */ data: {  objectId:'',  days:[],  signUp:[],  cur_year:0,  cur_month:0,  count:0 }, /**  * 生命周期函数--监听页面加载  */ onLoad: function (options) {  this.setData({objectId : options.objectId});   //获取当前年月   const date = new Date();  const cur_year = date.getFullYear();  const cur_month = date.getMonth() + 1;  const weeks_ch = ['日', '一', '二', '三', '四', '五', '六'];  this.calculateEmptyGrids(cur_year, cur_month);  this.calculateDays(cur_year, cur_month);  //获取当前用户当前任务的签到状态  this.onGetSignUp();  this.setData({   cur_year,   cur_month,   weeks_ch  }) }, /**  * 生命周期函数--监听页面初次渲染完成  */ onReady: function () { }, /**  * 生命周期函数--监听页面显示  */ onShow: function () { }, /**  * 生命周期函数--监听页面隐藏  */ onHide: function () { }, /**  * 生命周期函数--监听页面卸载  */ onUnload: function () { }, /**  * 页面相关事件处理函数--监听用户下拉动作  */ onPullDownRefresh: function () { }, /**  * 页面上拉触底事件的处理函数  */ onReachBottom: function () { }, /**  * 用户点击右上角分享  */ onShareAppMessage: function () { }, // 获取当月共多少天 getThisMonthDays:function(year, month){   return new Date(year, month, 0).getDate() }, // 获取当月第一天星期几 getFirstDayOfWeek:function(year, month) {  return new Date(Date.UTC(year, month - 1, 1)).getDay(); }, // 计算当月1号前空了几个格子,把它填充在days数组的前面 calculateEmptyGrids:function(year, month) {  var that = this;  //计算每个月时要清零  that.setData({days:[]});  const firstDayOfWeek = this.getFirstDayOfWeek(year, month);    if (firstDayOfWeek > 0) {   for (let i = 0; i < firstDayOfWeek; i++) {    var obj = {     date:null,     isSign:false    }    that.data.days.push(obj);   }   this.setData({    days:that.data.days   });  //清空  } else {   this.setData({    days: []   });  } }, // 绘制当月天数占的格子,并把它放到days数组中 calculateDays:function(year, month) {  var that = this;  const thisMonthDays = this.getThisMonthDays(year, month);  for (let i = 1; i <= thisMonthDays; i++) {   var obj = {    date: i,    isSign: false   }   that.data.days.push(obj);  }  this.setData({   days:that.data.days  }); }, //匹配判断当月与当月哪些日子签到打卡 onJudgeSign:function(){  var that = this;  var signs = that.data.signUp;  var daysArr = that.data.days;  for (var i=0; i < signs.length;i++){   var current = new Date(signs[i].date.replace(/-/g, "/"));   var year = current.getFullYear();   var month = current.getMonth()+1;   var day = current.getDate();   day = parseInt(day);   for (var j = 0; j < daysArr.length;j++){    //年月日相同并且已打卡    if (year == that.data.cur_year && month == that.data.cur_month && daysArr[j].date == day && signs[i].isSign == "今日已打卡"){     daysArr[j].isSign = true;    }   }  }  that.setData({days:daysArr}); }, // 切换控制年月,上一个月,下一个月 handleCalendar:function(e) {  const handle = e.currentTarget.dataset.handle;  const cur_year = this.data.cur_year;  const 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.calculateEmptyGrids(newYear, newMonth);   this.calculateDays(newYear, newMonth);   this.onGetSignUp();      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.calculateEmptyGrids(newYear, newMonth);   this.calculateDays(newYear, newMonth);   this.onGetSignUp();      this.setData({    cur_year: newYear,    cur_month: newMonth   })  } }, //获取当前用户该任务的签到数组 onGetSignUp:function(){  var that = this;  var Task_User = Bmob.Object.extend("task_user");  var q = new Bmob.Query(Task_User);  q.get(that.data.objectId, {   success: function (result) {    that.setData({     signUp : result.get("signUp"),     count : result.get("score")    });    //获取后就判断签到情况    that.onJudgeSign();   },   error: function (object, error) {   }  });   }})

Calendar.json json文件 

这里仅仅是改变了导航栏上的标题文字

{ "navigationBarTitleText": "打卡日历"}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表