|
<!DOCTYPE html> |
|
<html lang="zh-CN"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>AI API Dashboard</title> |
|
|
|
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css"> |
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet"> |
|
<style> |
|
|
|
body { |
|
font-family: 'Poppins', sans-serif; |
|
background: linear-gradient(135deg, #f5f7fa, #e9eff5); |
|
color: #333; |
|
line-height: 1.7; |
|
-webkit-font-smoothing: antialiased; |
|
-moz-osx-font-smoothing: grayscale; |
|
} |
|
.container { |
|
max-width: 1100px; |
|
padding: 20px; |
|
} |
|
h1 { |
|
font-weight: 700; |
|
color: #3f51b5; |
|
text-align: center; |
|
margin-bottom: 0.6em; |
|
letter-spacing: -0.5px; |
|
} |
|
p.lead { |
|
text-align: center; |
|
font-size: 1.2rem; |
|
color: #606c76; |
|
} |
|
|
|
.dashboard-section { |
|
background-color: #fff; |
|
border-radius: 12px; |
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.06); |
|
margin-bottom: 40px; |
|
padding: 30px; |
|
border: none; |
|
transition: transform 0.3s ease; |
|
} |
|
.dashboard-section:hover { |
|
transform: translateY(-5px); |
|
} |
|
.dashboard-section h2 { |
|
font-weight: 600; |
|
color: #424242; |
|
margin-bottom: 1.6rem; |
|
padding-bottom: 10px; |
|
border-bottom: 2px solid #e0e0e0; |
|
} |
|
|
|
.metrics-card { |
|
background-color: #fff; |
|
border: none; |
|
border-radius: 10px; |
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05); |
|
padding: 25px; |
|
margin-bottom: 20px; |
|
transition: transform 0.3s ease, box-shadow 0.3s ease; |
|
} |
|
.metrics-card:hover { |
|
transform: translateY(-3px); |
|
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.08); |
|
border-top: 3px solid #3f51b5; |
|
} |
|
.card-title { |
|
display: flex; |
|
align-items: center; |
|
font-size: 1.1rem; |
|
font-weight: 600; |
|
color: #37474f; |
|
margin-bottom: 1.2rem; |
|
} |
|
.card-title i { |
|
margin-right: 8px; |
|
font-size: 1.3rem; |
|
color: #8e44ad; |
|
} |
|
.metrics-card p { |
|
font-size: 1rem; |
|
margin-bottom: 0.8rem; |
|
} |
|
.badge { |
|
font-size: 1rem; |
|
font-weight: 600; |
|
padding: 0.5rem 0.75rem; |
|
border-radius: 0.5rem; |
|
} |
|
|
|
.key-balances-table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
margin-top: 20px; |
|
border: 1px solid #e8e8e8; |
|
border-radius: 8px; |
|
overflow: hidden; |
|
} |
|
.key-balances-table th, |
|
.key-balances-table td { |
|
padding: 12px 15px; |
|
text-align: left; |
|
border-bottom: 1px solid #ecf0f1; |
|
font-size: 0.95rem; |
|
} |
|
.key-balances-table thead { |
|
background-color: #ecf0f1; |
|
} |
|
.key-balances-table th { |
|
font-weight: 600; |
|
text-transform: uppercase; |
|
letter-spacing: 0.03em; |
|
color: #2c3e50; |
|
} |
|
.key-balances-table tbody tr:nth-child(even) { |
|
background-color: #f8f9fa; |
|
} |
|
.key-balances-table tbody tr:hover { |
|
background-color: #f1f3f5; |
|
} |
|
.text-break { |
|
word-break: break-word; |
|
} |
|
|
|
.footer { |
|
text-align: center; |
|
padding: 20px 0; |
|
font-size: 0.9rem; |
|
color: #888; |
|
border-top: 1px solid #eee; |
|
margin-top: 40px; |
|
} |
|
.footer a { |
|
color: #888; |
|
text-decoration: none; |
|
} |
|
.footer a:hover { |
|
color: #2c3e50; |
|
} |
|
|
|
@media (max-width: 576px) { |
|
h1 { font-size: 1.8rem; } |
|
.card-title { font-size: 1rem; } |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container mt-5"> |
|
<h1 class="text-center">AI API Dashboard</h1> |
|
<p class="lead text-center">实时监控您的 API 代理服务状态</p> |
|
|
|
|
|
<section class="dashboard-section"> |
|
<h2><i class="bi bi-speedometer2"></i> 实时性能指标</h2> |
|
<div class="row"> |
|
<div class="col-md-6 mb-4"> |
|
<div class="card metrics-card"> |
|
<div class="card-body"> |
|
<h5 class="card-title"><i class="bi bi-lightning-fill"></i> 请求速率</h5> |
|
<p>每分钟请求数 (RPM): <span class="badge bg-primary">{{ rpm }}</span></p> |
|
<p>每日请求数 (RPD): <span class="badge bg-secondary">{{ rpd }}</span></p> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="col-md-6"> |
|
<div class="card metrics-card"> |
|
<div class="card-body"> |
|
<h5 class="card-title"><i class="bi bi-graph-up-arrow"></i> Token 使用量</h5> |
|
<p>每分钟 Token 数 (TPM): <span class="badge bg-success">{{ tpm }}</span></p> |
|
<p>每日 Token 数 (TPD): <span class="badge bg-info">{{ tpd }}</span></p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="dashboard-section"> |
|
<h2><i class="bi bi-key-fill"></i> API 密钥余额</h2> |
|
<div class="table-responsive"> |
|
<table class="table key-balances-table"> |
|
<thead> |
|
<tr> |
|
<th>API 密钥 (已打码)</th> |
|
<th>余额</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
{% for key_balance in key_balances %} |
|
<tr> |
|
<td class="text-break">{{ key_balance.key }}</td> |
|
<td>{{ key_balance.balance }}</td> |
|
</tr> |
|
{% endfor %} |
|
{% if not key_balances %} |
|
<tr> |
|
<td colspan="2">没有可用的 API 密钥信息。</td> |
|
</tr> |
|
{% endif %} |
|
</tbody> |
|
</table> |
|
</div> |
|
</section> |
|
|
|
<div class="footer"> |
|
<p>Dashboard created at {{ now }} · Powered by <a href="https://vercel.com" target="_blank" rel="noopener noreferrer">Vercel</a></p> |
|
</div> |
|
</div> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> |
|
</body> |
|
</html> |