diff --git a/app/api/types.ts b/app/api/types.ts index 25c6223..ce7e665 100644 --- a/app/api/types.ts +++ b/app/api/types.ts @@ -1,29 +1,87 @@ // Event Types export interface Event { - id: string; - time: string; - type: string; - linkInfo: { + // 核心事件信息 + event_id: string; + event_time: string; + event_type: string; + event_attributes: string; + + // 链接信息 + link_id: string; + link_slug: string; + link_label: string; + link_title: string; + link_original_url: string; + link_attributes: string; + link_created_at: string; + link_expires_at: string | null; + link_tags: string; + + // 用户信息 + user_id: string; + user_name: string; + user_email: string; + user_attributes: string; + + // 团队信息 + team_id: string; + team_name: string; + team_attributes: string; + + // 项目信息 + project_id: string; + project_name: string; + project_attributes: string; + + // 二维码信息 + qr_code_id: string; + qr_code_name: string; + qr_code_attributes: string; + + // 访问者信息 + visitor_id: string; + session_id: string; + ip_address: string; + country: string; + city: string; + device_type: string; + browser: string; + os: string; + user_agent: string; + + // 来源信息 + referrer: string; + utm_source: string; + utm_medium: string; + utm_campaign: string; + + // 交互信息 + time_spent_sec: number; + is_bounce: boolean; + is_qr_scan: boolean; + conversion_type: string; + conversion_value: number; + + // 旧接口兼容字段 + id?: string; + time?: string; + type?: string; + linkInfo?: { id: string; shortUrl: string; originalUrl: string; }; - visitor: { + visitor?: { id: string; browser: string; os: string; device: string; }; - location: { + location?: { country: string; region: string; city: string; }; - referrer: string; - conversion?: { - type: string; - value: number; - }; } // Analytics Types diff --git a/app/events/page.tsx b/app/events/page.tsx index be07dea..90feabf 100644 --- a/app/events/page.tsx +++ b/app/events/page.tsx @@ -1,14 +1,14 @@ "use client"; -import { useState, useEffect, useRef } from 'react'; -import { addDays, format } from 'date-fns'; +import { useState, useEffect } from 'react'; +import { format } from 'date-fns'; import { DateRangePicker } from '../components/ui/DateRangePicker'; -import { Event, EventFilters } from '../api/types'; +import { Event } from '../api/types'; export default function EventsPage() { const [dateRange, setDateRange] = useState({ - from: addDays(new Date(), -7), - to: new Date() + from: new Date('2024-02-01'), + to: new Date('2025-03-05') }); const [loading, setLoading] = useState(true); @@ -22,7 +22,7 @@ export default function EventsPage() { linkSlug: '' }); - const [filters, setFilters] = useState({ + const [filters, setFilters] = useState({ startTime: format(new Date('2024-02-01'), "yyyy-MM-dd'T'HH:mm:ss'Z'"), endTime: format(new Date('2025-03-05'), "yyyy-MM-dd'T'HH:mm:ss'Z'"), page: 1, @@ -30,8 +30,6 @@ export default function EventsPage() { }); const [summary, setSummary] = useState(null); - const observerRef = useRef(null); - const lastEventRef = useRef(null); const fetchEvents = async (pageNum: number) => { try { @@ -56,15 +54,19 @@ export default function EventsPage() { throw new Error(data.error || 'Failed to fetch events'); } + const eventsData = data.data || data.events || []; + if (pageNum === 1) { - setEvents(data.events); + setEvents(eventsData); } else { - setEvents(prev => [...prev, ...data.events]); + setEvents(prev => [...prev, ...eventsData]); } - setHasMore(data.events.length === 50); + setHasMore(Array.isArray(eventsData) && eventsData.length === 50); } catch (err) { + console.error("Error fetching events:", err); setError(err instanceof Error ? err.message : 'An error occurred while fetching events'); + setEvents([]); } finally { setLoading(false); } @@ -174,42 +176,53 @@ export default function EventsPage() { Referrer + + Conversion + - {events.map((event, index) => ( - + {Array.isArray(events) && events.map((event, index) => ( + - {formatDate(event.time)} + {event.event_time && formatDate(event.event_time)} - {event.type} + {event.event_type || 'unknown'}
-
{event.linkInfo.shortUrl}
-
{event.linkInfo.originalUrl}
+
{event.link_slug || '-'}
+
{event.link_original_url || '-'}
-
{event.visitor.browser}
-
{event.visitor.os} / {event.visitor.device}
+
{event.browser || '-'}
+
{event.os || '-'} / {event.device_type || '-'}
-
{event.location.city}
-
{event.location.region}, {event.location.country}
+
{event.city || '-'}
+
{event.country || '-'}
{event.referrer || '-'} + +
+
{event.conversion_type || '-'}
+ {event.conversion_value > 0 && ( +
Value: {event.conversion_value}
+ )} +
+ ))} @@ -233,7 +246,7 @@ export default function EventsPage() { )} - {!loading && events.length === 0 && ( + {!loading && Array.isArray(events) && events.length === 0 && (
No events found