微信小程序仿打卡小程序

1.前言

  • 从两周前开始接触小程序,到现在也学到了一点.准备通过本次的文章,来从0到1写一个简单的单机版小程序,来帮助一些准备入门小程序开发的同学,同时也算是对自己这两周学习小程序的一个巩固与检测
  • 后续我也会在我的博客更新一些小程序的学习与'讲解',与小伙伴们共同学习
  • 最后会布置一个简短的小作业,同学们可以自己去补充

2.看前必读

  • 本文章并非针对于0基础,像工具的一些用法,目录结构不会讲解太多,有不会的可以找我咨询,博客上有我的联系方式,本文章主要是通过从0到1写一个简单的单机小程序,主要是一些js语法,css样式等的解释与学习
  • 当然会贴上一些官方的链接供大家去参考
  • 微信小程序官网  注册账号,选择小程序,根据指引来就可以:
  • 微信小程序开发工具 自助安装根据指引打开
  • 在开始之前,向大家推荐一个非常不错的技术公众号和小程序,每天会推荐一些优质文章来供大家学习,微信搜索公众号和小程序   码个蛋

3.简单准备工作

  1. 先看一下小程序的基础结构,不会画图,将就看吧,三个页面,具体一些比较细的效果没有画出来
  2. 一些弹窗按钮后续再补充吧,本文章会根据这个模型来写一个简单的单机小程序
  3. 简单的目录讲解 js是写一些函数和一些逻辑,wxml是页面设计,wxss是样式编辑,json是当前page的一些配置

4. 正式开始(在实际写的时候与上面效果图不太相同)

        4.1首页布局

先看下我的具体实现效果图

先分析一下首页的功能

  • 需要获取到当前用户的微信头像和微信昵称
  • 获取今日未打卡状态
  • 点击打卡要记录今天的打卡状态
  • 打卡按钮根据打卡状态变更样式

1.wxml布局代码

<!--pages/index/index.wxml-->
<view>
  <!-- 最顶部样式 -->
  <view class="top-view">
    <!-- 头像与昵称 -->
    <view class="user-info">
      <!-- 头像 -->
      <view class="avatar">
        <open-data type="userAvatarUrl"></open-data>
      </view>
      <!-- 昵称 -->
      <view class="nickname">
        <open-data type="userNickName"></open-data>
      </view>
    </view>
    <!-- 打卡天数统计 -->
    <view class="day-count">
      <text>
        已累计打卡
      </text>
      <text class="day-count-num">
        {{listSize}}
      </text>
      <text>
        天
      </text>
    </view>
  </view>
  <!-- 底部view -->
  <view class="bottom-view">
    <view bindtap="punchTheClock" class="btn_click">
      <text>{{todayClick?'已打卡':'今日打卡'}}</text>
    </view>
    <view bindtap="jumpDetail" class="btn_detail">打卡详情</view>
  </view>
</view>

2.样式代码

/* pages/index/index.wxss */
.top-view {
  position: relative;
  width: 100%;
  height: 280rpx;
  background-color: #FFFF00;
}

