|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Gemini API 代理服务</title> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<style> |
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; |
|
max-width: 1200px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
line-height: 1.6; |
|
background-color: #f8f9fa; |
|
} |
|
h1, h2, h3 { |
|
color: #333; |
|
text-align: center; |
|
margin-bottom: 20px; |
|
} |
|
.info-box { |
|
background-color: #fff; |
|
border: 1px solid #dee2e6; |
|
border-radius: 8px; |
|
padding: 20px; |
|
margin-bottom: 20px; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05); |
|
} |
|
.status { |
|
color: #28a745; |
|
font-weight: bold; |
|
font-size: 18px; |
|
margin-bottom: 20px; |
|
text-align: center; |
|
} |
|
.stats-grid { |
|
display: grid; |
|
grid-template-columns: repeat(3, 1fr); |
|
gap: 15px; |
|
margin-top: 15px; |
|
margin-bottom: 20px; |
|
} |
|
.stat-card { |
|
background-color: #e9ecef; |
|
padding: 15px; |
|
border-radius: 8px; |
|
text-align: center; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05); |
|
transition: transform 0.2s; |
|
} |
|
.stat-card:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1); |
|
} |
|
.stat-value { |
|
font-size: 24px; |
|
font-weight: bold; |
|
color: #007bff; |
|
} |
|
.stat-label { |
|
font-size: 14px; |
|
color: #6c757d; |
|
margin-top: 5px; |
|
} |
|
.section-title { |
|
color: #495057; |
|
border-bottom: 1px solid #dee2e6; |
|
padding-bottom: 10px; |
|
margin-bottom: 20px; |
|
} |
|
.log-container { |
|
background-color: #f5f5f5; |
|
border: 1px solid #ddd; |
|
border-radius: 8px; |
|
padding: 15px; |
|
margin-top: 20px; |
|
max-height: 500px; |
|
overflow-y: auto; |
|
font-family: monospace; |
|
font-size: 14px; |
|
line-height: 1.5; |
|
} |
|
.log-entry { |
|
margin-bottom: 8px; |
|
padding: 8px; |
|
border-radius: 4px; |
|
} |
|
.log-entry.INFO { |
|
background-color: #e8f4f8; |
|
border-left: 4px solid #17a2b8; |
|
} |
|
.log-entry.WARNING { |
|
background-color: #fff3cd; |
|
border-left: 4px solid #ffc107; |
|
} |
|
.log-entry.ERROR { |
|
background-color: #f8d7da; |
|
border-left: 4px solid #dc3545; |
|
} |
|
.log-entry.DEBUG { |
|
background-color: #d1ecf1; |
|
border-left: 4px solid #17a2b8; |
|
} |
|
.log-timestamp { |
|
color: #6c757d; |
|
font-size: 12px; |
|
margin-right: 10px; |
|
} |
|
.log-level { |
|
font-weight: bold; |
|
margin-right: 10px; |
|
} |
|
.log-level.INFO { |
|
color: #17a2b8; |
|
} |
|
.log-level.WARNING { |
|
color: #ffc107; |
|
} |
|
.log-level.ERROR { |
|
color: #dc3545; |
|
} |
|
.log-level.DEBUG { |
|
color: #17a2b8; |
|
} |
|
.log-message { |
|
color: #212529; |
|
} |
|
.refresh-button { |
|
display: block; |
|
margin: 20px auto; |
|
padding: 10px 20px; |
|
background-color: #007bff; |
|
color: white; |
|
border: none; |
|
border-radius: 4px; |
|
font-size: 16px; |
|
cursor: pointer; |
|
transition: background-color 0.2s; |
|
} |
|
.refresh-button:hover { |
|
background-color: #0069d9; |
|
} |
|
.log-filter { |
|
display: flex; |
|
justify-content: center; |
|
margin-bottom: 15px; |
|
gap: 10px; |
|
} |
|
.log-filter button { |
|
padding: 5px 10px; |
|
border: 1px solid #ddd; |
|
border-radius: 4px; |
|
background-color: #f8f9fa; |
|
cursor: pointer; |
|
} |
|
.log-filter button.active { |
|
background-color: #007bff; |
|
color: white; |
|
border-color: #007bff; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<h1>🤖 Gemini API 代理服务</h1> |
|
|
|
<div class="info-box"> |
|
<h2 class="section-title">🟢 运行状态</h2> |
|
<p class="status">服务运行中</p> |
|
|
|
<div class="stats-grid"> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ key_count }}</div> |
|
<div class="stat-label">可用API密钥数量</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ model_count }}</div> |
|
<div class="stat-label">可用模型数量</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ retry_count }}</div> |
|
<div class="stat-label">最大重试次数</div> |
|
</div> |
|
</div> |
|
|
|
<h3 class="section-title">API调用统计</h3> |
|
<div class="stats-grid"> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ last_24h_calls }}</div> |
|
<div class="stat-label">24小时内调用次数</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ hourly_calls }}</div> |
|
<div class="stat-label">一小时内调用次数</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ minute_calls }}</div> |
|
<div class="stat-label">一分钟内调用次数</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="info-box"> |
|
<h2 class="section-title">⚙️ 环境配置</h2> |
|
<div class="stats-grid"> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ max_requests_per_minute }}</div> |
|
<div class="stat-label">每分钟请求限制</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ max_requests_per_day_per_ip }}</div> |
|
<div class="stat-label">每IP每日请求限制</div> |
|
</div> |
|
<div class="stat-card"> |
|
<div class="stat-value">{{ current_time }}</div> |
|
<div class="stat-label">当前服务器时间</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="info-box"> |
|
<h2 class="section-title">📦 版本信息</h2> |
|
<div class="version-info" style="text-align: center; margin-bottom: 15px;"> |
|
<div style="font-size: 18px; margin-bottom: 10px;"> |
|
当前版本: <span style="font-weight: bold; color: #007bff;">{{ local_version }}</span> |
|
</div> |
|
{% if has_update %} |
|
<div style="display: flex; align-items: center; justify-content: center; margin-top: 15px;"> |
|
<div style="background-color: #fef6e0; border: 1px solid #ffeeba; border-radius: 4px; padding: 10px 15px; display: inline-flex; align-items: center;"> |
|
<span style="color: #ff9800; margin-right: 10px;"> |
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
|
<circle cx="12" cy="12" r="10"></circle> |
|
<line x1="12" y1="8" x2="12" y2="12"></line> |
|
<line x1="12" y1="16" x2="12.01" y2="16"></line> |
|
</svg> |
|
</span> |
|
<span> |
|
<strong>发现新版本!</strong> 最新版本: <span style="font-weight: bold; color: #28a745;">{{ remote_version }}</span> |
|
</span> |
|
</div> |
|
</div> |
|
{% endif %} |
|
</div> |
|
</div> |
|
|
|
<div class="info-box"> |
|
<h2 class="section-title"> 系统日志</h2> |
|
<div class="log-filter"> |
|
<button class="active" data-level="ALL">全部</button> |
|
<button data-level="INFO">信息</button> |
|
<button data-level="WARNING">警告</button> |
|
<button data-level="ERROR">错误</button> |
|
</div> |
|
<div class="log-container"> |
|
{% for log in logs %} |
|
<div class="log-entry {{ log.level }}" data-level="{{ log.level }}"> |
|
<span class="log-timestamp">{{ log.timestamp }}</span> |
|
<span class="log-level {{ log.level }}">{{ log.level }}</span> |
|
<span class="log-message"> |
|
{% if log.key != 'N/A' %}[{{ log.key }}]{% endif %} |
|
{% if log.request_type != 'N/A' %}{{ log.request_type }}{% endif %} |
|
{% if log.model != 'N/A' %}[{{ log.model }}]{% endif %} |
|
{% if log.status_code != 'N/A' %}{{ log.status_code }}{% endif %} |
|
: {{ log.message }} |
|
{% if log.error_message %} |
|
- {{ log.error_message }} |
|
{% endif %} |
|
</span> |
|
</div> |
|
{% endfor %} |
|
</div> |
|
<button class="refresh-button" onclick="window.location.reload()">刷新日志</button> |
|
</div> |
|
|
|
<script> |
|
|
|
document.querySelectorAll('.log-filter button').forEach(button => { |
|
button.addEventListener('click', function() { |
|
|
|
document.querySelectorAll('.log-filter button').forEach(btn => { |
|
btn.classList.remove('active'); |
|
}); |
|
|
|
|
|
this.classList.add('active'); |
|
|
|
const level = this.getAttribute('data-level'); |
|
|
|
|
|
document.querySelectorAll('.log-entry').forEach(entry => { |
|
if (level === 'ALL' || entry.getAttribute('data-level') === level) { |
|
entry.style.display = 'block'; |
|
} else { |
|
entry.style.display = 'none'; |
|
} |
|
}); |
|
}); |
|
}); |
|
|
|
|
|
window.onload = function() { |
|
const logContainer = document.querySelector('.log-container'); |
|
logContainer.scrollTop = logContainer.scrollHeight; |
|
}; |
|
</script> |
|
</body> |
|
</html> |