feat(cloudflare): 完成隧道接入、运维与 P0 体验优化

This commit is contained in:
2026-10-01 11:32:54 +08:00
parent 36d8b1e464
commit 83cc9d504b
48 changed files with 5383 additions and 201 deletions
+35 -2
View File
@@ -43,6 +43,13 @@ import type {
CfTunnelPayload,
CfAppSettings,
CfAppSettingsInput,
CfDriftResult,
CfDiagnosticsResult,
CfAccessStatus,
CfZone,
CfTunnelRoutes,
CfPreflightResult,
CfRouteTestResult,
} from './types'
export function asList<T>(value: T[] | null | undefined): T[] {
@@ -495,20 +502,46 @@ export const api = {
request<CfTunnel>(`/api/cloudflare/tunnels/${id}/stop`, { method: 'POST' }),
restartCfTunnel: (id: number) =>
request<CfTunnel>(`/api/cloudflare/tunnels/${id}/restart`, { method: 'POST' }),
refreshCfCredentials: (id: number) =>
request<CfTunnel>(`/api/cloudflare/tunnels/${id}/credentials/refresh`, { method: 'POST' }),
getCfTunnelStatus: (id: number) =>
request<CfRuntimeStatus>(`/api/cloudflare/tunnels/${id}/status`),
getCfTunnelLogs: (id: number, lines = 200) =>
request<{ output: string }>(`/api/cloudflare/tunnels/${id}/logs?lines=${lines}`),
getCfTunnelConfig: (id: number) =>
request<{ content: string }>(`/api/cloudflare/tunnels/${id}/config`),
getCfTunnelRoutes: (id: number) =>
request<CfTunnelRoutes>(`/api/cloudflare/tunnels/${id}/routes`),
replaceCfTunnelRoutes: (id: number, routes: Array<{ hostname: string; path: string; service: string }>) =>
request<CfTunnelRoutes>(`/api/cloudflare/tunnels/${id}/routes`, {
method: 'PUT',
body: JSON.stringify({ routes }),
}),
getCfTunnelDrift: (id: number) => request<CfDriftResult>(`/api/cloudflare/tunnels/${id}/drift`),
syncCfTunnelRoutes: (id: number) =>
request<{ ok: boolean }>(`/api/cloudflare/tunnels/${id}/sync`, { method: 'POST' }),
getCfTunnelDiagnostics: (id: number) =>
request<CfDiagnosticsResult>(`/api/cloudflare/tunnels/${id}/diagnostics`),
getCfBinary: () => request<{ version: string; mirrors: CfMirror[] }>('/api/cloudflare/binary'),
downloadCfBinary: (mirror: string) =>
downloadCfBinary: (mirror: string, version = '') =>
request<{ ok: boolean; version: string }>('/api/cloudflare/binary/download', {
method: 'POST',
body: JSON.stringify({ mirror }),
body: JSON.stringify({ mirror, version }),
}),
getLatestCfBinary: () => request<{ version: string }>('/api/cloudflare/binary/latest'),
rollbackCfBinary: () =>
request<{ ok: boolean; version: string }>('/api/cloudflare/binary/rollback', { method: 'POST' }),
getCfIngressCandidates: () =>
request<{ hostnames: string[] }>('/api/cloudflare/ingress-candidates'),
getCfZones: () => request<{ zones: CfZone[] }>('/api/cloudflare/zones'),
getCfAccessStatus: (hostname: string) =>
request<CfAccessStatus>(`/api/cloudflare/access-status?hostname=${encodeURIComponent(hostname)}`),
getCfPreflight: () => request<CfPreflightResult>('/api/cloudflare/preflight'),
testCfRoute: (service: string) =>
request<CfRouteTestResult>('/api/cloudflare/routes/test', {
method: 'POST',
body: JSON.stringify({ service }),
}),
getCfSettings: () => request<CfAppSettings>('/api/cloudflare/settings'),
saveCfSettings: (payload: CfAppSettingsInput) =>
request<CfAppSettings>('/api/cloudflare/settings', { method: 'PUT', body: JSON.stringify(payload) }),
+82
View File
@@ -50,6 +50,9 @@ export interface ProxyRule {
name: string
sort_order: number
security: ProxySecurityConfig
exits: string[]
cf_tunnel_id: number
sync_warning?: string
created_at: string
updated_at: string
}
@@ -108,6 +111,8 @@ export interface ProxySavePayload {
enabled?: boolean
name?: string
security?: ProxySecurityPayload
exits?: string[]
cf_tunnel_id?: number
}
export interface AuthStatus {
@@ -165,6 +170,10 @@ export interface DashboardStatus {
mem_total_bytes: number
disk_used_bytes: number
disk_total_bytes: number
cloudflare_count: number
cloudflare_online: number
cloudflare_status: string
cloudflare_message?: string
}
export interface DDNSDomainRecord {
@@ -1024,9 +1033,19 @@ export interface MetricsHistory {
export interface StatusPageRoute {
domain: string
state: string
source?: 'frp' | 'cloudflare' | string
uptime_pct: number
down_minutes: number
unknown_minutes: number
incidents: StatusPageIncident[]
}
export interface StatusPageIncident {
from: string
to?: string
reason?: string
detail?: string
minutes: number
}
export interface StatusPagePayload {
@@ -1064,6 +1083,7 @@ export interface CfTunnel {
last_error?: string
metrics_port?: number
auto_start: boolean
managed: boolean
hostnames?: string[]
origin_service?: string
dns_warning?: string
@@ -1090,6 +1110,11 @@ export interface CfMirror {
base: string
}
export interface CfZone {
id: string
name: string
}
export interface CfTunnelPayload {
name: string
mode: string
@@ -1098,6 +1123,7 @@ export interface CfTunnelPayload {
origin_service?: string
network: CfNetworkSettings
auto_start: boolean
managed: boolean
}
export interface CfAppSettings {
@@ -1119,3 +1145,59 @@ export interface CfAppSettingsInput {
mirror: string
network: CfNetworkSettings
}
export interface CfDriftResult {
tunnel_id: number
managed: boolean
has_drift: boolean
items: string[]
}
export interface CfRouteView {
id?: number
hostname: string
path: string
service: string
source: 'rule' | 'config' | string
}
export interface CfTunnelRoutes {
managed: boolean
routes: CfRouteView[]
catch_all: string
}
export interface CfDiagnosticCheck {
name: string
status: 'ok' | 'warning' | 'error' | string
message: string
}
export interface CfDiagnosticsResult {
tunnel_id: number
generated_at: string
checks: CfDiagnosticCheck[]
}
export interface CfPreflightCheck {
name: string
status: 'ok' | 'error' | string
message: string
action?: string
}
export interface CfPreflightResult {
ready: boolean
checks: CfPreflightCheck[]
}
export interface CfRouteTestResult {
ok: boolean
message: string
latency_ms: number
}
export interface CfAccessStatus {
enabled: boolean
name?: string
}