links search

This commit is contained in:
2025-03-31 16:46:33 +08:00
parent d75110d6b8
commit e7b3b735e0
11 changed files with 689 additions and 303 deletions

View File

@@ -2,23 +2,12 @@
import { useEffect } from 'react';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
export default function SwaggerPage() {
useEffect(() => {
// 设置页面标题
document.title = 'API Documentation - ShortURL Analytics';
// 动态添加Swagger UI CSS
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'https://unpkg.com/swagger-ui-dist@5.20.1/swagger-ui.css';
document.head.appendChild(link);
// 清理函数
return () => {
document.head.removeChild(link);
};
}, []);
// Swagger配置
@@ -222,27 +211,93 @@ export default function SwaggerPage() {
get: {
tags: ['events'],
summary: 'Get events',
description: 'Retrieve events within a specified time range with pagination support',
description: 'Retrieve events with pagination and filtering support. If startTime and endTime are not provided, will return the most recent events.',
parameters: [
{
name: 'startTime',
in: 'query',
required: true,
required: false,
schema: {
type: 'string',
format: 'date-time',
},
description: 'Start time for events query (ISO 8601 format)',
description: 'Start time for events query (ISO 8601 format). If not provided, no lower time bound will be applied.',
},
{
name: 'endTime',
in: 'query',
required: true,
required: false,
schema: {
type: 'string',
format: 'date-time',
},
description: 'End time for events query (ISO 8601 format)',
description: 'End time for events query (ISO 8601 format). If not provided, no upper time bound will be applied.',
},
{
name: 'eventType',
in: 'query',
schema: {
type: 'string',
enum: ['click', 'redirect', 'conversion', 'error']
},
description: 'Filter events by type',
},
{
name: 'linkId',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by link ID',
},
{
name: 'linkSlug',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by link slug',
},
{
name: 'userId',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by user ID',
},
{
name: 'teamId',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by team ID',
},
{
name: 'projectId',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by project ID',
},
{
name: 'tags',
in: 'query',
schema: {
type: 'string'
},
description: 'Filter events by tags (comma-separated list)',
example: 'promo,vip,summer'
},
{
name: 'searchSlug',
in: 'query',
schema: {
type: 'string'
},
description: 'Search events by partial link slug match',
},
{
name: 'page',
@@ -259,12 +314,31 @@ export default function SwaggerPage() {
in: 'query',
schema: {
type: 'integer',
default: 50,
default: 20,
minimum: 1,
maximum: 100,
},
description: 'Number of items per page',
},
{
name: 'sortBy',
in: 'query',
schema: {
type: 'string',
enum: ['event_time', 'event_type', 'link_slug', 'conversion_value']
},
description: 'Field to sort by',
},
{
name: 'sortOrder',
in: 'query',
schema: {
type: 'string',
enum: ['asc', 'desc'],
default: 'desc'
},
description: 'Sort order',
}
],
responses: {
'200': {
@@ -274,31 +348,116 @@ export default function SwaggerPage() {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true
},
data: {
type: 'array',
items: {
$ref: '#/components/schemas/Event',
},
$ref: '#/components/schemas/Event'
}
},
pagination: {
$ref: '#/components/schemas/Pagination',
},
},
meta: {
type: 'object',
properties: {
total: {
type: 'number',
description: 'Total number of events matching the filters'
},
page: {
type: 'number',
description: 'Current page number'
},
pageSize: {
type: 'number',
description: 'Number of items per page'
},
filters: {
type: 'object',
properties: {
tags: {
type: 'array',
items: {
type: 'string'
},
description: 'Applied tag filters'
},
teamId: {
type: 'string',
description: 'Applied team filter'
},
projectId: {
type: 'string',
description: 'Applied project filter'
},
searchSlug: {
type: 'string',
description: 'Applied slug search term'
}
}
}
}
}
}
},
},
},
example: {
success: true,
data: [
{
event_id: '123e4567-e89b-12d3-a456-426614174000',
event_time: '2024-03-31T10:00:00.000Z',
event_type: 'click',
link_slug: 'summer-promo',
link_tags: ['promo', 'summer'],
team_id: 'team1',
project_id: 'proj1'
}
],
meta: {
total: 150,
page: 1,
pageSize: 20,
filters: {
tags: ['promo', 'summer'],
teamId: 'team1',
projectId: 'proj1',
searchSlug: 'summer'
}
}
}
}
}
},
'400': {
description: 'Bad request',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Error',
$ref: '#/components/schemas/Error'
},
},
},
example: {
success: false,
error: 'Invalid tags format'
}
}
}
},
},
'500': {
description: 'Server error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Error'
},
example: {
success: false,
error: 'Internal server error'
}
}
}
}
}
},
},
'/events/summary': {
@@ -526,6 +685,74 @@ export default function SwaggerPage() {
},
},
},
'/events/tags': {
get: {
tags: ['events'],
summary: '获取标签列表',
description: '获取所有事件中的唯一标签列表。如果提供了 teamId则只返回该团队的标签。',
parameters: [
{
name: 'teamId',
in: 'query',
required: false,
schema: {
type: 'string',
},
description: '团队ID可选。如果提供则只返回该团队的标签。',
},
],
responses: {
'200': {
description: '成功获取标签列表',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true,
},
data: {
type: 'array',
items: {
type: 'object',
properties: {
tag_name: {
type: 'string',
example: 'marketing',
},
},
},
},
},
},
},
},
},
'500': {
description: '服务器错误',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false,
},
error: {
type: 'string',
example: 'Failed to fetch tags',
},
},
},
},
},
},
},
},
},
},
components: {
schemas: {