Compare commits

..

1 Commits

Author SHA1 Message Date
fatedier
ad5ebc0017 Add frps proxy traffic API v2 2026-07-08 01:46:37 +08:00
5 changed files with 41 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
## Features
* Expanded the frps dashboard API v2 migration across Clients, Proxies, Server Overview, Client Detail, and Proxy Detail, covering paginated users/clients/proxies, detail data, proxy traffic history, server system info, offline proxy statistics pruning, server-side pagination, search, and proxy type filtering.
* Added dashboard API v2 pagination endpoints for users, clients, and proxies.
* The frps dashboard Clients and Proxies pages now use API v2 pagination and server-side search, including proxy type filtering and searchable proxy spec fields such as remote ports, custom domains, and subdomains.
## Fixes

View File

@@ -49,7 +49,7 @@ export const toLegacyProxyStats = (proxy: ProxyV2Info): ProxyStatsInfo => ({
curConns: proxy.status.curConns,
lastStartTime: proxy.status.lastStartTime,
lastCloseTime: proxy.status.lastCloseTime,
status: proxy.status.phase,
status: proxy.status.state || proxy.status.phase || '',
})
export const getProxy = (type: string, name: string) => {

View File

@@ -7,6 +7,7 @@ export interface ClientInfoData {
wireProtocol?: string
hostname: string
clientIP?: string
metas?: Record<string, string>
firstConnectedAt: number
lastConnectedAt: number
disconnectedAt?: number

View File

@@ -36,7 +36,8 @@ export interface ProxyV2Info {
}
export interface ProxyV2Status {
phase: 'online' | 'offline'
state?: string
phase?: string
todayTrafficIn: number
todayTrafficOut: number
curConns: number

View File

@@ -10,6 +10,7 @@ export class Client {
wireProtocol: string
hostname: string
ip: string
metas: Map<string, string>
firstConnectedAt: Date
lastConnectedAt: Date
disconnectedAt?: Date
@@ -25,6 +26,12 @@ export class Client {
this.wireProtocol = data.wireProtocol || ''
this.hostname = data.hostname
this.ip = data.clientIP || ''
this.metas = new Map<string, string>()
if (data.metas) {
for (const [key, value] of Object.entries(data.metas)) {
this.metas.set(key, value)
}
}
this.firstConnectedAt = new Date(data.firstConnectedAt * 1000)
this.lastConnectedAt = new Date(data.lastConnectedAt * 1000)
if (data.disconnectedAt && data.disconnectedAt > 0) {
@@ -45,6 +52,10 @@ export class Client {
return this.runID
}
get shortRunId(): string {
return this.runID.substring(0, 8)
}
get wireProtocolLabel(): string {
if (!this.wireProtocol) return ''
return `Protocol ${this.wireProtocol}`
@@ -62,4 +73,28 @@ export class Client {
if (!this.disconnectedAt) return ''
return formatDistanceToNow(this.disconnectedAt)
}
get statusColor(): string {
return this.online ? 'success' : 'danger'
}
get metasArray(): Array<{ key: string; value: string }> {
const arr: Array<{ key: string; value: string }> = []
this.metas.forEach((value, key) => {
arr.push({ key, value })
})
return arr
}
matchesFilter(searchText: string): boolean {
const search = searchText.toLowerCase()
return (
this.key.toLowerCase().includes(search) ||
this.user.toLowerCase().includes(search) ||
this.clientID.toLowerCase().includes(search) ||
this.runID.toLowerCase().includes(search) ||
this.wireProtocol.toLowerCase().includes(search) ||
this.hostname.toLowerCase().includes(search)
)
}
}