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(); } }