feat(zone): add Cloudflare-style traffic overview charts

Expose Zone stats API with multi-host access-log aggregates and time
series, and render unique visitors, requests and data served on the
Zone overview with 24h/7d/30d range controls.
This commit is contained in:
ryan
2026-07-12 16:38:35 +08:00
parent efcf61e32d
commit 31b4886a14
20 changed files with 1026 additions and 32 deletions
+3
View File
@@ -108,6 +108,9 @@ export type {
ZoneItem,
ZoneMutationPayload,
ZoneOverview,
ZoneStats,
ZoneStatsPoint,
ZoneStatsRange,
TlsCertificateApplyPayload,
TlsCertificateContentItem,
TlsCertificateDetailItem,
+23
View File
@@ -988,6 +988,29 @@ export interface ZoneOverview {
domains: ZoneDomainItem[];
}
export type ZoneStatsRange = '24h' | '7d' | '30d';
export interface ZoneStatsPoint {
bucket_started_at: string;
request_count: number;
unique_visitors: number;
bytes_sent: number;
}
export interface ZoneStats {
range: ZoneStatsRange;
range_hours: number;
window_started_at: string;
window_ended_at: string;
bucket_minutes: number;
unique_visitors: number;
request_count: number;
bytes_sent: number;
domain_count: number;
available: boolean;
series: ZoneStatsPoint[];
}
@@ -1,5 +1,13 @@
import {OpenFlareBaseService} from './base.service'
import type {ZoneDomainItem, ZoneDomainMutationPayload, ZoneItem, ZoneMutationPayload, ZoneOverview} from './types'
import type {
ZoneDomainItem,
ZoneDomainMutationPayload,
ZoneItem,
ZoneMutationPayload,
ZoneOverview,
ZoneStats,
ZoneStatsRange,
} from './types'
export const zoneQueryKey = ['openflare', 'zones'] as const
@@ -8,6 +16,9 @@ export class ZoneService extends OpenFlareBaseService {
static list(): Promise<ZoneItem[]> { return this.get<ZoneItem[]>('/') }
static getOverview(id: number): Promise<ZoneOverview> { return this.get<ZoneOverview>(`/${id}/overview`) }
static getStats(id: number, range: ZoneStatsRange = '24h'): Promise<ZoneStats> {
return this.get<ZoneStats>(`/${id}/stats`, {range})
}
static create(payload: ZoneMutationPayload): Promise<ZoneItem> { return this.post<ZoneItem>('/', payload) }
static update(id: number, payload: ZoneMutationPayload): Promise<ZoneItem> { return this.post<ZoneItem>(`/${id}/update`, payload) }
static deleteById(id: number): Promise<void> { return this.post<void>(`/${id}/delete`) }