request->get('page_path', '')); $platform = trim((string) $this->request->get('platform', '')); if (!$pagePath) { return $this->data(['lists' => []]); } $now = time(); $query = PagePopup::where('status', 1) ->where(function ($q) use ($now) { $q->whereOr([ ['start_time', '=', 0], ['start_time', '<=', $now] ]); }) ->where(function ($q) use ($now) { $q->whereOr([ ['end_time', '=', 0], ['end_time', '>=', $now] ]); }) ->order(['sort' => 'desc', 'id' => 'desc']); $all = $query->select()->toArray(); // 路径匹配 + 平台筛选(PHP 端处理通配符) $matched = []; foreach ($all as $item) { // 平台筛选 if (!empty($item['target_platform']) && $platform) { $platforms = array_filter(array_map('trim', explode(',', $item['target_platform']))); if (!empty($platforms) && !in_array($platform, $platforms, true)) { continue; } } // 路径匹配 if (!self::pathMatch($item['page_path'], $pagePath)) { continue; } $matched[] = [ 'id' => $item['id'], 'name' => $item['name'], 'popup_type' => $item['popup_type'], 'image' => $item['image'], 'title' => $item['title'], 'content' => $item['content'], 'link_type' => $item['link_type'], 'link_url' => $item['link_url'], 'frequency' => $item['frequency'], 'delay_seconds' => $item['delay_seconds'], 'auto_close_seconds' => $item['auto_close_seconds'] ?? 0, 'is_closable' => $item['is_closable'] ?? 1, 'sort' => $item['sort'], ]; } return $this->data(['lists' => $matched]); } /** * 上报弹窗操作 */ public function report(): Json { $popupId = (int) $this->request->post('popup_id/d', 0); $action = (int) $this->request->post('action/d', 0); $pagePath = (string) $this->request->post('page_path', ''); $deviceId = (string) $this->request->post('device_id', ''); $platform = (string) $this->request->post('platform', ''); if ($popupId <= 0 || !in_array($action, [1, 2, 3], true)) { return $this->fail('参数错误'); } $now = time(); $ip = $this->request->ip() ?: ''; $ua = $this->request->header('user-agent', ''); if (mb_strlen($ua) > 500) $ua = mb_substr($ua, 0, 500); PagePopupLog::insert([ 'popup_id' => $popupId, 'user_id' => $this->userId ?: 0, 'device_id' => $deviceId, 'action' => $action, 'page_path' => $pagePath, 'platform' => $platform, 'ip' => $ip, 'ua' => $ua, 'create_time' => $now, ]); // 冗余统计字段 $field = [1 => 'show_count', 2 => 'click_count', 3 => 'close_count'][$action] ?? ''; if ($field) { PagePopup::where('id', $popupId)->inc($field)->update(); } return $this->data(['ok' => true]); } /** * 路径匹配规则: * - * 匹配所有 * - 末尾 * 表示前缀匹配(/pages/news_detail/*) * - 完全相等 */ private static function pathMatch(string $pattern, string $path): bool { $pattern = trim($pattern); if ($pattern === '' || $pattern === '*') return true; if (substr($pattern, -1) === '*') { $prefix = substr($pattern, 0, -1); return strpos($path, $prefix) === 0; } return $pattern === $path; } }