toArray() : $banner; $item['status'] = (int) $item['status']; $item['activity_id'] = self::boundActivityId($item['click_type'] ?? null, $item['link'] ?? null); $item = array_replace($item, self::links($item)); $item['can_manual_toggle'] = $item['activity_id'] === null; $item['manual_status'] = $item['can_manual_toggle'] ? $item['status'] : null; if ($item['activity_id'] !== null) { $activityIds[$item['activity_id']] = $item['activity_id']; } $items[] = $item; } // Read raw timestamps; ActivityReward's date accessors discard the time of day. $activities = empty($activityIds) ? collect() : DB::table('activity_rewards') ->whereIn('id', array_values($activityIds)) ->get(['id', 'status', 'start_time', 'end_time'])->keyBy('id'); foreach ($items as &$item) { $activity = $item['activity_id'] === null ? null : $activities->get($item['activity_id']); $reason = null; if ($item['activity_id'] !== null) { if ($activity === null) { $reason = 'activity_missing'; } elseif ((int) $activity->status !== 1) { $reason = 'activity_offline'; } elseif ((int) $activity->start_time > $now) { $reason = 'activity_not_started'; } elseif ((int) $activity->end_time <= $now) { $reason = 'activity_ended'; } } elseif ($item['manual_status'] !== 1) { $reason = 'manual'; } $item['effective_status'] = $reason === null ? 1 : 0; $item['status'] = $item['effective_status']; $item['offline_reason'] = $reason; } unset($item); return $items; } /** Normalized jump fields for the admin form; internal rows always expose both platform paths. */ public static function links(array $row): array { $type = self::clickType($row['click_type'] ?? null, $row['link'] ?? null); if ($type === 'activity') { return ['click_type' => $type, 'link' => self::activityId($row['link'] ?? null), 'link_pc' => null, 'link_h5' => null]; } return ContentLink::normalize(['click_type' => $type] + $row); } }