AnalyticsController.java 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package com.pharmacopoeia.controller;
  2. import com.pharmacopoeia.dto.ApiResponse;
  3. import com.pharmacopoeia.service.AnalyticsService;
  4. import com.pharmacopoeia.util.IpUtils;
  5. import jakarta.servlet.http.HttpServletRequest;
  6. import org.springframework.http.ResponseEntity;
  7. import org.springframework.web.bind.annotation.*;
  8. import java.util.Map;
  9. @RestController
  10. @RequestMapping("/api/v1/analytics")
  11. public class AnalyticsController {
  12. private final AnalyticsService analyticsService;
  13. private final HttpServletRequest request;
  14. public AnalyticsController(AnalyticsService analyticsService, HttpServletRequest request) {
  15. this.analyticsService = analyticsService;
  16. this.request = request;
  17. }
  18. // ==================== 事件 ====================
  19. @GetMapping("/events")
  20. public ResponseEntity<ApiResponse<Map<String, Object>>> queryEvents(
  21. @RequestParam(required = false) String eventType,
  22. @RequestParam(required = false) String startDate,
  23. @RequestParam(required = false) String endDate,
  24. @RequestParam(defaultValue = "1") int page,
  25. @RequestParam(defaultValue = "20") int pageSize) {
  26. return ResponseEntity.ok(ApiResponse.success(
  27. analyticsService.queryEvents(eventType, startDate, endDate, page, pageSize)));
  28. }
  29. @GetMapping("/events/{id}")
  30. public ResponseEntity<ApiResponse<Map<String, Object>>> getEventDetail(@PathVariable long id) {
  31. var detail = analyticsService.getEventDetail(id);
  32. if (detail.isEmpty()) {
  33. return ResponseEntity.ok(ApiResponse.<Map<String, Object>>builder().code(404).message("事件不存在").build());
  34. }
  35. return ResponseEntity.ok(ApiResponse.success(detail));
  36. }
  37. @PostMapping("/events")
  38. public ResponseEntity<ApiResponse<Map<String, String>>> saveEvent(@RequestBody Map<String, Object> body) {
  39. String eventType = (String) body.getOrDefault("event_type", "unknown");
  40. @SuppressWarnings("unchecked")
  41. Map<String, Object> eventData = body.get("event_data") instanceof Map
  42. ? (Map<String, Object>) body.get("event_data") : Map.of();
  43. String pageUrl = (String) body.getOrDefault("page_url", "");
  44. String referrer = (String) body.getOrDefault("referrer", "");
  45. String userKey = getCurrentUserKey();
  46. String ip = IpUtils.getClientIp(request);
  47. String ua = request.getHeader("User-Agent");
  48. analyticsService.saveEvent(userKey, eventType, eventData, pageUrl, referrer,
  49. ip, ua != null ? ua : "");
  50. return ResponseEntity.accepted()
  51. .body(ApiResponse.<Map<String, String>>builder().code(202).message("accepted")
  52. .data(Map.of("status", "accepted")).build());
  53. }
  54. // ==================== 概览 ====================
  55. /** 概览数字:total_events / active_users / page_views / searches / ai_qa */
  56. @GetMapping("/stats/overview")
  57. public ResponseEntity<ApiResponse<Map<String, Object>>> queryOverview(
  58. @RequestParam(required = false) String range) {
  59. if (range == null || range.isBlank()) {
  60. range = "total";
  61. }
  62. return ResponseEntity.ok(ApiResponse.success(analyticsService.queryOverview(range)));
  63. }
  64. // ==================== 维度 ====================
  65. /** 分页维度统计:dimension=ip/url/type/user/user_ip */
  66. @GetMapping("/stats/dimension")
  67. public ResponseEntity<ApiResponse<Map<String, Object>>> queryDimension(
  68. @RequestParam String dimension,
  69. @RequestParam(required = false) String startDate,
  70. @RequestParam(required = false) String endDate,
  71. @RequestParam(defaultValue = "1") int page,
  72. @RequestParam(defaultValue = "20") int pageSize) {
  73. return ResponseEntity.ok(ApiResponse.success(
  74. analyticsService.queryDimension(dimension, startDate, endDate, page, pageSize)));
  75. }
  76. private String getCurrentUserKey() {
  77. var auth = org.springframework.security.core.context.SecurityContextHolder
  78. .getContext().getAuthentication();
  79. if (auth != null && auth.isAuthenticated()
  80. && !"anonymousUser".equals(auth.getPrincipal())) {
  81. return auth.getName();
  82. }
  83. return "anonymous";
  84. }
  85. }