feat: Implement initial backend API server with various endpoints and background services, including an error account cleaner.
This commit is contained in:
@@ -508,7 +508,7 @@ func handleS2ATest(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 请求 S2A 仪表盘接口
|
// 请求 S2A 仪表盘接口
|
||||||
dashboardURL := config.Global.S2AApiBase + "/api/v1/admin/dashboard"
|
dashboardURL := config.Global.S2AApiBase + "/api/v1/admin/dashboard/stats"
|
||||||
req, err := http.NewRequest("GET", dashboardURL, nil)
|
req, err := http.NewRequest("GET", dashboardURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.Error(w, http.StatusInternalServerError, "创建请求失败")
|
api.Error(w, http.StatusInternalServerError, "创建请求失败")
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func getTotalAccountCount() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
url := fmt.Sprintf("%s/api/v1/admin/dashboard", config.Global.S2AApiBase)
|
url := fmt.Sprintf("%s/api/v1/admin/dashboard/stats", config.Global.S2AApiBase)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Users, CheckCircle, XCircle, AlertTriangle, Zap, Activity, TrendingUp } from 'lucide-react'
|
import { Users, CheckCircle, XCircle, AlertTriangle, Zap, Activity } from 'lucide-react'
|
||||||
import type { DashboardStats } from '../../types'
|
import type { DashboardStats } from '../../types'
|
||||||
import StatsCard from './StatsCard'
|
import StatsCard from './StatsCard'
|
||||||
|
|
||||||
@@ -78,17 +78,15 @@ export default function PoolStatus({ stats, loading, error }: PoolStatusProps) {
|
|||||||
color="slate"
|
color="slate"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
{/* RPM 卡片 - 显示当前 RPM 和今日最高 */}
|
<StatsCard
|
||||||
<div className="relative">
|
title="RPM"
|
||||||
<StatsCard title="RPM" value={stats?.rpm ?? 0} icon={Zap} color="blue" loading={loading} />
|
value={stats?.rpm ?? 0}
|
||||||
{/* 今日最高 RPM 显示在卡片下方 */}
|
icon={Zap}
|
||||||
{maxRpm > 0 && (
|
color="blue"
|
||||||
<div className="absolute -bottom-5 left-0 right-0 flex items-center justify-center gap-1 text-xs text-slate-500 dark:text-slate-400">
|
loading={loading}
|
||||||
<TrendingUp className="h-3 w-3 text-orange-500" />
|
subtitle={maxRpm > 0 ? `📈 今日最高: ${maxRpm}` : undefined}
|
||||||
<span>今日最高: <span className="font-semibold text-orange-500">{maxRpm}</span></span>
|
/>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ interface StatsCardProps {
|
|||||||
trendValue?: string
|
trendValue?: string
|
||||||
color?: 'blue' | 'green' | 'yellow' | 'red' | 'slate'
|
color?: 'blue' | 'green' | 'yellow' | 'red' | 'slate'
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
|
subtitle?: string
|
||||||
|
subtitleColor?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StatsCard({
|
export default function StatsCard({
|
||||||
@@ -20,6 +22,8 @@ export default function StatsCard({
|
|||||||
trendValue,
|
trendValue,
|
||||||
color = 'blue',
|
color = 'blue',
|
||||||
loading = false,
|
loading = false,
|
||||||
|
subtitle,
|
||||||
|
subtitleColor = 'text-orange-500',
|
||||||
}: StatsCardProps) {
|
}: StatsCardProps) {
|
||||||
const colorStyles = {
|
const colorStyles = {
|
||||||
blue: {
|
blue: {
|
||||||
@@ -80,6 +84,11 @@ export default function StatsCard({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{subtitle && (
|
||||||
|
<p className={`mt-1 text-xs font-medium ${subtitleColor}`}>
|
||||||
|
{subtitle}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{trend && trendValue && TrendIcon && (
|
{trend && trendValue && TrendIcon && (
|
||||||
<div className={`mt-2 flex items-center gap-1 text-sm ${trendStyles[trend].color}`}>
|
<div className={`mt-2 flex items-center gap-1 text-sm ${trendStyles[trend].color}`}>
|
||||||
<TrendIcon className="h-4 w-4" />
|
<TrendIcon className="h-4 w-4" />
|
||||||
@@ -94,3 +103,4 @@ export default function StatsCard({
|
|||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user