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


Posted in Javascript onSeptember 21, 2020

生活中有各种可以打卡的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": "打卡日历"
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
按给定几率进行随机抽取的js代码
Dec 28 Javascript
基于jquery的不规则矩形的排列实现代码
Apr 16 Javascript
jQuery中has()方法用法实例
Jan 06 Javascript
基于JavaScript实现定时跳转到指定页面
Jan 01 Javascript
关于JS中的方法是否加括号的问题
Jul 27 Javascript
Angular和百度地图的结合实例代码
Oct 19 Javascript
Web 开发中Ajax的Session 超时处理方法
Jan 19 Javascript
Angular.JS利用ng-disabled属性和ng-model实现禁用button效果
Apr 05 Javascript
ES6字符串模板,剩余参数,默认参数功能与用法示例
Apr 06 Javascript
浅谈微信页面入口文件被缓存解决方案
Sep 29 Javascript
JavaScript类的继承操作实例总结
Dec 20 Javascript
详解jQuery中的prop()使用方法
Jan 05 jQuery
微信小程序实现时间预约功能
Nov 27 #Javascript
微信小程序使用component自定义toast弹窗效果
Nov 27 #Javascript
微信小程序自定义底部导航带跳转功能
Nov 27 #Javascript
koa2使用ejs和nunjucks作为模板引擎的使用
Nov 27 #Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
Nov 27 #jQuery
js replace替换字符串同时替换多个方法
Nov 27 #Javascript
Vue中用props给data赋初始值遇到的问题解决
Nov 27 #Javascript
You might like
通过源码解析Laravel的依赖注入
2018/01/22 PHP
window.open()弹出居中的窗口
2007/02/01 Javascript
JavaScript 编程引入命名空间的方法与代码
2007/08/13 Javascript
科讯商业版中用到的ajax空间与分页函数
2007/09/02 Javascript
javascript取消文本选定的实现代码
2010/11/14 Javascript
Safari5中alert的无限循环BUG
2011/04/07 Javascript
js change,propertychange,input事件小议
2011/12/20 Javascript
js验证模型自我实现的具体方法
2013/06/21 Javascript
js实现单行文本向上滚动效果实例代码
2013/11/28 Javascript
jQuery选择器源码解读(六):Sizzle选择器匹配逻辑分析
2015/03/31 Javascript
js实现简单秒表走动的时钟特效
2020/03/25 Javascript
javascript实现一个简单的弹出窗
2016/02/22 Javascript
jQuery获取选中单选按钮radio的值
2016/12/27 Javascript
jQuery实现滚动效果
2017/11/17 jQuery
vue构建动态表单的方法示例
2018/09/22 Javascript
vue中keep-alive组件的入门使用教程
2019/06/06 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
Python3.x和Python2.x的区别介绍
2013/02/12 Python
深入解答关于Python的11道基本面试题
2017/04/01 Python
python中对_init_的理解及实例解析
2019/10/11 Python
利用Tensorflow的队列多线程读取数据方式
2020/02/05 Python
安装多个版本的TensorFlow的方法步骤
2020/04/21 Python
Numpy 多维数据数组的实现
2020/06/18 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
2020/11/17 Python
详解css3中 text-fill-color属性
2019/07/08 HTML / CSS
Html5 Canvas动画基础碰撞检测的实现
2018/12/06 HTML / CSS
美国艺术和工艺品商店:Hobby Lobby
2020/12/09 全球购物
环境科学专业研究生求职信
2013/10/02 职场文书
公司薪酬管理制度
2014/01/31 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
工厂门卫的岗位职责
2014/07/27 职场文书
2014年工人工作总结
2014/11/25 职场文书
杭白菊导游词
2015/02/10 职场文书
公司团队口号霸气押韵
2015/12/24 职场文书
《天净沙·秋思》教学反思三篇
2019/11/02 职场文书
Redis性能监控的实现
2021/07/09 Redis