309 lines
8.8 KiB
PHP
309 lines
8.8 KiB
PHP
<?php
|
|
|
|
namespace Modules\User\Facades;
|
|
|
|
use Carbon\Carbon;
|
|
use DateTime;
|
|
use Exception;
|
|
use Illuminate\Support\HigherOrderCollectionProxy;
|
|
use Modules\Gout\Models\GoutCase;
|
|
use Modules\User\Models\SignConfig;
|
|
use Modules\User\Models\SignLog;
|
|
use Modules\User\Models\User;
|
|
|
|
/**
|
|
* 用户签到
|
|
* Class UserSign
|
|
*
|
|
* @package Modules\User\Facades
|
|
*/
|
|
class UserSign
|
|
{
|
|
|
|
/**
|
|
* @param User $user
|
|
* @return array
|
|
*/
|
|
public static function signIn(User $user, $date = ''): array
|
|
{
|
|
try {
|
|
$date = Carbon::parse($date);//签到日期
|
|
|
|
$params = SignConfig::getParams();
|
|
if (! $params['open']) {
|
|
throw new Exception('签到功能未开启');
|
|
}
|
|
|
|
if (! self::canSign($user, $date)) {
|
|
throw new Exception(self::getNotSignText($user, $date));
|
|
}
|
|
|
|
$continue_days = $user->sign->continue_days;
|
|
$counts = $user->sign->counts;
|
|
if (SignLog::where('user_id', $user->id)
|
|
->whereDate('date', (clone $date)->subDay()->toDateString())
|
|
->exists()) {
|
|
$continue_days++;
|
|
} else {
|
|
$continue_days = 1;
|
|
}
|
|
|
|
$crystals = self::getSignCrystal($continue_days);
|
|
$rule_name = $params['rule_name'];
|
|
$str = "第{$continue_days}天签到";
|
|
if ($crystals > 0 && $user->isExperience()) {
|
|
$user->account->rule($rule_name, 0, false, [
|
|
'frozen_at' => now()->toDateTimeString(),
|
|
'settle_at' => now()->toDateTimeString(),
|
|
'remark' => '第'.$continue_days.'天签到',
|
|
]);
|
|
$str .= ",获得{$crystals}水滴"."\n";
|
|
// $str .= '第'.$continue_days.'天签到';
|
|
}
|
|
|
|
|
|
$task_crystals = self::getTaskCrystal($continue_days);
|
|
if ($task_crystals > 0) {
|
|
// $user->account->rule($rule_name, $task_crystals, true, [
|
|
// 'frozen_at' => now()->toDateTimeString(),
|
|
// 'settle_at' => now()->toDateTimeString(),
|
|
// 'remark' => '连续签到'.$continue_days.'天',
|
|
// ]);
|
|
// $str .= '连续签到'.$continue_days.'天,获得水晶'.$task_crystals;
|
|
$str .= '连续签到'.$continue_days.'天';
|
|
}
|
|
|
|
$user->sign->update([
|
|
'continue_days' => $continue_days,
|
|
'counts' => ++$counts,
|
|
'last_sign_at' => $date,
|
|
]);
|
|
SignLog::create([
|
|
'user_id' => $user->id,
|
|
'date' => $date,
|
|
'type' => 0,
|
|
]);
|
|
|
|
return [true, $str];
|
|
} catch (Exception $e) {
|
|
return [false, $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 返回连续签到额外任务
|
|
*
|
|
* @param int $continue_days
|
|
* @return int
|
|
*/
|
|
public static function getTaskCrystal(int $continue_days = 1): int
|
|
{
|
|
$tasks = SignConfig::getTasks();
|
|
$task = $tasks->firstWhere('day', $continue_days);
|
|
|
|
return $task['number'] ?? 0;
|
|
}
|
|
|
|
public static function getNextTaskCrystal($continue_days = 1)
|
|
{
|
|
$tasks = SignConfig::getTasks();
|
|
|
|
return $tasks->where('day', ' > ', $continue_days)
|
|
->sortBy('day')
|
|
->first();
|
|
}
|
|
|
|
/**
|
|
* 返回签到奖励
|
|
*
|
|
* @param int $continue_days
|
|
* @return HigherOrderCollectionProxy|int|mixed
|
|
*/
|
|
public static function getSignCrystal(int &$continue_days = 1)
|
|
{
|
|
$params = SignConfig::getParams();
|
|
$crystals = 0;
|
|
|
|
switch ($params['type']) {
|
|
case 'single':
|
|
$crystals = $params['single_number'];
|
|
break;
|
|
case 'continuous':
|
|
$crystals = (int) $params['continuous_base'] + (int) bcmul($continue_days - 1,
|
|
$params['continuous_incremental'],
|
|
0);
|
|
break;
|
|
case 'cycle':
|
|
if ($continue_days > $params['cycle_day']) {
|
|
$continue_days -= $params['cycle_day'];
|
|
}
|
|
$crystals = (int) $params['cycle_base'] + (int) bcmul($continue_days - 1, $params['cycle_incremental'],
|
|
0);
|
|
break;
|
|
}
|
|
|
|
return $crystals;
|
|
}
|
|
|
|
/**
|
|
* Notes : 某一天是否可签到
|
|
*
|
|
* @Date : 2021/5/28 3:25 下午
|
|
* @Author : <Jason.C>
|
|
* @param User $user
|
|
* @param Carbon $date
|
|
* @return bool
|
|
*/
|
|
public static function canSign(User $user, DateTime $date): bool
|
|
{
|
|
$identityMiddle = $user->identityMiddle()->first();
|
|
$start_at = $identityMiddle->started_at;
|
|
if (! $start_at) {
|
|
$start_at = $identityMiddle->created_at;
|
|
}
|
|
|
|
return $identityMiddle->identity->order > 1 &&
|
|
Carbon::parse($date)->endOfDay()->gt($start_at) &&
|
|
! $user->IsSign($date) &&
|
|
$date->isToday();
|
|
}
|
|
|
|
/**
|
|
* Notes: 是否可以补签
|
|
*
|
|
* @Author: 玄尘
|
|
* @Date: 2022/8/12 8:51
|
|
* @param User $user
|
|
* @param DateTime $date
|
|
* @return bool
|
|
*/
|
|
public static function canReSign(User $user, DateTime $date): bool
|
|
{
|
|
$identityMiddle = $user->identityMiddle()->first();
|
|
$start_at = $identityMiddle->started_at;
|
|
if (! $start_at) {
|
|
$start_at = $identityMiddle->created_at;
|
|
}
|
|
|
|
return ! $user->IsSign($date) &&
|
|
now()->endOfDay()->gt($date) &&
|
|
! $date->isToday() &&
|
|
Carbon::parse($date)->endOfDay()->gt($start_at);
|
|
}
|
|
|
|
/**
|
|
* Notes: 获取不可打卡的信息
|
|
*
|
|
* @Author: 玄尘
|
|
* @Date: 2022/8/10 13:18
|
|
*/
|
|
public static function getNotSignText(User $user, DateTime $date)
|
|
{
|
|
$identityMiddle = $user->identityMiddle()->first();
|
|
if (SignLog::where('user_id', $user->id)->whereDate('date', $date)->exists()) {
|
|
return '今日已打卡';
|
|
}
|
|
|
|
if ($identityMiddle->identity->order < 2) {
|
|
return '未开通会员';
|
|
}
|
|
|
|
$started_at = $identityMiddle->started_at;
|
|
if (! $started_at) {
|
|
$started_at = $identityMiddle->created_at;
|
|
}
|
|
|
|
if ($started_at->gt(Carbon::parse($date)->startOfDay())) {
|
|
return '当前时间还未开通会员';
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Notes : 补签
|
|
*
|
|
* @Date : 2021/5/28 3:15 下午
|
|
* @Author : <Jason.C>
|
|
* @param User $user
|
|
* @param DateTime $date
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public static function replenish(User $user, DateTime $date): array
|
|
{
|
|
if (! self::canReSign($user, $date)) {
|
|
throw new Exception(self::getNotSignText($user, $date));
|
|
}
|
|
$params = SignConfig::getParams();
|
|
|
|
$continue_days = $user->sign->continue_days;
|
|
|
|
$crystals = self::getSignCrystal($continue_days);
|
|
$rule_name = $params['rule_name'];
|
|
$str = $date->format('Y-m-d')."号补签";
|
|
|
|
if ($crystals > 0 && $user->isExperience()) {
|
|
$user->account->rule($rule_name, 0, false, [
|
|
'frozen_at' => now()->toDateTimeString(),
|
|
'settle_at' => now()->toDateTimeString(),
|
|
'remark' => now()->toDateTimeString().'天补签到',
|
|
]);
|
|
$str .= ",获得{$crystals}水滴"."\n";
|
|
}
|
|
|
|
$counts = $user->sign->counts;
|
|
|
|
|
|
$user->sign->update([
|
|
'counts' => ++$counts,
|
|
]);
|
|
|
|
$log = SignLog::create([
|
|
'user_id' => $user->id,
|
|
'date' => $date,
|
|
'type' => 1,
|
|
]);
|
|
|
|
self::recalculateContinueDays($user);
|
|
|
|
return [true, $str];
|
|
}
|
|
|
|
/**
|
|
* Notes: 重新计算连续签到日期
|
|
*
|
|
* @Author: 玄尘
|
|
* @Date: 2022/8/4 9:34
|
|
*/
|
|
public static function recalculateContinueDays(User $user)
|
|
{
|
|
$reset_at = $user->sign->reset_at;
|
|
$days = SignLog::query()
|
|
->byUser($user)
|
|
->when($reset_at, function ($q) use ($reset_at) {
|
|
$q->where('date', '>=', $reset_at);
|
|
})
|
|
->latest('date')
|
|
->pluck('date');
|
|
|
|
$continue_days = 1;
|
|
foreach ($days as $key => $day) {
|
|
if (isset($days[$key + 1])) {
|
|
if ($day->subDay()->isSameDay($days[$key + 1])) {
|
|
$continue_days++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
$user->sign->update([
|
|
'continue_days' => max($continue_days, 1),
|
|
'counts' => $user->signLogs()->count()
|
|
]);
|
|
return true;
|
|
}
|
|
|
|
}
|