init ana page with apis

This commit is contained in:
2025-03-21 12:08:37 +08:00
commit 271230fca7
71 changed files with 15699 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import { executeQuerySingle } from '@/lib/clickhouse';
import { StatsOverview } from '../types';
/**
* Get overview statistics for links
*/
export async function findStatsOverview(): Promise<StatsOverview | null> {
const query = `
WITH
toUInt64(count()) as total_links,
toUInt64(countIf(is_active = true)) as active_links
FROM links
SELECT
total_links as totalLinks,
active_links as activeLinks,
(SELECT count() FROM link_events) as totalVisits,
(SELECT count() FROM link_events) / NULLIF(total_links, 0) as conversionRate
`;
return await executeQuerySingle<StatsOverview>(query);
}

15
app/api/stats/route.ts Normal file
View File

@@ -0,0 +1,15 @@
import { NextResponse } from 'next/server';
import { getStatsOverview } from './service';
export async function GET() {
try {
const stats = await getStatsOverview();
return NextResponse.json(stats);
} catch (error) {
console.error('获取统计概览失败:', error);
return NextResponse.json(
{ error: '获取统计概览失败', message: (error as Error).message },
{ status: 500 }
);
}
}

21
app/api/stats/service.ts Normal file
View File

@@ -0,0 +1,21 @@
import { StatsOverview } from '../types';
import { findStatsOverview } from './repository';
/**
* Get link statistics overview
*/
export async function getStatsOverview(): Promise<StatsOverview> {
const stats = await findStatsOverview();
// Return default values if no data
if (!stats) {
return {
totalLinks: 0,
activeLinks: 0,
totalVisits: 0,
conversionRate: 0
};
}
return stats;
}