Spaces:
Running
Running
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>HuggingFace 保活管理器</title> | |
| <meta name="description" content="管理和保活您的HuggingFace Spaces,防止因长时间不访问而休眠"> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- 头部 --> | |
| <header class="header"> | |
| <div class="header-content"> | |
| <div class="logo"> | |
| <div class="logo-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </div> | |
| <div class="logo-text"> | |
| <h1>HF 保活管理器</h1> | |
| <p>HuggingFace Space Keepalive Manager</p> | |
| </div> | |
| </div> | |
| <div class="status-badge"> | |
| <span class="status-dot"></span> | |
| <span>运行中</span> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- 主内容区 --> | |
| <main class="main-content"> | |
| <!-- 状态卡片 --> | |
| <section class="status-section"> | |
| <div class="status-card"> | |
| <div class="status-icon urls-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </div> | |
| <div class="status-info"> | |
| <span class="status-value" id="url-count">{{ urls|length }}</span> | |
| <span class="status-label">保活URL</span> | |
| </div> | |
| </div> | |
| <div class="status-card"> | |
| <div class="status-icon interval-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/> | |
| <polyline points="12,6 12,12 16,14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </div> | |
| <div class="status-info"> | |
| <span class="status-value">{{ interval }}小时</span> | |
| <span class="status-label">保活间隔</span> | |
| </div> | |
| </div> | |
| <div class="status-card"> | |
| <div class="status-icon next-run-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M5 12h14M12 5l7 7-7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </div> | |
| <div class="status-info"> | |
| <span class="status-value next-run-time" id="next-run">{{ next_run }}</span> | |
| <span class="status-label">下次执行</span> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- 添加URL表单 --> | |
| <section class="add-url-section glass-card"> | |
| <h2> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/> | |
| <line x1="12" y1="8" x2="12" y2="16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> | |
| <line x1="8" y1="12" x2="16" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> | |
| </svg> | |
| 添加保活URL | |
| </h2> | |
| <form id="add-url-form" class="add-form"> | |
| <div class="form-row"> | |
| <div class="form-group"> | |
| <label for="url-input">URL地址</label> | |
| <input type="url" id="url-input" placeholder="https://your-space.hf.space" required> | |
| </div> | |
| <div class="form-group name-group"> | |
| <label for="name-input">名称 (可选)</label> | |
| <input type="text" id="name-input" placeholder="我的空间"> | |
| </div> | |
| <button type="submit" class="btn btn-primary"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <line x1="12" y1="5" x2="12" y2="19" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> | |
| <line x1="5" y1="12" x2="19" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> | |
| </svg> | |
| 添加 | |
| </button> | |
| </div> | |
| </form> | |
| </section> | |
| <!-- URL列表 --> | |
| <section class="urls-section glass-card"> | |
| <div class="section-header"> | |
| <h2> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| 保活列表 | |
| </h2> | |
| <button id="ping-all-btn" class="btn btn-secondary"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| 立即全部保活 | |
| </button> | |
| </div> | |
| <div id="urls-list" class="urls-list"> | |
| {% if urls %} | |
| {% for url in urls %} | |
| <div class="url-item" data-index="{{ loop.index0 }}"> | |
| <div class="url-info"> | |
| <span class="url-name">{{ url.name }}</span> | |
| <a href="{{ url.url }}" target="_blank" class="url-link">{{ url.url }}</a> | |
| <span class="url-added">添加于: {{ url.added_at }}</span> | |
| </div> | |
| <div class="url-actions"> | |
| <button class="btn btn-icon ping-btn" title="测试连接" data-index="{{ loop.index0 }}"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <polyline points="22,4 12,14.01 9,11.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </button> | |
| <button class="btn btn-icon btn-danger delete-btn" title="删除" data-index="{{ loop.index0 }}"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <polyline points="3,6 5,6 21,6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| {% endfor %} | |
| {% else %} | |
| <div class="empty-state"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| <p>还没有添加任何保活URL</p> | |
| <span>在上方输入框中添加需要保活的HuggingFace Space URL</span> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </section> | |
| <!-- 日志区域 --> | |
| <section class="logs-section glass-card"> | |
| <div class="section-header"> | |
| <h2> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <polyline points="14,2 14,8 20,8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <line x1="16" y1="13" x2="8" y2="13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <line x1="16" y1="17" x2="8" y2="17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <polyline points="10,9 9,9 8,9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| 运行日志 | |
| </h2> | |
| <button id="clear-logs-btn" class="btn btn-secondary btn-small"> | |
| <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <polyline points="3,6 5,6 21,6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| </svg> | |
| 清空日志 | |
| </button> | |
| </div> | |
| <div id="logs-container" class="logs-container"> | |
| {% for log in logs %} | |
| <div class="log-item log-{{ log.status }}"> | |
| <span class="log-time">{{ log.timestamp }}</span> | |
| <span class="log-url">{{ log.url }}</span> | |
| <span class="log-message">{{ log.message }}</span> | |
| </div> | |
| {% else %} | |
| <div class="empty-logs"> | |
| <p>暂无日志记录</p> | |
| </div> | |
| {% endfor %} | |
| </div> | |
| </section> | |
| </main> | |
| <!-- 页脚 --> | |
| <footer class="footer"> | |
| <p>HuggingFace Space 保活管理器 © 2024</p> | |
| <p class="footer-tip">💡 提示:保持此页面每日访问,即可确保所有配置的Space正常运行</p> | |
| </footer> | |
| </div> | |
| <!-- Toast 通知 --> | |
| <div id="toast-container"></div> | |
| <script src="{{ url_for('static', filename='script.js') }}"></script> | |
| </body> | |
| </html> | |