微信小程序签到功能实现
程序员文章站
2022-05-23 10:11:16
...
最近接到一个任务,是给一个线上的小程序添加一个签到的功能,具体功能包括:
1:按7天一轮显示时间
2:只计算连续签到天数,断签后自动归零
3:签到之后可以获得积分,连续签到前六天每天积分为1,六天之后每天积分为3
接到任务后,曾经尝试自己写界面,奈何道行太浅,都被领导否决了,无奈之下,便在网上找一些大神写的界面,最终找到一个还不错的,可惜没有后端,后来在大神同事的帮助下写了一个还算可以的后端功能,总算做出了草稿,具体代码如下,各位将就看一下。
前端(前端界面原创链接:https://blog.csdn.net/weixin_42211816/article/details/81985084)
wxml
<!--pages/signIn/signIn.wxml-->
<view class='signIn'>
<view class='sign-com'>
<view class='thead'>
<view class='tt'>您已连续签到</view>
<view class='mm'>
<label class='n'>
{{signNum}}
</label>
天
</view>
<view class='pp'>连续签到7日后每日得3分</view>
</view>
<view class='modle'>
<view class='mol'>
<view class='mol-line'></view>
<view class='mol-ites'>
<view class="ite {{signNum>=min?'hover':''}}" data-n='{{min}}'>
<label class='n'>+{{min<7?1:3}}</label> <!-- 若签到天数小于7天,则每天签到得1积分,若大于或等于7天,则每天签到得3积分 -->
</view>
<view class="ite {{signNum>=min+1?'hover':''}}" data-n='{{min+1}}'>
<label class='n'>+{{min+1<7?1:3}}</label>
</view>
<view class="ite {{signNum>=min+2?'hover':''}}" data-n='{{min+2}}'>
<label class='n'>+{{min+2<7?1:3}}</label>
</view>
<view class="ite {{signNum>=min+3?'hover':''}}" data-n='{{min+3}}'>
<label class='n'>+{{min+3<7?1:3}}</label>
</view>
<view class="ite {{signNum>=min+4?'hover':''}}" data-n='{{min+4}}'>
<label class='n'>+{{min+4<7?1:3}}</label>
</view>
<view class="ite {{signNum>=min+5?'hover':''}}" data-n='{{min+5}}'>
<label class='n'>+{{min+5<7?1:3}}</label>
</view>
<view class="ite {{signNum>=min+6?'hover':''}}" data-n='{{max}}'>
<label class='n'>+{{min+6<7?1:3}}</label>
</view>
</view>
</view>
<view class='moday'>
<label class='dd'>{{min}}天</label>
<label class='dd'>{{min+1}}天</label>
<label class='dd'>{{min+2}}天</label>
<label class='dd'>{{min+3}}天</label>
<label class='dd'>{{min+4}}天</label>
<label class='dd'>{{min+5}}天</label>
<label class='dd'>{{min+6}}天</label>
</view>
</view>
<view class='the-btn'>
<button type='button' class='btn' bindtap='bindSignIn' data-num="{{signNum}}" disabled='{{signState}}'
data-min="{{min}}" data-max="{{max}}" data-be="{{be}}">
签到
</button>
</view>
</view>
</view>
<view class='explax'>
<view class=''>日期开始:{{min}} </view>
<view class=''>日期结束:{{max}} </view>
<view class=''>签到数:{{signNum}}天</view>
<view class=''>切换周期的倍数:{{be}}</view>
</view>
wxss
/* pages/signIn/signIn.wxss */
.signIn{ width: 100%; height: auto;}
.sign-com{ width: 100%; height: auto; padding: 0 30rpx; box-sizing: border-box; overflow: hidden; }
.sign-com .thead{ width: 100%; text-align: center; padding: 50rpx 0 35rpx;}
.sign-com .thead .tt{ font-size: 24rpx;}
.sign-com .thead .mm{ margin-top: 10rpx; font-size: 24rpx;}
.sign-com .thead .mm .n{ font-size: 66rpx; margin-right: 25rpx;}
.sign-com .thead .pp{ color: #999; font-size: 24rpx; margin-top: 10rpx;}
.sign-com .modle{ width: 100%; height: 100rpx; margin-top: 10rpx; }
.sign-com .modle .mol{ width: 100%; height: 52rpx; position: relative; }
.sign-com .mol-line{ width: 100%; height: 4rpx; background-color: #e6e6e6; position: absolute; left: 0; top: 50%; transform: translateY(-50%);}
.sign-com .mol-ites{ width: 100%; height: 100%;position: absolute;}
.mol-ites .ite{ width: 52rpx; height: 52rpx; border-radius: 50%; border: 1px solid #f5f5f5;
background-color: #fff; box-sizing: border-box; position: absolute; left: 0; top: 0; z-index: 2;}
.mol-ites .ite .n{ width: 44rpx; height: 44rpx; line-height: 44rpx; text-align: center; border-radius: 50%; background-color: #f5f5f5;position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); font-size: 22rpx;}
.mol-ites .ite::after{ content: ""; width: 80rpx; height: 4rpx; background-color: transparent;
position: absolute; left: 52rpx; top: 50%; margin-top: -2rpx; z-index: 2;}
.mol-ites .ite:last-of-type::after{ width: 0;}
.mol-ites .ite:nth-of-type(2){ left: 107rpx;}
.mol-ites .ite:nth-of-type(3){ left: 214rpx;}
.mol-ites .ite:nth-of-type(4){ left: 321rpx;}
.mol-ites .ite:nth-of-type(5){ left: 428rpx;}
.mol-ites .ite:nth-of-type(6){ left: 535rpx;}
.mol-ites .ite:nth-of-type(7){ left: 642rpx;}
.mol-ites .ite.hover{ border-color: #ff614a;}
.mol-ites .ite.hover .n{ background-color: #ff614a; color: #fff;}
.mol-ites .ite.hover::after{ background-color: #ff614a; }
.moday{ width: 100%; height:40rpx; overflow: hidden; position: relative; margin-top:20rpx;}
.moday .dd{ width: 52rpx; height: 40rpx; line-height: 1; text-align: center; font-size: 22rpx;
position: absolute; left: 0; bottom: 0;}
.moday .dd:nth-of-type(2){ left: 107rpx;}
.moday .dd:nth-of-type(3){ left: 214rpx;}
.moday .dd:nth-of-type(4){ left: 321rpx;}
.moday .dd:nth-of-type(5){ left: 428rpx;}
.moday .dd:nth-of-type(6){ left: 535rpx;}
.moday .dd:nth-of-type(7){ left: 642rpx;}
.the-btn{ margin: 50rpx 0;}
.the-btn .btn{ background-color: #ff614a; color: #fff;}
.the-btn.signed .btn{ background-color: rgba(153, 153, 153, 0.61); }
.explax{ padding: 0 30rpx; font-size: 28rpx; color: #666;}
js
// pages/signIn/signIn.js
//获取应用实例
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
//img_url: config.imgUrl, //图片地址
//签到模块
signNum: 1, //签到数
signState: false, //签到状态
min: 1, //默认值日期第一天1
max: 7, //默认值日期最后一天7
be: 0, //默认倍数
},
onLoad: function (options) {
let _this = this;
var a = wx.getStorageSync("userInfo");
a ? this.setData({
uInfo: a
}) : wx.showModal({
title: "提示",
content: "您未登陆,请先登陆!",
success: function (t) {
if (t.confirm) {
var a = encodeURIComponent("/sqtg_sun/pages/public/pages/myorder/myorder?id=0");
app.reTo("/sqtg_sun/pages/home/login/login?id=" + a);
} else t.cancel && app.lunchTo("/sqtg_sun/pages/home/index/index");
}
});
//接收后端数据
this.getSignInfo();
},
getSignInfo(){
let that = this;
app.ajax({
url: "Signin|getSignInfo",
data: {
id:this.data.uInfo.id
},
success: function (res) {
console.log('连接成功')
that.setData({
signNum: res.data.signNum,
min: res.data.min //接收到的数据,页面调用的是这里的数据
})
},
// fail: function (res) {
// console.log("连接失败")
// }
})
},
//签到
bindSignIn(e) {
var that = this,
num = e.currentTarget.dataset.num;
num++
app.ajax({
url: "Signin|sign",
data: {
id: this.data.uInfo.id
},
success: function (res) {
that.setData({
signNum: num,
// signState: false //点击后是否继续允许点击,true为不允许,false为允许,正式使用时应为true
})
var min = e.currentTarget.dataset.min,
max = e.currentTarget.dataset.max,
be = e.currentTarget.dataset.be;
if (num % 7 == 0) {
be += 1;
that.setData({
be: be
})
}
if (num == 7 * be + 1) {
that.setData({
min: 7 * be + 1,
max: 7 * be + 7
})
}
// wx.showToast({
// icon: 'success',
// title: res.msg,
// })
console.log('连接成功1')
that.setData({
// signNum: res.data,
// min: res.data, //接收到的数据,页面调用的是这里的数据
// signState: res.data//点击后是否继续允许点击,true为不允许,false为允许,正式使用时应为true
})
},
// fail: function (res) {
// console.log("连接失败")
// }
})
},
})
后端(PHP,使用thinkphp框架)
<?php
namespace app\api\controller;
use app\base\controller\Api;
use app\model\User;
use think\Db;
class Signin extends Api
{
public function getSignInfo($id)
{
// 此处的$id 等价于 $id=$_POST['id'];
//php获取今日开始时间戳和结束时间戳
$today_start = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
$today_end = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')) - 1;
//php获取昨日起始时间戳和结束时间戳
$yesterday_start = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y'));
$yesterday_end = mktime(0, 0, 0, date('m'), date('d'), date('Y')) - 1;
$user = User::get(['id' => $id]);//判断id是否存在
//查询上一次签到时间
$lastdata = Db::table('rs_signin')
->where('ids', '=', $id)
->where('time','>=',$yesterday_start)
->where('time','<=',$yesterday_end)
->find();
if (!$lastdata) {
$signNum = Db::table('rs_signin')
->where('ids', '=', $id)
->where('time','>=',strtotime(date('Y-m-d 00:00:00')))
->count();
}else{
$signNum = Db::table('rs_signin')
->where('ids', '=', $id)
->where('time','>=',$user['firsttime'])
->count();
}
if ($signNum<7){
$min = 1;
}elseif($signNum>=7){
$min = $signNum-5;
}
success_json(['signNum'=>$signNum,'min'=>$min]);
if ($lastdata >= $yesterday_start && $lastdata <= $yesterday_end) { //昨天有签到的情况
//算出连续签到天数并输出值
// print_r($data);
// return json($data); //thinkphp原先的发送信息的方法,这个版本被更改过,变成了下面的success_json()方法
$dates = date('d', time()) - date('d', $data); //用今天的时间减去初始签到时间,得到中间相差的日数,即连续签到时间
success_json($dates); //成功时的操作(输出连续签到天数),此方法相当于return,应放在最后执行
} elseif ($lastdata < $yesterday_start) { //昨天没有签到的情况
// $counts = $integrals + 1;
//修改初始签到时间
$time = time(); //time值为今天签到时的时间戳
$data = Db::table('rs_signin')
->where('ids', '=', 82)
->update(['time' => $time]);//thinkphp的查询
}
} //getSignInfo()方法结束
//签到
public function sign($id)
{
//php获取今日开始时间戳和结束时间戳
$today_start = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
$today_end = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')) - 1;
//php获取昨日起始时间戳和结束时间戳
$yesterday_start = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y'));
$yesterday_end = mktime(0, 0, 0, date('m'), date('d'), date('Y')) - 1;
$issign = Db::table('rs_signin')
->where('ids', '=', $id)
->where('time', '>=', $today_start)
->where('time', '<=', $today_end)
->find();//判断今天是否已签到过
if ($issign) { //如果今天已经签到过,便阻止点击并终止操作
$signs = User::where('id',$id)->column('sign');
error_json('今日已签到');
return;
}
$id_select = Db::table('rs_signin')
->where('ids', '=', $id)
->where('time', '>=', $yesterday_start)
->where('time', '<=', $yesterday_end)
->find();//判断昨天是否已签到过
//查询积分
$integrals = User::where('id', '=', $id)->find();
$integrals = $integrals['integral'];
// print_r($integrals);
if ($id_select) { //如果昨天已经签到过,便算出今天签到之后与初始签到日之间的日数差,即连续签到天数
$member = User::where('id', '=', $id)->find();
// $dates = date('d', time()) - date('d', $data); //用今天的时间减去初始签到时间,得到中间相差的日数,即连续签到时间
$diff = date_diff((new \DateTime(date('Y-m-d 00:00:00',$member['firsttime']))), (new \DateTime(date('Y-m-d 00:00:00'))));
$day = $diff->days;
if ($day+1 >= 7) {
$integral_count = 3;
} else {
$integral_count = 1;
}
$counts = $integrals + $integral_count;
Db::table('rs_signin')->insert(['ids' => $id, 'time' => time(), 'integral' => $integral_count]);
User::update(['integral' => $counts],['id'=>$id]);
// print_r($day);
} else { //如果昨天没签到过,便更改user表中firsttime字段的值,并新增一条记录进rs_signin表中
// print_r('----');
$counts = $integrals + 1;
User::update(['firsttime' => strtotime(date('Y-m-d 00:00:00')),'integral'=>$counts],['id'=>$id]);
Db::table('rs_signin')->insert(['ids' => $id, 'time' => time(), 'integral' => 1]);
}
}
}//类结束
最终效果如下:
上一篇: Mysql安装后cmd找不到命令