create([ 'wechat_user_id' => $user->id, 'visited_at' => now(), ]); } public function actualTotalVisits(): int { return (int) WechatUserHomeVisit::query()->count(); } public function actualTodayVisits(): int { $tz = (string) config('app.timezone'); $start = Carbon::now($tz)->startOfDay(); $end = Carbon::now($tz)->endOfDay(); return (int) WechatUserHomeVisit::query() ->whereBetween('visited_at', [$start, $end]) ->count(); } public function totalVisits(): int { return max(0, $this->actualTotalVisits() + $this->totalOffset()); } public function todayVisits(): int { return max(0, $this->actualTodayVisits() + $this->todayOffset()); } public function totalOffset(): int { return SystemSetting::getInt(self::KEY_TOTAL_OFFSET, 0); } public function todayOffset(): int { $today = Carbon::now((string) config('app.timezone'))->toDateString(); $offsetDate = SystemSetting::getString(self::KEY_TODAY_OFFSET_DATE); if ($offsetDate !== $today) { return 0; } return SystemSetting::getInt(self::KEY_TODAY_OFFSET, 0); } /** * @return array{ * actual_total: int, * actual_today: int, * display_total: int, * display_today: int, * total_offset: int, * today_offset: int * } */ public function visitStatsPayload(): array { return [ 'actual_total' => $this->actualTotalVisits(), 'actual_today' => $this->actualTodayVisits(), 'display_total' => $this->totalVisits(), 'display_today' => $this->todayVisits(), 'total_offset' => $this->totalOffset(), 'today_offset' => $this->todayOffset(), ]; } public function updateDisplayValues(int $displayTotal, int $displayToday): void { SystemSetting::setInt( self::KEY_TOTAL_OFFSET, $displayTotal - $this->actualTotalVisits(), ); $today = Carbon::now((string) config('app.timezone'))->toDateString(); SystemSetting::setInt( self::KEY_TODAY_OFFSET, $displayToday - $this->actualTodayVisits(), ); SystemSetting::setString(self::KEY_TODAY_OFFSET_DATE, $today); } public function totalWechatUsers(): int { return (int) WechatUser::query()->count(); } }