import { NextRequest, NextResponse } from 'next/server'; import type { ApiResponse } from '@/lib/types'; import { executeQuery } from '@/lib/clickhouse'; export async function GET(request: NextRequest) { try { // 获取查询参数 const searchParams = request.nextUrl.searchParams; const startTime = searchParams.get('startTime'); const endTime = searchParams.get('endTime'); const linkId = searchParams.get('linkId'); if (!startTime || !endTime || !linkId) { return NextResponse.json({ success: false, error: 'Missing required parameters' }, { status: 400 }); } // 查询链接的点击事件 const query = ` SELECT event_attributes FROM events WHERE link_id = '${linkId}' AND event_time >= parseDateTimeBestEffort('${startTime}') AND event_time <= parseDateTimeBestEffort('${endTime}') AND event_type = 'click' `; const events = await executeQuery(query); // 处理事件数据,按路径分组 const pathMap = new Map(); let totalClicks = 0; events.forEach((event: any) => { try { if (event.event_attributes) { const attrs = JSON.parse(event.event_attributes); if (attrs.full_url) { // 提取URL的路径和参数部分 const url = new URL(attrs.full_url); const pathWithParams = url.pathname + (url.search || ''); // 更新路径计数 const currentCount = pathMap.get(pathWithParams) || 0; pathMap.set(pathWithParams, currentCount + 1); totalClicks++; } } } catch (error) { // 忽略解析错误 } }); // 转换为数组并按点击数排序 const pathData = Array.from(pathMap.entries()) .map(([path, count]) => ({ path, count, percentage: totalClicks > 0 ? count / totalClicks : 0, })) .sort((a, b) => b.count - a.count); const response: ApiResponse = { success: true, data: pathData, meta: { total: totalClicks } }; return NextResponse.json(response); } catch (error) { console.error('Error fetching path analytics data:', error); const response: ApiResponse = { success: false, error: error instanceof Error ? error.message : 'Internal server error' }; return NextResponse.json(response, { status: 500 }); } }