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


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 相关文章推荐
JQuery开发的数独游戏代码
Oct 29 Javascript
javascript读写XML实现广告轮换(兼容IE、FF)
Aug 09 Javascript
浅谈javascript属性onresize
Apr 20 Javascript
JavaScript运行过程中的“预编译阶段”和“执行阶段”
Dec 16 Javascript
jquery插件Jplayer使用方法简析
Apr 22 Javascript
bootstrap daterangepicker汉化以及扩展功能
Jun 15 Javascript
[js高手之路]HTML标签解释成DOM节点的实现方法
Aug 31 Javascript
微信小程序使用navigateTo数据传递的实例
Sep 26 Javascript
mockjs,json-server一起搭建前端通用的数据模拟框架教程
Dec 18 Javascript
JS实现的JSON数组去重算法示例
Apr 11 Javascript
JavaScript设计模式之建造者模式实例教程
Jul 02 Javascript
JavaScript枚举选择jquery插件代码实例
Nov 17 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
生成ubuntu自动切换壁纸xml文件的php代码
2010/07/17 PHP
PHP在不同页面间传递Json数据示例代码
2013/06/08 PHP
php使用curl存储cookie的示例
2014/03/31 PHP
php计算两个日期时间差(返回年、月、日)
2014/06/19 PHP
Yii数据模型中rules类验证器用法分析
2016/07/15 PHP
thinkphp实现把数据库中的列的值存到下拉框中的方法
2017/01/20 PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式二图文详解
2019/04/09 PHP
javascript fullscreen全屏实现代码
2009/04/09 Javascript
十分钟打造AutoComplete自动完成效果代码
2009/12/26 Javascript
javascript 多种搜索引擎集成的页面实现代码
2010/01/02 Javascript
日历查询的算法 如何计算某一天是星期几
2012/12/12 Javascript
node.js中的fs.mkdirSync方法使用说明
2014/12/17 Javascript
JavaScript中的立即执行函数表达式介绍
2015/03/15 Javascript
javascript定义类和类的实现实例详解
2015/12/01 Javascript
Bootstrap每天必学之级联下拉菜单
2016/03/27 Javascript
jQuery 全选 全部选 反选 实现代码
2016/08/17 Javascript
深入理解vue-router之keep-alive
2017/08/31 Javascript
layui radio性别单选框赋值方法
2018/08/15 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
2019/08/16 Javascript
CountUp.js实现数字滚动增值效果
2019/10/17 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
2020/02/13 Javascript
Vue中的this.$options.data()和this.$data用法说明
2020/07/26 Javascript
js实现随机点名功能
2020/12/23 Javascript
[01:06]欢迎来到上海,TI9
2018/08/26 DOTA
Python线程的两种编程方式
2015/04/14 Python
Python编程修改MP3文件名称的方法
2017/04/19 Python
centos6.4下python3.6.1安装教程
2017/07/21 Python
使用Python的Dataframe取两列时间值相差一年的所有行方法
2018/07/10 Python
Python sklearn KFold 生成交叉验证数据集的方法
2018/12/11 Python
解决python ogr shp字段写入中文乱码的问题
2018/12/31 Python
仓库组长岗位职责
2014/01/29 职场文书
模特职业生涯规划范文
2014/02/26 职场文书
办公室主任岗位承诺书
2014/05/29 职场文书
最美孝心少年事迹材料
2014/08/15 职场文书
公司奖励通知
2015/04/21 职场文书
女性健康知识讲座通知
2015/04/23 职场文书