效果图如下所示
.wxml
<view class='gs_banner'>
<view class='gs_continue'>
<view>每日坚持签到</view>
<view>总共签到:<text>{{continuity}}</text>天</view>
</view>
</view>
<view class='gs_sign'>
<view class='gs_sign_box'>
<view class='gs_pillar'>
<view class='gs_post'>
<view></view>
</view>
<view class='gs_post'>
<view></view>
</view>
<view class='gs_post'>
<view></view>
</view>
<view class='gs_post'>
<view></view>
</view>
<view class='gs_post'>
<view></view>
</view>
</view>
<view class='gs_sign_day'>
<image bindtap='onshow' src='/images/rl.png'></image>
<view>持续签到 <text>{{continuity}}</text>天</view>
</view>
<view class='gs_sign_content'>
<view class='gs_week'>
<block wx:for="{{week}}" wx:key="index">
<view class='gs_wook'>
<view style='width: {{ sysW }}px; height: {{ sysW }}px; line-height: {{ sysW }}px;'>{{item.wook}}</view>
</view>
</block>
</view>
<view class='gs_week'>
<block wx:for="{{day}}" wx:key="index">
<view class="gs_wook {{ item.wook == getDate ? 'dateOn' : ''}}" style='width: {{ sysW }}px; height: {{ sysW }}px; line-height: {{ sysW }}px;' bindtap="{{item.src?'wenlin':''}}" data-index="{{index}}">
<view id="{{item.src?'fuconl':''}}" style="{{item.src && !item.check?'visibility: hidden;':''}}">{{item.wook}}</view>
<view class='gs_clocksucceed' wx:if="{{item.src && !item.check}}">
<image src='{{item.src}}'></image>
</view>
</view>
</block>
</view>
<view class='gs_circle'>
<view class='gs_incircle' style="{{ornot?'background-color:#e7ebed;cursor:auto;':''}}">
<view class='gs_excircle' bindtap="{{ornot?'':'dakainc'}}">
<view class='gs_innercircle' style="{{ornot?'background-color:#ddd;':''}}">{{ornot?'已打卡':'打卡'}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 弹出部分 -->
<view class='gs_calendar' style='display:{{display}}'>
<view class='gs_bg' bindtap='onhide'></view>
<view class='gs_gs_calendar_box'>
<view class="canlendarBgView">
<view class="canlendarView">
<view class="canlendarTopView">
<view class="leftBgView" bindtap="handleCalendar" data-handle="prev">
<view class="leftView">
上个月
</view>
</view>
<view class="centerView">{{cur_year || "--"}} 年 {{cur_month || "--"}} 月</view>
<view class="rightBgView" bindtap="handleCalendar" data-handle="next">
<view class="leftView">
下个月
</view>
</view>
</view>
<view class="weekBgView">
<view style='width: {{ sysW }}px; height: {{ sysW }}px; line-height: {{ sysW }}px;' class="weekView" wx:for="{{weeks_ch}}" wx:key="index" data-idx="{{index}}">{{item}}</view>
</view>
<view class="dateBgView">
<view wx:if="{{hasEmptyGrid}}" class="dateEmptyView" wx:for="{{empytGrids}}" wx:key="index" data-idx="{{index}}">
</view>
<view style='width: {{ sysW }}px; height: {{ sysW }}px; line-height: {{ sysW }}px;{{ index == 0 ? "margin-left:" + sysW * marLet + "px;" : "" }}' class="dateView {{item.wook == getDate && judge == 1?'dateOn':''}}" wx:for="{{days}}" wx:key="index" bindtap="{{item.src?'wenldisp':''}}" data-index="{{index}}">
<view style="{{item.src && !item.check?'visibility: hidden;':''}}" id="{{item.src?'fuconl':''}}" class="datesView">{{item.wook}}</view>
<view class='clocksucceed' wx:if="{{item.src && !item.check}}">
<image src='{{item.src}}'></image>
</view>
</view>
</view>
</view>
</view>
<view class='del'>
<text bindtap="onhide" class="cuIcon-close">x</text>
</view>
</view>
</view>
<!-- 签到弹窗 -->
<view class="load" style="{{sign?'':'top:calc((100vh - 750rpx)/2);opacity: 0;z-index:-1;'}}">
<image class="load-imagae" src="/images/register.png"></image>
<view class="load-centent">
<view>签到成功</view>
<view>持续签到<span>{{continuity}}</span>天</view>
<view bindtap="popup">好的</view>
</view>
</view>
.js
const util = require('../../utils/util.js')
Page({
data: {
sysW: null,
lastDay: null,
year: null,
hasEmptyGrid: false,
cur_year: '',
cur_month: '',
firstDay: null,
getDate:null,
month:null,
display:"none",
week:[
{
wook: "一"
}, {
wook: "二"
}, {
wook: "三"
}, {
wook: "四"
}, {
wook: "五"
}, {
wook: "六"
}, {
wook: "日"
},
],
day:[],
days:[],
ornot:false,//今天是否签到
continuity:2,//签到天数
sign:false,//签到弹窗
},
getProWeekList:function(){
let that=this
let date=new Date()
let cur_year = parseInt(date.getFullYear())
let cur_month = parseInt(date.getMonth() + 1)
let obinl = parseInt(util.getWeekByDate(new Date()));//今天周几
let danqian = new Date(date.getTime()).getDate()
let shang = that.getThisMonthDays(((cur_month - 1) < 1?cur_year-1:cur_year),((cur_month - 1) < 1?12:cur_month - 1))
let ben = that.getThisMonthDays(cur_year,cur_month)
let xyue = 7 - (7 - obinl)
let syue = 7 - obinl
let array = []
let name_a = 0
let name_b = 0
let name_c = 0
for(let i = 0;i<xyue;i++){
name_a = xyue - danqian
name_b = shang - name_a
name_c = name_b + i + 1
if(name_c > shang){
name_c = 1 + (name_a <= i?i - name_a:0)
}
array.push({wook:name_c})
}
for(let i = 0;i<syue;i++){
name_a = danqian + i + 1
if(name_a > ben){
name_a = name_a - ben
}
array.push({wook:name_a,src:''})
}
that.setData({
day:array
})
},
dateSelectAction: function (e) {
let cur_day = e.currentTarget.dataset.idx;
this.setData({
todayIndex: cur_day
})
console.log(`点击的日期:${this.data.cur_year}年${this.data.cur_month}月${cur_day + 1}日`);
},
setNowDate: function () {
const date = new Date();
const cur_year = date.getFullYear();
const cur_month = date.getMonth() + 1;
const todayIndex = date.getDate();
const weeks_ch = ['日', '一', '二', '三', '四', '五', '六'];
this.calculateEmptyGrids(cur_year, cur_month);
this.setData({
cur_year: cur_year,
cur_month: cur_month,
weeks_ch,
todayIndex,
})
},
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) {
const firstDayOfWeek = this.getFirstDayOfWeek(year, month);
let empytGrids = [];
if (firstDayOfWeek > 0) {
for (let i = 0; i < firstDayOfWeek; i++) {
empytGrids.push(i);
}
this.setData({
hasEmptyGrid: true,
empytGrids
});
} else {
this.setData({
hasEmptyGrid: false,
empytGrids: []
});
}
},
calculateDays(year, month) {
var timestamp = Date.parse(new Date());
timestamp = timestamp / 1000;
var n = timestamp * 1000;
var tiem = new Date(n);
var Y = tiem.getFullYear();
var M = (tiem.getMonth() + 1 < 10 ? '0' + (tiem.getMonth() + 1) : tiem.getMonth() + 1);
let getDate = this.data.ornot?this.data.getDate:(this.data.getDate - 1) //多少号
let cur_year = this.data.cur_year//年
let cur_month = this.data.cur_month//月
let thisMonthDays = this.getThisMonthDays(year, month);
let month_s = year.toString() + (month.toString().length == 1?'0' + month.toString():month.toString());
let openitem = (this.data.opentime[0] + '' +((this.data.opentime[1]+'').length == 1?'0'+this.data.opentime[1]:this.data.opentime[1]));
for (let i = 1; i <= thisMonthDays; i++) {
if(month_s > openitem){
this.data.days.push({wook:i,src:''});
}else if(openitem < month_s && month == this.data.shuttime[1]){//小于开始月份
this.data.days.push({wook:i,src:i <= getDate?'/images/newspaper.png':''});
}else if(openitem == month_s && month == this.data.opentime[1]){
if((Y+''+M) == month_s && this.data.opentime[2] <= i && i <= (this.data.ornot?this.data.getDate:this.data.getDate-1)){
this.data.days.push({wook:i,src:'/images/newspaper.png'});
}else if((Y+''+M) != month_s && this.data.opentime[2] <= i){
this.data.days.push({wook:i,src:'/images/newspaper.png'});
}else{
this.data.days.push({wook:i,src:''});
}
}else if(openitem == month_s && month < this.data.shuttime[1]){
this.data.days.push({wook:i,src:this.data.opentime[2] <= i?'/images/newspaper.png':''});
}else if(openitem < month_s && month < this.data.shuttime[1]){
this.data.days.push({wook:i,src:'/images/newspaper.png'});
}else{
this.data.days.push({wook:i,src:''});
}
}
this.setData({
days:this.data.days,
})
},
//上下月
handleCalendar(e) {
const handle = e.currentTarget.dataset.handle;
const cur_year = this.data.cur_year;
const cur_month = this.data.cur_month;
this.setData({
days:[]
})
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);
let firstDay = new Date(newYear, newMonth - 1, 1);
this.data.firstDay = firstDay.getDay();
this.setData({
cur_year: newYear,
cur_month: newMonth,
marLet: this.data.firstDay
})
if (this.data.month == newMonth) {
this.setData({
judge: 1
})
} else {
this.setData({
judge: 0
})
}
} 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);
let firstDay = new Date(newYear, newMonth - 1, 1);
this.data.firstDay = firstDay.getDay();
this.setData({
cur_year: newYear,
cur_month: newMonth,
marLet: this.data.firstDay
})
if (this.data.month == newMonth){
this.setData({
judge:1
})
}else{
this.setData({
judge: 0
})
}
}
},
dataTime: function () {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth();
var months = date.getMonth() + 1;
//获取现今年份
this.data.year = year;
//获取现今月份
this.data.month = months;
//获取今日日期
this.data.getDate = date.getDate();
//最后一天是几号
var d = new Date(year, months, 0);
this.data.lastDay = d.getDate();
//第一天星期几
let firstDay = new Date(year, month, 1);
this.data.firstDay = firstDay.getDay();
this.setData({
marLet:this.data.firstDay
})
},
onshow:function(){
this.setData({
display:"block",
})
},
onhide:function(){
this.setData({
display: "none",
})
},
onLoad: function (options) {
var that = this;
this.setNowDate();
this.getProWeekList()
this.dataTime();
var res = wx.getSystemInfoSync();
this.setData({
sysW: res.windowHeight / 12-5,//更具屏幕宽度变化自动设置宽度
getDate: this.data.getDate,
judge:1,
month: this.data.month,
});
this.sigarr();
},
//获取数组参数
sigarr:function(e){
let that = this
let ornot = that.data.ornot?0:1//当天是否签到
let continuity = that.data.continuity//连续签到天数
let obinl = parseInt(util.getWeekByDate(new Date()));//今天周几
let cur_year = that.data.cur_year;//年份
let cur_month = that.data.cur_month - 1;//月份
if (cur_month < 1) {//月份小于1年份减1
cur_year = cur_year - 1;
cur_month = 12;
}
let num = obinl<continuity?(obinl + 1):continuity
//七日签到数组
for(let i = 0;i < num;i++){
if(i <= (obinl + 1)){
if(ornot == 0){
if(0 <= (obinl - i - 1)){
that.data.day[obinl - i - 1].src = "/images/newspaper.png"
}
}else{
if(0 <= (obinl - i - 2)){
that.data.day[obinl - i - 2].src = "/images/newspaper.png"
}
}
}else{
return false
}
}
//签到数组
that.setData({
day:that.data.day,//七天签到
shuttime:[that.data.cur_year,that.data.cur_month,(that.data.getDate - ornot)],//结束签到时间
})
if(that.data.getDate < continuity){//当前天数不够减去连续签到天数
let qindao = continuity - that.data.getDate//签到天数
let rili = parseInt(that.getThisMonthDays(cur_year, cur_month))//上月天数
if((rili + that.data.getDate) < continuity){//连续签到天数大于上个月加当前日期的和
let num = 1
let guil = ''
let gumlitem = continuity - rili - that.data.getDate + ornot
for(let i = 0;i < num;i++){
num++
cur_month = cur_month - 1
if (cur_month < 1) {
cur_year = cur_year - 1;
cur_month = 12;
}
guil = parseInt(that.getThisMonthDays(cur_year, cur_month))//上月天数
gumlitem = gumlitem - guil
if(gumlitem < 1){
gumlitem = Math.abs(gumlitem) + 1
num = 0
}
}
that.setData({
opentime:[cur_year,cur_month,gumlitem],//开始签到时间
})
}else{
that.setData({
opentime:[cur_year,cur_month,(rili - qindao + 1 - ornot)],//开始签到时间
})
}
}else{
that.setData({
opentime:[that.data.cur_year,that.data.cur_month,(that.data.getDate - continuity + 1 - ornot)],//开始签到时间
})
}
this.calculateDays(that.data.cur_year, that.data.cur_month);//数组获取
},
//打卡签到
dakainc:function(e){
let that = this
let date = new Date();
that.setData({
ornot:true,
continuity:that.data.continuity + 1,
days:[],
cur_year:date.getFullYear(),
cur_month:date.getMonth() + 1,
todayIndex:date.getDate(),
judge:1,
})
that.dataTime()//年月份排版
that.calculateEmptyGrids(that.data.cur_year,that.data.cur_month)//年月份排版
that.sigarr();//获取数组参数
that.popup();//显示签到弹窗
},
//显示签到弹窗
popup:function(e){
this.setData({
sign:!this.data.sign
})
},
//七日数组显示文字
wenlin:function(e){
let index = e.currentTarget.dataset.index
this.data.day[index].check = this.data.day[index].check?false:true
this.setData({
day:this.data.day
})
},
//数组显示文字
wenldisp:function(e){
let index = e.currentTarget.dataset.index
this.data.days[index].check = this.data.days[index].check?false:true
this.setData({
days:this.data.days
})
},
//滑动切换
swiperTab: function (e) {
var that = this;
that.setData({
currentTab: e.detail.current
});
},
//点击切换
clickTab: function (e) {
var that = this;
if (this.data.currentTab === e.target.dataset.current) {
return false;
} else {
that.setData({
currentTab: e.target.dataset.current,
})
}
},
})
.wxss
view,image{box-sizing: border-box;}
page{
background-color: #f4f4f4;
}
.gs_banner image{
width:750rpx;
height:256rpx;
vertical-align: top;
}
.gs_continue{
background-color: #fff;
padding:30rpx 20rpx;
}
.gs_continue view:first-child{
font-size:34rpx;
color:#454545;
padding-bottom:20rpx;
}
.gs_continue view:last-child{
font-size:32rpx;
color:#707070;
}
.gs_continue view text{
color:#dd2522;
}
.gs_sign{
margin-top:30rpx;
}
.gs_sign_box{
background-color:#fff;
width:677rpx;
margin:0 auto;
position:relative;
border-radius:15rpx;
}
.gs_pillar{
overflow:hidden;
position:absolute;
top:-16rpx;
width:100%;
}
.gs_pillar .gs_post{
float:left;
width:20%;
text-align: center;
}
.gs_pillar .gs_post view{
display:inline-block;
width:18rpx;
height:42rpx;
background-color:#53acfc;
border-radius:20rpx;
}
.gs_sign_day{
padding:60rpx 20rpx 0;
}
.gs_sign_day image{
width:45rpx;
height:45rpx;
vertical-align: middle;
position: relative;
bottom: 6rpx;
}
.gs_sign_day view{
display:inline-block;
font-size: 30rpx;
margin-left: 14rpx;
color:#707070;
}
.gs_sign_day view text{
color:#dd2522;
}
.gs_sign_content{
padding:20rpx;
}
.gs_week{
overflow:hidden;
}
.gs_wook{
display:inline-block;
text-align: center;
position: relative;
box-sizing: border-box;
}
.gs_wook view{
display: inline-block;
font-size:30rpx;
color:#707070;
width:60rpx;
height:60rpx;
line-height:60rpx;
}
.gs_clocksucceed{
position:absolute;
top:10rpx;
left:16rpx;
}
.gs_clocksucceed image{
width:50rpx;
height:50rpx;
vertical-align: bottom;
position: relative;
bottom: 2rpx;
}
.gs_sign_content .gs_week:nth-child(2) .gs_wook view{
color:#454545;
}
.gs_circle{
padding:50rpx 0;
}
.gs_incircle{
width:225rpx;
height:225rpx;
background-color: #cce6ff;
border-radius:50%;
padding: 10rpx;
margin:20rpx auto;
cursor: pointer;
}
.gs_excircle{
width:100%;
height: 100%;
background-color:#fff;
border-radius:50%;
position: relative;
}
.gs_innercircle{
width:190rpx;
height:190rpx;
background-color: #8bc4f6;
border-radius:50%;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
color:#fff;
font-size:36rpx;
}
.gs_calendar{
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
display:none;
}
.gs_bg{
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
background-color:rgba(0,0,0,.3);
}
.gs_gs_calendar_box{
position: absolute;
top:180rpx;
left:40rpx;
width:677rpx;
background-color:#fff;
padding:20rpx;
box-sizing: border-box;
}
.canlendarTopView{
overflow:hidden;
padding:40rpx 20rpx;
margin-left:20rpx;
display: flex;
align-items: center;
}
.leftBgView{
float:left;
width:153rpx;
text-align: center;
}
.leftView image{
width:60rpx;
height:60rpx;
}
.centerView{
float:left;
font-size:32rpx;
height:60rpx;
line-height:60rpx;
width:260rpx;
text-align: center;
}
.rightBgView{
float:left;
width:156rpx;
text-align: center;
}
.rightView image{
width:60rpx;
height:60rpx;
}
.weekBgView{
overflow:hidden;
}
.weekView{
float:left;
width:14.28571428571429%;
text-align: center;
font-size:30rpx;
color:#707070;
}
.dateBgView{
overflow:hidden;
margin-bottom:20rpx;
}
.dateView{
display:inline-block;
text-align: center;
position:relative;
}
.datesView{
font-size:30rpx;
color:#2b2b2b;
}
.dateOn{
border-radius: 50%;
background-color: #53acfc;
color: #fff !important;
}
.del{
position:absolute;
top:-20rpx;
right:-20rpx;
width:50rpx;
height:50rpx;
background-color:#909090;
border-radius:50%;
display: flex;
align-items: center;
justify-content: center;
}
.del>text{
color: #fff;
font-size: 36rpx;
}
.leftView>text{
font-size: 40rpx;
}
.clocksucceed{
position:absolute;
top:-3rpx;
left:20rpx;
}
.clocksucceed image{
width:50rpx;
height:50rpx;
vertical-align: middle;
position: relative;
bottom: 4rpx;
}
#fuconl{
color: #FF6666;
}
/* 签到弹窗 */
.load{
width: 80%;
height: 600rpx;
position: fixed;
top:calc((100vh - 800rpx)/2);
left: 10%;
transition: all 0.3s ease-in-out 0s;
-webkit-transition: all 0.3s ease-in-out 0s;
opacity: 1;
z-index: 10;
}
.loadingpic {
width: 100%;
height: 93%;
position: absolute;
animation: load 3s linear 1s infinite;
z-index: 10;
margin-top: 7%;
}
@keyframes load{
0%{
webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100%{
webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.load-imagae{
width:400rpx;
height:400rpx;
margin: 100rpx calc((100% - 400rpx)/2);
position: absolute;
z-index: 11;
}
.load-centent{
width:400rpx;
height:400rpx;
margin: 100rpx calc((100% - 400rpx)/2);
position: relative;
z-index: 12;
text-align: center;
padding: 25% 10% 5% 10%;
}
.load-centent>view:nth-child(1){
font-size: 34rpx;
color: #fff;
}
.load-centent>view:nth-child(2){
color: #fff;
opacity: 0.7;
margin: 20rpx 0;
font-size: 24rpx;
}
.load-centent>view:nth-child(3){
width: 85%;
margin: 30rpx 7.5% 0 7.5%;
height: 70rpx;
line-height: 70rpx;
border-radius: 40rpx;
background-color: #F8D168;
color: #EB4331;
font-size: 30rpx;
}
util.js引入文件:https://blog.csdn.net/qq_43764578/article/details/106059340
签到弹窗-图片素材:https://blog.csdn.net/qq_43764578/article/details/105854829
这个是我在网上拔下来的模板:https://www.cnblogs.com/web-know-how/p/9550137.html
这个签到模板是从网上拔下来,然后自己整理了一下把修改的地方都备注了一下,整个签到流程算是走通了,复制下来就能用。
签到流程是根据后台接口返回一个连续签到时间,还有今天是否签到,连续签到三十天就会重置签到进行修改的。
遇到问题可以看我主页加我Q,很少看博客,对你有帮助别忘记点赞收藏。