.user-info {
  left: 50rpx;
  position: relative;
  top: 80rpx;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.avatar {
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  overflow: hidden;
}

.nickname {
  margin-left: 30rpx;
  font-size: 38rpx;
  color: #000000;
}

.day-count {
  position: absolute;
  right: 20rpx;
  bottom: 20rpx;
  display: flex;
}

.day-count-num {
  color: #FF0000;
}

.bottom-view {
  display: flex;
  flex-direction: column;
  align-items: center;
  scrollbar-shadow-color: #FF0000;
}

.btn_click {
  border-radius: 50%;
  overflow: hidden;
  background-color: #FF0000;
  display: flex;
  width: 300rpx;
  margin-top: 280rpx;
  box-shadow: 0px 2px 5px 5px #FF0000;
  align-items: center;
  justify-content: center;
  height: 300rpx;
}

.btn_click text {
  color: #FFFFFF;
  font-size: 60rpx;
}

.btn_detail {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 45rpx;
  color: #000000;
  position: absolute;
  bottom: 100rpx;
}

3.js逻辑代码层

// pages/index/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    todayClick: false,
    clickStatusKey: '',
    clickListKey: 'clickListKey',
    clickList: [],
    listSize: '0'
  },

  /**
   * 点击打卡
   */
  punchTheClock() {
    if (this.data.todayClick) {
      //如果今天已打卡
    } else {
      wx.setStorageSync(this.data.clickStatusKey, true)
      let itemData = {
        date: this.getNowDate(),
        // date: '2021-7-10',
        status: true,
        desc: ''
      }
      this.getTodayClickStatus()
      let clickList = this.getClickList()
      this.setData({
        clickList: clickList
      })
      this.data.clickList.unshift(itemData)
      wx.setStorageSync(this.data.clickListKey, this.data.clickList)
      
      this.getClickDayCount()
    }
  },
  getClickList() {
    return wx.getStorageSync(this.data.clickListKey) || []
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.setData({
      clickStatusKey: 'clickStatus_' + this.getNowDate()
    })
    this.getTodayClickStatus()
  },
  /**
   * 获取今天的打卡状态
   */
  getTodayClickStatus() {
    let status = wx.getStorageSync(this.data.clickStatusKey)
    if (status != null) {
      this.setData({
        todayClick: status
      })
    }
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    this.addUnPunchDay()
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    this.getClickDayCount()
  },
  /**
   * 添加未打卡日期数据
   */
  addUnPunchDay() {
    //当前添加的日期
    let currentAddDate = ''
    let list = wx.getStorageSync(this.data.clickListKey) || []
    if (list.length == 0 || list[0].date == this.getNowDate()) {
      //从未打过卡或者最后一个打卡的是昨天
      return
    }
    currentAddDate = list[0].date
    //一直添加直到添加到昨天
    while (true) {
      if (currentAddDate >= this.getNowDate()) {
        return
      }
      currentAddDate = this.getAppointDayDate(currentAddDate, 1)
      //所有status为false,没打卡状态
      let itemData = {
        date: currentAddDate,
        status: false,
        desc: ''
      }
      //倒序把距离上一次打开的每一天都添加上
      list.unshift(itemData)
      if (currentAddDate == this.getAppointDayDate(this.getNowDate(), -1)) {
        console.log("添加到昨天之后跳出循环")
        break
      }
    }
    wx.setStorageSync(this.data.clickListKey, list)
  },

  /**
   * 获取指定日期的前几天或者后几天
   * day: -1前一天  1后一天
   */
  getAppointDayDate(date, day) {
    var dd = new Date(date);
    dd.setDate(dd.getDate() + day);
    var y = dd.getFullYear();
    var m = dd.getMonth() + 1 < 10 ? "0" + (dd.getMonth() + 1) : dd.getMonth() + 1;
    var d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate();
    return y + "-" + m + "-" + d;
  },

  /**
   * 获取真正的打卡天数
   */
  getClickDayCount() {
    let clickList = this.getClickList()
    let clickSize = 0
    for (let index = 0; index < clickList.length; index++) {
      if (clickList[index].status) {
        clickSize++
      }
    }
    this.setData({
      listSize: clickSize
    })
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },
  // 获取当前日期
  getNowDate: function () {
    let dateTime
    let YYYY = new Date().getFullYear()
    let MM = new Date().getMonth() + 1
    let DD = new Date().getDate()
    dateTime = YYYY + '-' + MM + '-' + DD
    return dateTime
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },

  jumpDetail() {
    wx.navigateTo({
      url: '../listdetail/listdetail',
    })
  }
})

        4.2列表布局布局

先附上效果图

分析一下主要功能

  • 首先要把距离上次日期的中间未打卡数据添加进来
  • 根据打卡状态改变背景颜色和字体颜色
  • 如果未打卡或者补卡的要显示注意按钮
  • 如果是补卡的用户点击注意弹出未打卡的备注原因
  • 点击未打卡跳到补卡页面
<!--pages/listdetail/listdetail.wxml-->
<view>

  <!-- 空数据页面 -->
  <view wx:if="{{isEmpty}}" class="empty-view">
    <text>你还没有打过卡</text>
  </view>
  <block wx:else>
    <!-- 有数据页面 -->
    <view class="list-item-view" style="background-color: {{item.status?'#FFFF00':'#FF0000'}}" wx:for="{{punchList}}">
      <view class="punch-info">
        <view class="item-date" style="color: {{item.status?'#000000':'#FFFF00'}}">{{item.date}}</view>
        <view class="item-status" style="color: {{item.status?'#FF0000':'#FFFFFF'}}">{{item.status?'已打卡':'未打卡'}}</view>
      </view>
      <view wx:if='{{!item.status||item.desc}}' class="view-desc">注意</view>
    </view>
  </block>

</view>

wxss样式页面

/* pages/listdetail/listdetail.wxss */
.list-item-view {
  margin-top: 5rpx;
  padding: 30rpx;
  display: flex;
  flex-direction: row;
  background-color: #FFFF00;
  align-items: center;
}

.punch-info {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.item-date{
  font-weight: 600;
  color: #000000;
}
.item-status{
  font-size: 30rpx;
  color: #FF0000;
}

.view-desc {
  position: absolute;
  right: 30rpx;
}
.item-line{
  height: 2rpx;
  background-color: #2b2a2a;
}

逻辑js页面

// pages/listdetail/listdetail.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    isEmpty: false,
    punchList: [],
    clickListKey: 'clickListKey'
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let list = wx.getStorageSync(this.data.clickListKey) || []
    console.log(list)
    this.setData({
      punchList: list,
      isEmpty: list.length <= 0
    })
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

4.3补卡页面

  • 给同学们留下的一个小作业,后续会在文章中补充
  • 点击未打卡列表跳转该页面,正常打卡不可跳转

思路提示

  1. 将列表的index传入该页面,点击提交补卡,将该item的desc字段修改,然后关闭页面,备注不可少于10个字
  2. 返回上一页直接展示该数据,变更为已打卡状态

源码地址:微信打卡小程序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值