| <!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> |