feat(dashboard): optimize dashboard layout and add new charts

This commit is contained in:
祀梦
2026-04-05 21:04:49 +08:00
parent 7d5eaa438a
commit 02cd37db71
11 changed files with 967 additions and 657 deletions

View File

@@ -108,3 +108,21 @@ async def batch_delete(
async def clean_invalid(service: ProxyService = Depends(get_proxy_service)):
count = await service.clean_invalid()
return success_response(f"清理了 {count} 个无效代理", {"deleted_count": count})
@router.get("/latency-distribution")
async def get_latency_distribution(
service: ProxyService = Depends(get_proxy_service),
):
"""获取延迟分布数据,用于直方图展示"""
distribution = await service.get_latency_distribution()
return success_response("获取延迟分布成功", distribution)
@router.get("/score-distribution")
async def get_score_distribution(
service: ProxyService = Depends(get_proxy_service),
):
"""获取评分分布数据,用于柱状图展示"""
distribution = await service.get_score_distribution()
return success_response("获取评分分布成功", distribution)

View File

@@ -526,3 +526,73 @@ class ProxyRepository:
except Exception as e:
logger.error(f"clean_expired failed: {e}", exc_info=True)
return 0
@staticmethod
async def get_latency_distribution(db: aiosqlite.Connection) -> dict:
"""获取延迟分布数据(仅已验证可用的代理)"""
try:
async with db.execute(
"""
SELECT response_time_ms FROM proxies
WHERE validated = 1 AND score > 0 AND response_time_ms IS NOT NULL AND response_time_ms > 0
"""
) as cursor:
rows = await cursor.fetchall()
if not rows:
return {"ranges": [], "counts": []}
latencies = [row[0] for row in rows]
ranges = ["<500ms", "500-1s", "1-2s", "2-3s", ">3s"]
counts = [0, 0, 0, 0, 0]
for lat in latencies:
if lat < 500:
counts[0] += 1
elif lat < 1000:
counts[1] += 1
elif lat < 2000:
counts[2] += 1
elif lat < 3000:
counts[3] += 1
else:
counts[4] += 1
return {"ranges": ranges, "counts": counts}
except Exception as e:
logger.error(f"get_latency_distribution failed: {e}", exc_info=True)
return {"ranges": [], "counts": []}
@staticmethod
async def get_score_distribution(db: aiosqlite.Connection) -> dict:
"""获取评分分布数据(仅已验证可用的代理)"""
try:
async with db.execute(
"""
SELECT score FROM proxies
WHERE validated = 1 AND score > 0
"""
) as cursor:
rows = await cursor.fetchall()
if not rows:
return {"ranges": [], "counts": []}
scores = [row[0] for row in rows]
ranges = ["80-100", "60-80", "40-60", "20-40", "0-20"]
counts = [0, 0, 0, 0, 0]
for score in scores:
if score >= 80:
counts[0] += 1
elif score >= 60:
counts[1] += 1
elif score >= 40:
counts[2] += 1
elif score >= 20:
counts[3] += 1
else:
counts[4] += 1
return {"ranges": ranges, "counts": counts}
except Exception as e:
logger.error(f"get_score_distribution failed: {e}", exc_info=True)
return {"ranges": [], "counts": []}

View File

@@ -147,3 +147,11 @@ class ProxyService:
if isinstance(dt, str):
return dt
return dt.isoformat()
async def get_latency_distribution(self) -> dict:
async with get_db() as db:
return await self.proxy_repo.get_latency_distribution(db)
async def get_score_distribution(self) -> dict:
async with get_db() as db:
return await self.proxy_repo.get_score_distribution(db)