Files
MrleeAdmin/backend/app/dao/member/MemberSignDao.php
T
2026-08-31 11:33:59 +08:00

251 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
namespace app\dao\member;
use app\service\api\member\MemberService;
use core\base\BaseDao;
use app\model\member\MemberSign;
use support\Container;
/**
* 会员签到DAO
*/
class MemberSignDao extends BaseDao
{
/**
* 设置模型
*/
protected function setModel(): string
{
return MemberSign::class;
}
/**
* 创建签到记录
*/
public function created(int $memberId, string $signDate, int $points, int $continuousDays, array $deviceInfo = []): MemberSign
{
$sign = new MemberSign();
$sign->member_id = $memberId;
$sign->sign_date = $signDate;
$sign->points = $points;
$sign->continuous_days = $continuousDays;
$sign->save();
return $sign;
}
/**
* 检查今日是否已签到
*/
public function isSignedToday(int|string $memberId, string $today): bool
{
return $this->query()
->where('member_id', $memberId)
->where('sign_date', $today)
->exists();
}
/**
* 获取最近一次签到记录
*/
public function getLastSign(int|string $memberId): ?MemberSign
{
return $this->query()
->where('member_id', $memberId)
->orderBy('sign_date', 'desc')
->first();
}
/**
* 获取会员签到记录
*/
public function getMemberSignRecords(int|string $memberId, int $days = 30): array
{
$startDate = date('Y-m-d', strtotime("-$days days"));
return $this->query()
->where('member_id', $memberId)
->where('sign_date', '>=', $startDate)
->orderBy('sign_date', 'asc')
->get()
->toArray();
}
/**
* 获取本月签到天数
*/
public function getMonthSignDays(int|string $memberId): int
{
$firstDay = date('Y-m-01');
$lastDay = date('Y-m-t');
return $this->query()
->where('member_id', $memberId)
->whereBetween('sign_date', [$firstDay, $lastDay])
->count();
}
/**
* 获取连续签到排行榜
*/
public function getContinuousSignRanking(int $limit = 10): array
{
return $this->query()
->selectRaw('member_id, MAX(continuous_days) as max_continuous_days')
->groupBy('member_id')
->orderBy('max_continuous_days', 'desc')
->limit($limit)
->with('member')
->get()
->toArray();
}
/**
* 获取签到统计
*/
public function getSignStatistics(int|string $memberId): array
{
$totalSignDays = $this->query()
->where('member_id', $memberId)
->count();
$monthSignDays = $this->getMonthSignDays($memberId);
$continuousDays = $this->query()
->where('member_id', $memberId)
->orderBy('sign_date', 'desc')
->value('continuous_days') ?? 0;
// 获取用户积分
$points = Container::make(MemberService::class)
->get($memberId)
->points ?? 0;
return [
'total_sign_days' => $totalSignDays,
'month_sign_days' => $monthSignDays,
'continuous_days' => $continuousDays,
'today_signed' => $this->isSignedToday($memberId, date('Y-m-d')),
'points' => $points
];
}
/**
* 获取年度签到统计
*/
public function getYearSignStatistics(int|string $memberId, int $year = null): array
{
if ($year === null) {
$year = date('Y');
}
$startDate = $year . '-01-01';
$endDate = $year . '-12-31';
$totalSignDays = $this->query()
->where('member_id', $memberId)
->whereBetween('sign_date', [$startDate, $endDate])
->count();
// 统计每个月的签到天数
$monthlyStats = [];
for ($month = 1; $month <= 12; $month++) {
$monthStart = $year . '-' . str_pad((string)$month, 2, '0', STR_PAD_LEFT) . '-01';
$monthEnd = $year . '-' . str_pad((string)$month, 2, '0', STR_PAD_LEFT) . '-' . date('t', strtotime($monthStart));
$monthlyStats[$month] = $this->query()
->where('member_id', $memberId)
->whereBetween('sign_date', [$monthStart, $monthEnd])
->count();
}
return [
'year' => $year,
'total_sign_days' => $totalSignDays,
'monthly_stats' => $monthlyStats
];
}
/**
* 获取周签到统计
*/
public function getWeekSignStatistics(int|string $memberId): array
{
$weekStart = date('Y-m-d', strtotime('this week'));
$weekEnd = date('Y-m-d', strtotime('this week +6 days'));
$signDays = $this->query()
->where('member_id', $memberId)
->whereBetween('sign_date', [$weekStart, $weekEnd])
->count();
return [
'week_start' => $weekStart,
'week_end' => $weekEnd,
'sign_days' => $signDays,
'total_days' => 7
];
}
/**
* 获取连续签到奖励
*/
public function getContinuousSignReward(int|string $continuousDays): int
{
// 连续签到奖励规则
$rewards = [
7 => 50, // 连续7天奖励50积分
14 => 100, // 连续14天奖励100积分
30 => 200, // 连续30天奖励200积分
];
return $rewards[$continuousDays] ?? 0;
}
/**
* 获取签到日历
*/
public function getSignCalendar(int|string $memberId, int $year, int $month): array
{
$firstDay = $year . '-' . str_pad((string)$month, 2, '0', STR_PAD_LEFT) . '-01';
$lastDay = $year . '-' . str_pad((string)$month, 2, '0', STR_PAD_LEFT) . '-' . date('t', strtotime($firstDay));
$signs = $this->query()
->where('member_id', $memberId)
->whereBetween('sign_date', [$firstDay, $lastDay])
->get()
->toArray();
$calendar = [];
foreach ($signs as $sign) {
$calendar[] = $sign['sign_date'];
}
return $calendar;
}
/**
* 批量获取会员签到统计
*/
public function batchGetSignStatistics(array $memberIds): array
{
$result = [];
foreach ($memberIds as $memberId) {
$result[$memberId] = $this->getSignStatistics($memberId);
}
return $result;
}
/**
* 清理过期签到记录(保留最近一年的记录)
*/
public function cleanExpiredRecords(): int
{
$oneYearAgo = date('Y-m-d', strtotime('-1 year'));
return $this->query()
->where('sign_date', '<', $oneYearAgo)
->delete();
}
}