mikami / app /index.html
mikamipan's picture
Upload 8 files
1b65398 verified
<!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() {
// 移除所有按钮的active类
document.querySelectorAll('.log-filter button').forEach(btn => {
btn.classList.remove('active');
});
// 为当前按钮添加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>