| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- <?php
- namespace App\Services;
- use App\Models\User;
- use Illuminate\Support\Facades\DB;
- /**
- * 注册走势 / 注册域名统计
- */
- class RegisterStatService
- {
- /**
- * @param string $type today|all
- * @return array{type:string,times:array,member:array,virtual:array,member_total:int,virtual_total:int,...}
- */
- public static function trend(string $type, ?string $startDate, ?string $endDate): array
- {
- $today = date('Y-m-d');
- $startDate = $startDate ?: $today;
- $endDate = $endDate ?: $today;
- if ($type === 'today') {
- $day = $startDate;
- $bucketExpr = "DATE_FORMAT(created_at, '%H:00')";
- $times = [];
- for ($h = 0; $h < 24; $h++) {
- $times[] = sprintf('%02d:00', $h);
- }
- $rangeStart = $day . ' 00:00:00';
- $rangeEnd = $day . ' 23:59:59';
- $meta = ['type' => 'today', 'date' => $day];
- } else {
- $bucketExpr = "DATE_FORMAT(created_at, '%Y-%m-%d')";
- $times = [];
- $cursor = strtotime($startDate);
- $endTs = strtotime($endDate);
- while ($cursor <= $endTs) {
- $times[] = date('Y-m-d', $cursor);
- $cursor = strtotime('+1 day', $cursor);
- }
- $rangeStart = $startDate . ' 00:00:00';
- $rangeEnd = $endDate . ' 23:59:59';
- $meta = [
- 'type' => 'all',
- 'start_time' => $startDate,
- 'end_time' => $endDate,
- ];
- }
- $rows = User::query()
- ->selectRaw("{$bucketExpr} as time_key, `from` as user_from, COUNT(*) as cnt")
- ->whereBetween('created_at', [$rangeStart, $rangeEnd])
- ->groupByRaw("{$bucketExpr}, `from`")
- ->get();
- $memberMap = array_fill_keys($times, 0);
- $virtualMap = array_fill_keys($times, 0);
- foreach ($rows as $row) {
- $key = (string)$row->time_key;
- if (!array_key_exists($key, $memberMap)) {
- continue;
- }
- if ((string)$row->user_from === '2') {
- $virtualMap[$key] += (int)$row->cnt;
- } else {
- $memberMap[$key] += (int)$row->cnt;
- }
- }
- return array_merge($meta, [
- 'times' => $times,
- 'member' => array_values($memberMap),
- 'virtual' => array_values($virtualMap),
- 'member_total' => array_sum($memberMap),
- 'virtual_total' => array_sum($virtualMap),
- ]);
- }
- /**
- * 域名统计(SQL 分页)
- *
- * @return array{total:int,data:list<array{register_url:string,register_count:int}>}
- */
- public static function domain(?string $startDate, ?string $endDate, int $page, int $limit): array
- {
- $domainExpr = "IF(register_domain = '' OR register_domain IS NULL, '未知', register_domain)";
- $base = User::query();
- if ($startDate) {
- $base->where('created_at', '>=', $startDate . ' 00:00:00');
- }
- if ($endDate) {
- $base->where('created_at', '<=', $endDate . ' 23:59:59');
- }
- $grouped = (clone $base)
- ->selectRaw("{$domainExpr} as register_url, COUNT(*) as register_count")
- ->groupByRaw($domainExpr);
- $total = (int)DB::query()->fromSub(
- (clone $grouped),
- 'domain_groups'
- )->count();
- $offset = max(0, ($page - 1) * $limit);
- $rows = (clone $grouped)
- ->orderByDesc(DB::raw('register_count'))
- ->offset($offset)
- ->limit($limit)
- ->get();
- $data = $rows->map(fn ($row) => [
- 'register_url' => (string)$row->register_url,
- 'register_count' => (int)$row->register_count,
- ])->values()->all();
- return ['total' => $total, 'data' => $data];
- }
- }
|