first
This commit is contained in:
109
modules/User/Facades/Calendar.php
Normal file
109
modules/User/Facades/Calendar.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\User\Facades;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Modules\User\Models\User;
|
||||
|
||||
class Calendar
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 获取日历展示图,设置每周开始为周日
|
||||
*
|
||||
* @Date : 2022/1/21 10:23
|
||||
* @Author : Mr.wang
|
||||
* @param string $date
|
||||
* @return array
|
||||
*/
|
||||
public static function show(string $date = ''): array
|
||||
{
|
||||
$start = Carbon::parse($date)->startOfMonth()->startOfWeek(0)->toDateString();
|
||||
$end = Carbon::parse($date)->endOfMonth()->endOfWeek(6)->toDateString();
|
||||
$data = self::getBetweenDate($start, $end);
|
||||
|
||||
$calendar = Carbon::parse($date);
|
||||
|
||||
$days = $data->map(function ($today) use ($calendar) {
|
||||
return [
|
||||
'today' => $today->toDateString(),
|
||||
'day' => (int) $today->format('j'),
|
||||
'isPast' => $today->isPast(),//是否为之前的日期
|
||||
'isMonth' => $today->isSameMonth($calendar),//当前月
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'calendar' => $days
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 返回日期区间
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/2/8 16:52
|
||||
* @param string $start_at 开始日期
|
||||
* @param string $end_at 结束日期
|
||||
*/
|
||||
public static function getBetweenDate(string $start_at, string $end_at)
|
||||
{
|
||||
return collect(CarbonPeriod::create($start_at, $end_at));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取日期 某一天的前一天后一天
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/1/21 11:03
|
||||
* @param string $today
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function day(string $today = '', string $type = ''): string
|
||||
{
|
||||
$variate = ['before' => -1, 'after' => 1, '' => 0][$type];
|
||||
|
||||
return Carbon::parse($today)->addDays($variate)->toDateString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取日期 某一天的前一天后一天
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/1/21 11:03
|
||||
* @param string $month
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function getFirstDayByMonth(string $month = '', string $type = ''): string
|
||||
{
|
||||
$month = Carbon::parse($month);
|
||||
if ($type == 'before') {
|
||||
$month = $month->subMonth();
|
||||
}
|
||||
|
||||
if ($type == 'after') {
|
||||
$month = $month->addMonth();
|
||||
}
|
||||
|
||||
return $month->startOfMonth()->toDateString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取年份
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/8/10 9:30
|
||||
* @param $start
|
||||
*/
|
||||
public static function getYears($startYear)
|
||||
{
|
||||
$years = CarbonPeriod::years($startYear);
|
||||
return $years;
|
||||
}
|
||||
}
|
||||
122
modules/User/Facades/Sms.php
Normal file
122
modules/User/Facades/Sms.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\User\Facades;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Modules\User\Models\Sms as SmsModel;
|
||||
use Modules\User\Models\SmsConfig;
|
||||
use Modules\User\Services\VerificationCode;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
|
||||
use Overtrue\EasySms\Strategies\OrderStrategy;
|
||||
|
||||
class Sms
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 获取短信配置
|
||||
*
|
||||
* @Date : 2021/5/27 4:01 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param string|null $key 配置的主键
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getConfig(string $key = null)
|
||||
{
|
||||
$model = SmsConfig::orderByDesc('in_use')->first();
|
||||
|
||||
$config = [
|
||||
'debug' => $model->debug ?? true,
|
||||
'debug_code' => $model->debug_code ?? '0000',
|
||||
'length' => $model->length ?? 4,
|
||||
'template' => $model->template ?? [],
|
||||
'default' => [
|
||||
'strategy' => OrderStrategy::class,
|
||||
'gateways' => [
|
||||
$model->default_gateway ?? 'aliyun',
|
||||
],
|
||||
],
|
||||
'gateways' => [
|
||||
$model->default_gateway => $model->getGateway(),
|
||||
],
|
||||
];
|
||||
|
||||
// dd($config);
|
||||
|
||||
if (isset($config['gateways']['aliyun'])) {
|
||||
$config['gateways']['aliyun']['access_key_id'] = $config['gateways']['aliyun']['APP_ID'];
|
||||
$config['gateways']['aliyun']['access_key_secret'] = $config['gateways']['aliyun']['APP_SECRET'];
|
||||
$config['gateways']['aliyun']['sign_name'] = $config['gateways']['aliyun']['SIGN_NAME'];
|
||||
}
|
||||
|
||||
return Arr::get($config, $key) ?? $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 发送验证码短信
|
||||
*
|
||||
* @Date : 2021/5/26 4:17 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param string $mobile 手机号码
|
||||
* @param string $channel 验证通道
|
||||
* @throws InvalidArgumentException
|
||||
* @throws NoGatewayAvailableException
|
||||
*/
|
||||
public static function sendVerificationCode(string $mobile, string $channel = 'DEFAULT')
|
||||
{
|
||||
$message = new VerificationCode(self::getConfig(), $channel);
|
||||
|
||||
if (! self::getConfig('debug')) {
|
||||
app('sms')->send($mobile, $message);
|
||||
}
|
||||
|
||||
SmsModel::create([
|
||||
'mobile' => $mobile,
|
||||
'channel' => $channel,
|
||||
'gateway' => self::getConfig('debug') ? 'debug' : self::getConfig('default.gateways.0'),
|
||||
'content' => $message->code,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证短信
|
||||
*
|
||||
* @Author:<C.Jason>
|
||||
* @Date :2018-11-07T14:26:38+0800
|
||||
* @param string $mobile 手机号码
|
||||
* @param string $code 验证码
|
||||
* @param string $channel 验证通道
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkCode(string $mobile, string $code, string $channel = 'DEFAULT'): bool
|
||||
{
|
||||
$Sms = SmsModel::where('mobile', $mobile)->where('channel', $channel)->first();
|
||||
|
||||
if ($Sms && $Sms->content == $code) {
|
||||
if ($Sms->used && ! self::getConfig('debug')) {
|
||||
return false;
|
||||
}
|
||||
# todo 有效期判定
|
||||
$Sms->used = 1;
|
||||
$Sms->save();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 发送通知短信
|
||||
*
|
||||
* @Date : 2021/5/26 5:08 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param string|array $mobile 接受短信的手机号
|
||||
* @param string $content 短信内容
|
||||
*/
|
||||
public static function sendNotification($mobile, string $content)
|
||||
{
|
||||
# todo. 这里要实现批量发送,短信通道等操作,待测试
|
||||
}
|
||||
|
||||
}
|
||||
308
modules/User/Facades/UserSign.php
Normal file
308
modules/User/Facades/UserSign.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?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->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->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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user