Pārlūkot izejas kodu

埋点系统的信息统计接口更新等操作

liuchengsen 4 nedēļas atpakaļ
vecāks
revīzija
6359cae926

+ 8 - 16
backend-java/src/main/java/com/pharmacopoeia/repository/UserEventRepository.java

@@ -16,56 +16,48 @@ public interface UserEventRepository extends JpaRepository<UserEvent, Long>,
 
 
     /** 总数 */
     /** 总数 */
     @Query("SELECT COUNT(e) FROM UserEvent e " +
     @Query("SELECT COUNT(e) FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime)")
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime")
     long countTotal(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     long countTotal(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 去重活跃用户数 */
     /** 去重活跃用户数 */
     @Query("SELECT COUNT(DISTINCT e.userKey) FROM UserEvent e " +
     @Query("SELECT COUNT(DISTINCT e.userKey) FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime)")
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime")
     long countDistinctUsers(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     long countDistinctUsers(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 按类型统计数量 */
     /** 按类型统计数量 */
     @Query("SELECT COUNT(e) FROM UserEvent e " +
     @Query("SELECT COUNT(e) FROM UserEvent e " +
            "WHERE e.eventType = :eventType " +
            "WHERE e.eventType = :eventType " +
-           "AND (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime)")
+           "AND e.createdAt >= :startTime AND e.createdAt < :endTime")
     long countByType(@Param("eventType") String eventType,
     long countByType(@Param("eventType") String eventType,
                      @Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
                      @Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 按 IP 分组统计 */
     /** 按 IP 分组统计 */
     @Query("SELECT e.ip as key, COUNT(e) as cnt FROM UserEvent e " +
     @Query("SELECT e.ip as key, COUNT(e) as cnt FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime) " +
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime " +
            "GROUP BY e.ip ORDER BY cnt DESC")
            "GROUP BY e.ip ORDER BY cnt DESC")
     List<Object[]> countByIp(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     List<Object[]> countByIp(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 按 page_url 分组统计 */
     /** 按 page_url 分组统计 */
     @Query("SELECT e.pageUrl as key, COUNT(e) as cnt FROM UserEvent e " +
     @Query("SELECT e.pageUrl as key, COUNT(e) as cnt FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime) " +
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime " +
            "GROUP BY e.pageUrl ORDER BY cnt DESC")
            "GROUP BY e.pageUrl ORDER BY cnt DESC")
     List<Object[]> countByPageUrl(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     List<Object[]> countByPageUrl(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 按 event_type 分组统计 */
     /** 按 event_type 分组统计 */
     @Query("SELECT e.eventType as key, COUNT(e) as cnt FROM UserEvent e " +
     @Query("SELECT e.eventType as key, COUNT(e) as cnt FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime) " +
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime " +
            "GROUP BY e.eventType ORDER BY cnt DESC")
            "GROUP BY e.eventType ORDER BY cnt DESC")
     List<Object[]> countByEventType(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     List<Object[]> countByEventType(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 按 user_key 分组统计(去重用户) */
     /** 按 user_key 分组统计(去重用户) */
     @Query("SELECT e.userKey as key, COUNT(e) as cnt FROM UserEvent e " +
     @Query("SELECT e.userKey as key, COUNT(e) as cnt FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime) " +
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime " +
            "GROUP BY e.userKey ORDER BY cnt DESC")
            "GROUP BY e.userKey ORDER BY cnt DESC")
     List<Object[]> countByUserKey(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     List<Object[]> countByUserKey(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 
 
     /** 用户+IP 混合维度:每个用户关联的 IP 列表 */
     /** 用户+IP 混合维度:每个用户关联的 IP 列表 */
     @Query("SELECT e.userKey, e.ip, COUNT(e) as cnt FROM UserEvent e " +
     @Query("SELECT e.userKey, e.ip, COUNT(e) as cnt FROM UserEvent e " +
-           "WHERE (:startTime IS NULL OR e.createdAt >= :startTime) " +
-           "AND (:endTime IS NULL OR e.createdAt < :endTime) " +
+           "WHERE e.createdAt >= :startTime AND e.createdAt < :endTime " +
            "GROUP BY e.userKey, e.ip ORDER BY e.userKey, cnt DESC")
            "GROUP BY e.userKey, e.ip ORDER BY e.userKey, cnt DESC")
     List<Object[]> countByUserIp(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
     List<Object[]> countByUserIp(@Param("startTime") Instant startTime, @Param("endTime") Instant endTime);
 }
 }

+ 2 - 2
backend-java/src/main/java/com/pharmacopoeia/service/AnalyticsService.java

@@ -54,7 +54,7 @@ public class AnalyticsService {
     /** 列表(精简字段,不含 event_data / page_url / referrer / user_agent) */
     /** 列表(精简字段,不含 event_data / page_url / referrer / user_agent) */
     public Map<String, Object> queryEvents(String eventType, String startDate, String endDate,
     public Map<String, Object> queryEvents(String eventType, String startDate, String endDate,
                                            int page, int pageSize) {
                                            int page, int pageSize) {
-        Instant startTime = parseDate(startDate);
+        Instant startTime = parseDate(startDate) != null ? parseDate(startDate) : Instant.EPOCH;
         Instant endTime = endDate != null && !endDate.isBlank()
         Instant endTime = endDate != null && !endDate.isBlank()
                 ? LocalDate.parse(endDate).plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant()
                 ? LocalDate.parse(endDate).plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant()
                 : Instant.parse("2099-12-31T23:59:59Z");
                 : Instant.parse("2099-12-31T23:59:59Z");
@@ -163,7 +163,7 @@ public class AnalyticsService {
      *  如果日期都不传,调用方默认填了当天 */
      *  如果日期都不传,调用方默认填了当天 */
     public Map<String, Object> queryStats(String startDate, String endDate, String dimension,
     public Map<String, Object> queryStats(String startDate, String endDate, String dimension,
                                           String range) {
                                           String range) {
-        Instant startTime = parseDate(startDate);
+        Instant startTime = parseDate(startDate) != null ? parseDate(startDate) : Instant.EPOCH;
         Instant endTime = endDate != null && !endDate.isBlank()
         Instant endTime = endDate != null && !endDate.isBlank()
                 ? LocalDate.parse(endDate).plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant()
                 ? LocalDate.parse(endDate).plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant()
                 : Instant.parse("2099-12-31T23:59:59Z");
                 : Instant.parse("2099-12-31T23:59:59Z");

+ 3 - 1
static/index.html

@@ -190,7 +190,9 @@
   // 用户行为埋点(fire-and-forget,不影响主流程)
   // 用户行为埋点(fire-and-forget,不影响主流程)
   // ============================================================
   // ============================================================
   function track(type, data){
   function track(type, data){
-    var payload = {event_type: type, event_data: data || {}, page_url: window.location.href};
+    var merged = data || {};
+    merged.source = 'ai_pharmacopoeia';
+    var payload = {event_type: type, event_data: merged, page_url: window.location.href};
     var h = {'Content-Type': 'application/json'};
     var h = {'Content-Type': 'application/json'};
     if (TOKEN) h['Authorization'] = 'Bearer ' + TOKEN;
     if (TOKEN) h['Authorization'] = 'Bearer ' + TOKEN;
     try {
     try {