183 lines
4.9 KiB
TypeScript
183 lines
4.9 KiB
TypeScript
import { fetchWithAuth } from "./client";
|
|
|
|
// ── 类型定义 ────────────────────────────────────────────────────────────────────
|
|
|
|
export interface PublishRecordCreate {
|
|
content_title: string;
|
|
content_id?: string;
|
|
platform: string;
|
|
published_url?: string;
|
|
status?: string;
|
|
published_at?: string;
|
|
}
|
|
|
|
export interface PublishRecordResponse {
|
|
id: string;
|
|
organization_id: string;
|
|
content_title: string;
|
|
content_id: string | null;
|
|
platform: string;
|
|
published_url: string | null;
|
|
status: string;
|
|
published_at: string | null;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface MetricsUpdateRequest {
|
|
views?: number;
|
|
likes?: number;
|
|
comments?: number;
|
|
shares?: number;
|
|
bookmarks?: number;
|
|
ai_citation_count?: number;
|
|
search_impressions?: number;
|
|
search_clicks?: number;
|
|
avg_read_duration?: number;
|
|
read_completion_rate?: number;
|
|
}
|
|
|
|
export interface MetricsResponse {
|
|
id: string;
|
|
publish_record_id: string;
|
|
recorded_at: string;
|
|
views: number;
|
|
likes: number;
|
|
comments: number;
|
|
shares: number;
|
|
bookmarks: number;
|
|
ai_citation_count: number;
|
|
search_impressions: number;
|
|
search_clicks: number;
|
|
avg_read_duration: number;
|
|
read_completion_rate: number;
|
|
}
|
|
|
|
export interface OverviewStatsResponse {
|
|
total_published: number;
|
|
total_views: number;
|
|
total_interactions: number;
|
|
total_ai_citations: number;
|
|
avg_engagement_rate: number;
|
|
platform_distribution: Record<string, number>;
|
|
}
|
|
|
|
export interface ContentPerformanceResponse {
|
|
id: string;
|
|
content_title: string;
|
|
platform: string;
|
|
published_url: string | null;
|
|
status: string;
|
|
published_at: string | null;
|
|
latest_metrics: Record<string, unknown> | null;
|
|
metrics_history: Record<string, unknown>[];
|
|
}
|
|
|
|
export interface TopContentItem {
|
|
publish_record_id: string;
|
|
content_title: string;
|
|
platform: string;
|
|
published_url: string | null;
|
|
views: number;
|
|
likes: number;
|
|
comments: number;
|
|
shares: number;
|
|
bookmarks: number;
|
|
ai_citation_count: number;
|
|
search_impressions: number;
|
|
search_clicks: number;
|
|
avg_read_duration: number;
|
|
read_completion_rate: number;
|
|
recorded_at: string | null;
|
|
}
|
|
|
|
export interface TopContentResponse {
|
|
items: TopContentItem[];
|
|
sort_by: string;
|
|
total: number;
|
|
}
|
|
|
|
export interface InsightResponse {
|
|
id: string;
|
|
organization_id: string;
|
|
content_id: string | null;
|
|
insight_type: string;
|
|
title: string;
|
|
description: string;
|
|
recommendation: string;
|
|
severity: string;
|
|
applied: boolean;
|
|
created_at: string;
|
|
}
|
|
|
|
// ── API ────────────────────────────────────────────────────────────────────────
|
|
|
|
export const analyticsApi = {
|
|
getOverview: (token?: string) =>
|
|
fetchWithAuth("/api/v1/analytics/overview", {}, token) as Promise<OverviewStatsResponse>,
|
|
|
|
getTopContent: (
|
|
token?: string,
|
|
params?: { sort_by?: string; limit?: number }
|
|
) => {
|
|
const query = new URLSearchParams();
|
|
if (params?.sort_by) query.set("sort_by", params.sort_by);
|
|
if (params?.limit !== undefined) query.set("limit", String(params.limit));
|
|
const qs = query.toString();
|
|
return fetchWithAuth(
|
|
`/api/v1/analytics/top${qs ? `?${qs}` : ""}`,
|
|
{},
|
|
token
|
|
) as Promise<TopContentResponse>;
|
|
},
|
|
|
|
getContentPerformance: (token?: string, publishId?: string) =>
|
|
fetchWithAuth(
|
|
`/api/v1/analytics/content/${publishId}`,
|
|
{},
|
|
token
|
|
) as Promise<ContentPerformanceResponse>,
|
|
|
|
getInsights: (
|
|
token?: string,
|
|
params?: { limit?: number; insight_type?: string }
|
|
) => {
|
|
const query = new URLSearchParams();
|
|
if (params?.limit !== undefined) query.set("limit", String(params.limit));
|
|
if (params?.insight_type) query.set("insight_type", params.insight_type);
|
|
const qs = query.toString();
|
|
return fetchWithAuth(
|
|
`/api/v1/analytics/insights${qs ? `?${qs}` : ""}`,
|
|
{},
|
|
token
|
|
) as Promise<InsightResponse[]>;
|
|
},
|
|
|
|
generateInsights: (token?: string) =>
|
|
fetchWithAuth(
|
|
"/api/v1/analytics/insights/generate",
|
|
{ method: "POST" },
|
|
token
|
|
) as Promise<Record<string, unknown>[]>,
|
|
|
|
applyInsight: (token?: string, insightId?: string) =>
|
|
fetchWithAuth(
|
|
`/api/v1/analytics/insights/${insightId}/apply`,
|
|
{ method: "POST" },
|
|
token
|
|
) as Promise<InsightResponse>,
|
|
|
|
recordPublish: (token?: string, data?: PublishRecordCreate) =>
|
|
fetchWithAuth(
|
|
"/api/v1/analytics/publish",
|
|
{ method: "POST", body: JSON.stringify(data) },
|
|
token
|
|
) as Promise<PublishRecordResponse>,
|
|
|
|
updateMetrics: (token?: string, publishId?: string, data?: MetricsUpdateRequest) =>
|
|
fetchWithAuth(
|
|
`/api/v1/analytics/metrics/${publishId}`,
|
|
{ method: "PUT", body: JSON.stringify(data) },
|
|
token
|
|
) as Promise<MetricsResponse>,
|
|
};
|