|
|
@@ -0,0 +1,55 @@
|
|
|
+package com.pharmacopoeia.controller;
|
|
|
+
|
|
|
+import com.pharmacopoeia.service.AnalyticsService;
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/api/v1/analytics")
|
|
|
+public class AnalyticsController {
|
|
|
+
|
|
|
+ private final AnalyticsService analyticsService;
|
|
|
+ private final HttpServletRequest request;
|
|
|
+
|
|
|
+ public AnalyticsController(AnalyticsService analyticsService, HttpServletRequest request) {
|
|
|
+ this.analyticsService = analyticsService;
|
|
|
+ this.request = request;
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/events")
|
|
|
+ public ResponseEntity<Map<String, String>> saveEvent(@RequestBody Map<String, Object> body) {
|
|
|
+ String eventType = (String) body.getOrDefault("event_type", "unknown");
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, Object> eventData = body.get("event_data") instanceof Map
|
|
|
+ ? (Map<String, Object>) body.get("event_data") : Map.of();
|
|
|
+ String pageUrl = (String) body.getOrDefault("page_url", "");
|
|
|
+ String referrer = (String) body.getOrDefault("referrer", "");
|
|
|
+
|
|
|
+ String userKey = getCurrentUserKey();
|
|
|
+ String ip = request.getRemoteAddr();
|
|
|
+ String forwarded = request.getHeader("X-Forwarded-For");
|
|
|
+ if (forwarded != null && !forwarded.isBlank()) {
|
|
|
+ ip = forwarded.split(",")[0].trim();
|
|
|
+ }
|
|
|
+ String ua = request.getHeader("User-Agent");
|
|
|
+
|
|
|
+ // fire-and-forget:异步写入,不等待
|
|
|
+ analyticsService.saveEvent(userKey, eventType, eventData, pageUrl, referrer,
|
|
|
+ ip, ua != null ? ua : "");
|
|
|
+
|
|
|
+ // 始终返回 202,前端不关心结果
|
|
|
+ return ResponseEntity.accepted().body(Map.of("status", "accepted"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getCurrentUserKey() {
|
|
|
+ var auth = org.springframework.security.core.context.SecurityContextHolder
|
|
|
+ .getContext().getAuthentication();
|
|
|
+ if (auth != null && auth.isAuthenticated() && !"anonymousUser".equals(auth.getPrincipal())) {
|
|
|
+ return auth.getName();
|
|
|
+ }
|
|
|
+ return "anonymous";
|
|
|
+ }
|
|
|
+}
|