目錄
一、需求
1、爲什麼要贈送積分
用戶(連續)簽到贈送(額外)積分,可以增加用戶的活躍度,少一些殭屍用戶;邀請好友贈送積分,可以擴大平臺的用戶量。
2、怎麼獲取積分
這個範圍就比較廣了,給幾個獲取積分的例子
- 用戶註冊獲取積分
- 成功邀請新用戶獲取積分
- 完成首購獲取積分
- 用戶消費獲取積分
- 用戶簽到獲取積分
- 完成新手任務獲取積分
- 完善基本信息獲取積分
- …
3、積分如何使用
1)、兌換
- 可以弄個積分商城,直接用積分兌換商品
2)、抵扣
- 購買商品時,除了可以使用優惠券抵扣、餘額抵扣,還可以使用積分抵扣
3)、等等
二、規則
1、用戶註冊
- 用戶註冊贈送積分
2、成功邀請新用戶
- 成功邀請新用戶,新用戶有註冊積分,邀請人有邀請積分
3、用戶簽到
- 用戶每日簽到可以獲取固定的積分
- 用戶連續簽到滿n天,額外贈送積分
- 如果用戶同時滿足多個連續簽到任務,則取額外積分爲最大簽到天數的積分
- 多個簽到任務:比如用戶連續5天贈送1積分,用戶連續簽到10天贈送2積分;用戶連續簽到了10天,則既滿足連續簽到5天,又滿足連續簽到10天,我們取連續簽到10天的2積分作爲額外積分。(也可以都取,則額外積分爲1+2=3,這個要看規則怎麼定了)
4、聯想
- 可以添加規則
用戶簽到當天如果是用戶生日,積分翻倍
Tips:如果生日可爲公曆,也可爲農曆,則要注意區分
- …
三、數據表
1、用戶表 user
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
...
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '總積分',
`signDay` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '連續簽到天數',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
2、用戶簽到表 user_sign
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`userId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '積分',
`dateTime` varchar(50) NOT NULL DEFAULT '' COMMENT '簽到日期:格式爲2090-01-01',
`remark` text COMMENT '備註',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
3、積分(獲取)日誌表 integral_log
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`userId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`fkId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '關聯id',
`fkType` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '關聯類型:1:新用戶註冊;2用戶簽到;3用戶消費;4邀請新用戶;...',
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '積分',
`remark` text COMMENT '備註',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
四、代碼
1、用戶簽到方法
/**
* 用戶簽到
* @return mixed
* @throws Exception
*/
public function sign() {
$userInfo = self::loginInfo(); //緩存中根據Token獲取用戶的登錄信息
if (!$userInfo){
exit('請先登錄');
}
$userId = $userInfo['id'];
$userDao = new UserDao(); //實例化用戶表
$signDao = new UserSignDao(); //實例化用戶簽到表
//判斷用戶今天是否簽到
$dateTime = date('Y-m-d');
$todayParam = ['userId' => $userId, 'dateTime' => $dateTime];
$todayInfo = $signDao->single($todayParam);
if ($todayInfo){
exit('您今天已經簽到過了');
}
//判斷用戶昨天是否簽到
$yesterday = date('Y-m-d', strtotime('-1 day')); //昨天的日期格式:2090-01-01
$yesterdayParam = ['userId' => $userId, 'dateTime' => $yesterday];
$yesterdayInfo = $signDao->single($yesterdayParam);
if ($yesterdayInfo){ //昨天簽到了,簽到天數自增1
$userDao->setInc(['id' => $userId], 'signDay', 1); //第三個參數默認爲1,可以不傳。
}else{ //昨天斷籤,連續簽到天數重置爲1
$userDao->updateByQuery(['signDay' => 1], ['id' => $userId]); //更新該用戶的簽到天數爲1天
}
list($integral, $remark) = IntegralService::insert($userId, 2); //記錄簽到積分日誌
//添加簽到數據
$data = [
'userId' => $userId, //用戶ID
'dateTime' => $dateTime, //簽到日期
'integral' => $integral, //簽到贈送的積分
'remark' => $remark //簽到日誌
];
$signDao->insert($data); //添加數據,createTime,updateTime已在該方法中追加
return 'success';
}
2、公共類 - 積分贈送日誌方法
- 這個表可以再加個type字段,區分積分類型:積分獲取/積分消費
class IntegralService{
/**
* [積分贈送日誌]公共方法
* @param $userId 用戶ID
* @param $fkType 贈送類型:1:新用戶註冊;2用戶簽到;3用戶消費;4邀請新用戶;...
* @param int $fkId 關聯ID:如果類型爲用戶消費,則關聯ID爲訂單的ID;如果類型爲邀請新用戶,則關聯ID爲新用戶的ID...
* @return array 返回[積分,備註]
*/
public static function insert($userId, $fkType, $fkId = 0){
$remark = '';
$integral = 0;
$userDao = new UserDao();
if ($fkType == 1){ //新用戶註冊
$integral = 20; //新用戶註冊贈送積分:這個可以寫到配置裏
$remark = '新用戶贈送積分';
}else if ($fkType == 2){ //每日簽到贈送額外積分
list($integral, $remark) = self::userSign($userId, $userDao);
}else if ($fkType == 3){ //消費
//...
}else if ($fkType == 4){ //推薦新用戶
$userInfo = $userDao->info($fkId); //新用戶的ID
if (empty($userInfo)){
exit('被邀請用戶不存在');
}
$integral = 10; //推薦新用戶註冊贈送積分:這個可以寫到配置裏
$remark = '邀請新用戶 [ ' . $userInfo['username'] . ' ] 贈送積分';
}
//積分日誌記錄
$data = [
'userId' => $userId,
'fkId' => $fkId,
'fkType' => $fkType,
'integral' => $integral,
'remark' => $remark
];
$integralDao = new IntegralLogDao();
$integralDao->insert($data); //添加數據,createTime,updateTime已在該方法中追加
//用戶積分自增$integral
$userDao->setInc(['id' => $userId], 'integral', $integral);
return [$integral, $remark];
}
/**
* 獲取會員簽到獲取的積分,備註
* @param $userId
* @param $userDao
* @return array
*/
public static function userSign($userId, $userDao){
$userInfo = $userDao->info($userId);
if (empty($userInfo)){
exit('用戶不存在');
}
$signDay = $userInfo['signDay']; //用戶連續簽到天數
$remark = '';
$integral = 3; //用戶每日簽到積分:這個可以寫到配置裏
if ($signDay != 0){ //如果簽到日期不爲0
# 簽到額外送積分:這個可以寫到配置裏
/**
* name:說明
* desc:備註,這裏表示連續簽到天數
* value:值,這裏表示額外贈送積分數量
*/
$extraIntegral = [
['name' => '連續簽到7天額外贈送1積分', 'desc' => 7, 'value' => 1],
['name' => '連續簽到15天額外贈送2積分', 'desc' => 15, 'value' => 2],
['name' => '連續簽到30天額外贈送5積分', 'desc' => 30, 'value' => 5],
];
//二維數組排序:按照積分降序,如果同時滿足多個連續簽到任務,則取最大簽到天數的積分。
$values = array_column($extraIntegral, 'value');
array_multisort($values, SORT_DESC, $extraIntegral);
$isGiveExtra = false; //是否已經贈送了額外積分
foreach ($extraIntegral as $value){
$day = $value['desc']; //配置的簽到天數
$giveIntegral = $value['value']; //贈送額外積分
if (($signDay % $day) == 0){ //如果:用戶連續簽到天數 % 配置的連續簽到天數 = 0;我們認爲該用戶可以獲取額外積分
if ($isGiveExtra){ //如果:已經贈送了額外積分,則不再贈送,結束循環
break;
}
$integral += $giveIntegral; //積分 = 每日簽到默認積分 + 連續簽到額外贈送的積分
$remark = "您已經連續簽到了 [ {$day} ] 天,額外贈送您 [ {$giveIntegral} ] 積分"; //備註
$isGiveExtra = true; //設置爲true,已經贈送了積分,不再重複贈送
# 或者去除 $isGiveExtra 變量相關操作,直接在這裏 break
}
}
}
$remark = $remark ? $remark : '簽到贈送積分';
return [$integral, $remark];
}
}