feat(record): 增加测试结果保存和展示功能
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { LatencyResult, TEST_NODES } from '@shared/types'
|
||||
import { LatencyResult, TEST_NODES, IpInfo } from '@shared/types'
|
||||
|
||||
const API_BASE = '/api'
|
||||
|
||||
@@ -17,6 +17,34 @@ export interface BatchResultResponse {
|
||||
latency: number | null
|
||||
success: boolean
|
||||
}>
|
||||
resolvedAddress?: string
|
||||
ipInfo?: IpInfo | null
|
||||
}
|
||||
|
||||
export interface SaveResultRequest {
|
||||
type: 'single' | 'compare'
|
||||
input: { target: string } | { leftTarget: string; rightTarget: string }
|
||||
results: Array<{ nodeId: string; latency: number | null; success: boolean }> | {
|
||||
left: Array<{ nodeId: string; latency: number | null; success: boolean }>
|
||||
right: Array<{ nodeId: string; latency: number | null; success: boolean }>
|
||||
}
|
||||
ipInfo?: IpInfo | { left: IpInfo | null; right: IpInfo | null } | null
|
||||
}
|
||||
|
||||
export interface SaveResultResponse {
|
||||
id: string
|
||||
shareUrl: string
|
||||
}
|
||||
|
||||
export interface SavedResultData {
|
||||
type: 'single' | 'compare'
|
||||
input: { target: string } | { leftTarget: string; rightTarget: string }
|
||||
results: Array<{ nodeId: string; latency: number | null; success: boolean }> | {
|
||||
left: Array<{ nodeId: string; latency: number | null; success: boolean }>
|
||||
right: Array<{ nodeId: string; latency: number | null; success: boolean }>
|
||||
}
|
||||
ipInfo?: IpInfo | { left: IpInfo | null; right: IpInfo | null } | null
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export async function fetchUserIp(): Promise<string> {
|
||||
@@ -26,10 +54,15 @@ export async function fetchUserIp(): Promise<string> {
|
||||
return data.ip
|
||||
}
|
||||
|
||||
export interface TestResult {
|
||||
resolvedAddress?: string
|
||||
ipInfo?: IpInfo | null
|
||||
}
|
||||
|
||||
export async function testAllNodes(
|
||||
target: string,
|
||||
onProgress: (result: LatencyResult) => void
|
||||
): Promise<void> {
|
||||
): Promise<TestResult> {
|
||||
for (const node of TEST_NODES) {
|
||||
onProgress({ nodeId: node.id, latency: null, status: 'pending' })
|
||||
}
|
||||
@@ -44,7 +77,7 @@ export async function testAllNodes(
|
||||
for (const node of TEST_NODES) {
|
||||
onProgress({ nodeId: node.id, latency: null, status: 'failed' })
|
||||
}
|
||||
return
|
||||
return {}
|
||||
}
|
||||
|
||||
const { measurementId }: BatchMeasurementResponse = await res.json()
|
||||
@@ -56,6 +89,8 @@ export async function testAllNodes(
|
||||
const startTime = Date.now()
|
||||
const timeout = 60000
|
||||
const completedNodes = new Set<string>()
|
||||
let resolvedAddress: string | undefined
|
||||
let ipInfo: IpInfo | null | undefined
|
||||
|
||||
while (Date.now() - startTime < timeout) {
|
||||
await new Promise(r => setTimeout(r, 800))
|
||||
@@ -65,6 +100,16 @@ export async function testAllNodes(
|
||||
|
||||
const data: BatchResultResponse = await pollRes.json()
|
||||
|
||||
// Capture resolved IP address
|
||||
if (!resolvedAddress && data.resolvedAddress) {
|
||||
resolvedAddress = data.resolvedAddress
|
||||
}
|
||||
|
||||
// Capture IP info when available
|
||||
if (!ipInfo && data.ipInfo) {
|
||||
ipInfo = data.ipInfo
|
||||
}
|
||||
|
||||
for (const result of data.results) {
|
||||
if (result.success && !completedNodes.has(result.nodeId)) {
|
||||
completedNodes.add(result.nodeId)
|
||||
@@ -89,4 +134,30 @@ export async function testAllNodes(
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return { resolvedAddress, ipInfo }
|
||||
}
|
||||
|
||||
export async function saveResult(data: SaveResultRequest): Promise<SaveResultResponse> {
|
||||
const res = await fetch(`${API_BASE}/results`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to save result')
|
||||
}
|
||||
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function fetchSavedResult(id: string): Promise<SavedResultData> {
|
||||
const res = await fetch(`${API_BASE}/results/${id}`)
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to fetch result')
|
||||
}
|
||||
|
||||
return res.json()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user