Spaces:
Paused
Paused
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <meta name="apple-mobile-web-app-capable" content="yes"> | |
| <meta name="apple-mobile-web-app-status-bar-style" content="default"> | |
| <title>Notion2API 管理面板</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary-color: #0066cc; | |
| --secondary-color: #6c757d; | |
| --success-color: #28a745; | |
| --danger-color: #dc3545; | |
| --warning-color: #ffc107; | |
| --light-bg: #f8f9fa; | |
| --border-color: #dee2e6; | |
| --mobile-navbar-height: 56px; | |
| } | |
| body { | |
| background-color: var(--light-bg); | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
| -webkit-font-smoothing: antialiased; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| /* 移动端优化 */ | |
| @media (max-width: 768px) { | |
| body { | |
| padding-bottom: 60px; /* 为底部操作栏留出空间 */ | |
| } | |
| .container { | |
| padding-left: 12px; | |
| padding-right: 12px; | |
| } | |
| /* 移动端导航栏优化 */ | |
| .navbar { | |
| padding: 0.5rem 0; | |
| position: sticky; | |
| top: 0; | |
| z-index: 1030; | |
| } | |
| .navbar-brand { | |
| font-size: 1.1rem; | |
| } | |
| .navbar-brand i { | |
| display: none; /* 移动端隐藏图标 */ | |
| } | |
| /* 用户信息优化 */ | |
| .user-info { | |
| gap: 0.5rem ; | |
| } | |
| .user-info .avatar { | |
| width: 28px ; | |
| height: 28px ; | |
| font-size: 0.875rem; | |
| } | |
| .user-info span { | |
| font-size: 0.875rem; | |
| } | |
| /* 统计卡片移动端优化 */ | |
| .stats-card { | |
| padding: 1rem ; | |
| margin-bottom: 0.75rem; | |
| } | |
| .stats-card h3 { | |
| font-size: 1.5rem ; | |
| } | |
| .stats-card p { | |
| font-size: 0.875rem; | |
| } | |
| /* 表格移动端优化 */ | |
| .table-container { | |
| overflow-x: auto; | |
| -webkit-overflow-scrolling: touch; | |
| margin: 0 -12px; | |
| padding: 0 12px; | |
| } | |
| .table { | |
| font-size: 0.875rem; | |
| white-space: nowrap; | |
| } | |
| .table td, .table th { | |
| padding: 0.5rem; | |
| } | |
| /* 隐藏次要列 */ | |
| .mobile-hide { | |
| display: none ; | |
| } | |
| /* 操作按钮优化 */ | |
| .action-buttons { | |
| gap: 0.25rem ; | |
| } | |
| .btn-sm { | |
| padding: 0.25rem 0.5rem; | |
| font-size: 0.75rem; | |
| } | |
| /* 卡片移动端优化 */ | |
| .card { | |
| margin-bottom: 1rem; | |
| border-radius: 8px; | |
| } | |
| .card-header { | |
| padding: 0.75rem 1rem; | |
| font-size: 0.9rem; | |
| } | |
| .card-body { | |
| padding: 1rem; | |
| } | |
| /* 模态框移动端优化 */ | |
| .modal-dialog { | |
| margin: 0.5rem; | |
| max-width: calc(100% - 1rem); | |
| } | |
| .modal-content { | |
| border-radius: 12px; | |
| } | |
| /* 表单移动端优化 */ | |
| .form-control, .form-select { | |
| font-size: 16px; /* 防止iOS缩放 */ | |
| padding: 0.75rem; | |
| } | |
| /* 底部浮动操作栏 */ | |
| .mobile-action-bar { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| background: white; | |
| border-top: 1px solid var(--border-color); | |
| padding: 0.75rem; | |
| display: flex; | |
| gap: 0.5rem; | |
| z-index: 1020; | |
| box-shadow: 0 -2px 10px rgba(0,0,0,0.1); | |
| } | |
| .mobile-action-bar .btn { | |
| flex: 1; | |
| font-size: 0.875rem; | |
| } | |
| /* 空状态优化 */ | |
| .empty-state { | |
| padding: 2rem 1rem; | |
| } | |
| .empty-state i { | |
| font-size: 2rem; | |
| } | |
| /* Toast移动端位置 */ | |
| .toast-container { | |
| top: var(--mobile-navbar-height) ; | |
| right: 12px ; | |
| } | |
| } | |
| /* 通用样式 */ | |
| .navbar { | |
| background-color: white ; | |
| box-shadow: 0 2px 4px rgba(0,0,0,.1); | |
| } | |
| .navbar-brand { | |
| font-weight: 600; | |
| color: var(--primary-color) ; | |
| } | |
| .main-container { | |
| margin-top: 2rem; | |
| } | |
| .card { | |
| border: none; | |
| box-shadow: 0 2px 8px rgba(0,0,0,.08); | |
| border-radius: 12px; | |
| margin-bottom: 1.5rem; | |
| } | |
| .card-header { | |
| background-color: white; | |
| border-bottom: 1px solid var(--border-color); | |
| padding: 1.25rem; | |
| font-weight: 600; | |
| } | |
| .table { | |
| margin-bottom: 0; | |
| } | |
| .table th { | |
| border-bottom: 2px solid var(--border-color); | |
| font-weight: 600; | |
| color: var(--secondary-color); | |
| text-transform: uppercase; | |
| font-size: 0.875rem; | |
| letter-spacing: 0.5px; | |
| } | |
| .badge { | |
| padding: 0.375rem 0.75rem; | |
| font-weight: 500; | |
| } | |
| .btn { | |
| border-radius: 8px; | |
| padding: 0.5rem 1rem; | |
| font-weight: 500; | |
| transition: all 0.2s; | |
| } | |
| .btn-primary { | |
| background-color: var(--primary-color); | |
| border-color: var(--primary-color); | |
| } | |
| .btn-primary:hover { | |
| background-color: #0056b3; | |
| border-color: #0056b3; | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 8px rgba(0,102,204,.25); | |
| } | |
| .btn-sm { | |
| padding: 0.375rem 0.75rem; | |
| font-size: 0.875rem; | |
| } | |
| .status-indicator { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| margin-right: 0.5rem; | |
| } | |
| .status-active { | |
| background-color: var(--success-color); | |
| animation: pulse 2s infinite; | |
| } | |
| .status-inactive { | |
| background-color: var(--danger-color); | |
| } | |
| @keyframes pulse { | |
| 0% { | |
| box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.4); | |
| } | |
| 70% { | |
| box-shadow: 0 0 0 10px rgba(40, 167, 69, 0); | |
| } | |
| 100% { | |
| box-shadow: 0 0 0 0 rgba(40, 167, 69, 0); | |
| } | |
| } | |
| .modal-header { | |
| border-bottom: 1px solid var(--border-color); | |
| background-color: var(--light-bg); | |
| } | |
| .form-label { | |
| font-weight: 500; | |
| color: var(--secondary-color); | |
| margin-bottom: 0.5rem; | |
| } | |
| .form-control, .form-select { | |
| border-radius: 8px; | |
| border: 1px solid var(--border-color); | |
| padding: 0.625rem 0.875rem; | |
| } | |
| .form-control:focus, .form-select:focus { | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 0 0.2rem rgba(0, 102, 204, 0.25); | |
| } | |
| .alert { | |
| border-radius: 8px; | |
| border: none; | |
| } | |
| .text-muted { | |
| color: #8492a6 ; | |
| } | |
| .empty-state { | |
| text-align: center; | |
| padding: 3rem; | |
| color: var(--secondary-color); | |
| } | |
| .empty-state i { | |
| font-size: 3rem; | |
| color: var(--border-color); | |
| margin-bottom: 1rem; | |
| } | |
| .stats-card { | |
| background: linear-gradient(135deg, var(--primary-color) 0%, #0056b3 100%); | |
| color: white; | |
| border: none; | |
| border-radius: 12px; | |
| padding: 1.5rem; | |
| } | |
| .stats-card h3 { | |
| margin-bottom: 0.5rem; | |
| font-size: 2rem; | |
| font-weight: 700; | |
| } | |
| .stats-card p { | |
| margin-bottom: 0; | |
| opacity: 0.9; | |
| } | |
| .loading-spinner { | |
| display: none; | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| z-index: 9999; | |
| } | |
| .loading-spinner.active { | |
| display: block; | |
| } | |
| .toast-container { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| z-index: 1050; | |
| } | |
| .cookie-item { | |
| transition: background-color 0.2s; | |
| } | |
| .cookie-item:hover { | |
| background-color: var(--light-bg); | |
| } | |
| .action-buttons { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .thread-id-input { | |
| max-width: 200px; | |
| } | |
| /* 登录页面样式 */ | |
| .login-container { | |
| min-height: 100vh; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| padding: 1rem; | |
| } | |
| .login-card { | |
| width: 100%; | |
| max-width: 400px; | |
| padding: 2rem; | |
| background: white; | |
| border-radius: 16px; | |
| box-shadow: 0 10px 25px rgba(0,0,0,.1); | |
| } | |
| .login-card .logo { | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .login-card .logo i { | |
| font-size: 3rem; | |
| color: var(--primary-color); | |
| } | |
| .login-card h2 { | |
| text-align: center; | |
| margin-bottom: 1.5rem; | |
| color: #333; | |
| font-weight: 600; | |
| } | |
| .login-error { | |
| display: none; | |
| margin-bottom: 1rem; | |
| } | |
| #mainContent { | |
| display: none; | |
| } | |
| .user-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .user-info .avatar { | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 50%; | |
| background: var(--primary-color); | |
| color: white; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: 600; | |
| } | |
| /* 表格响应式滚动 */ | |
| .table-responsive { | |
| -webkit-overflow-scrolling: touch; | |
| } | |
| /* 移动端触摸优化 */ | |
| @media (hover: none) { | |
| .btn:hover { | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .cookie-item:hover { | |
| background-color: transparent; | |
| } | |
| } | |
| /* 桌面端隐藏移动操作栏 */ | |
| @media (min-width: 769px) { | |
| .mobile-action-bar { | |
| display: none ; | |
| } | |
| .mobile-only { | |
| display: none ; | |
| } | |
| } | |
| /* 改进的响应式断点 */ | |
| @media (min-width: 576px) and (max-width: 768px) { | |
| .col-sm-6 { | |
| flex: 0 0 50%; | |
| max-width: 50%; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- 登录页面 --> | |
| <div id="loginContainer" class="login-container"> | |
| <div class="login-card"> | |
| <div class="logo"> | |
| <i class="bi bi-cloud-arrow-up-fill"></i> | |
| </div> | |
| <h2>Notion2API 管理登录</h2> | |
| <div class="alert alert-danger login-error" id="loginError" role="alert"> | |
| <i class="bi bi-exclamation-circle me-2"></i> | |
| <span id="loginErrorText">用户名或密码错误</span> | |
| </div> | |
| <form id="loginForm"> | |
| <div class="mb-3"> | |
| <label for="username" class="form-label">用户名</label> | |
| <input type="text" class="form-control" id="username" required | |
| placeholder="请输入用户名" autocomplete="username"> | |
| </div> | |
| <div class="mb-3"> | |
| <label for="password" class="form-label">密码</label> | |
| <input type="password" class="form-control" id="password" required | |
| placeholder="请输入密码" autocomplete="current-password"> | |
| </div> | |
| <div class="mb-3 form-check"> | |
| <input type="checkbox" class="form-check-input" id="remember"> | |
| <label class="form-check-label" for="remember"> | |
| 记住我 | |
| </label> | |
| </div> | |
| <button type="submit" class="btn btn-primary w-100"> | |
| <i class="bi bi-box-arrow-in-right me-2"></i> | |
| 登录 | |
| </button> | |
| </form> | |
| <div class="text-center mt-3 text-muted"> | |
| <small>默认用户名: admin</small> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 主内容区域 --> | |
| <div id="mainContent"> | |
| <!-- 导航栏 --> | |
| <nav class="navbar navbar-expand-lg navbar-light"> | |
| <div class="container"> | |
| <a class="navbar-brand" href="#"> | |
| <i class="bi bi-cloud-arrow-up-fill me-2"></i> | |
| <span class="d-none d-sm-inline">Notion2API 管理面板</span> | |
| <span class="d-inline d-sm-none">Notion2API</span> | |
| </a> | |
| <div class="ms-auto d-flex align-items-center"> | |
| <div class="user-info me-3"> | |
| <div class="avatar"> | |
| <span id="userAvatar">A</span> | |
| </div> | |
| <span class="text-muted d-none d-sm-inline" id="currentUser">admin</span> | |
| </div> | |
| <button class="btn btn-outline-secondary btn-sm" onclick="logout()"> | |
| <i class="bi bi-box-arrow-right me-1 d-none d-sm-inline"></i> | |
| <span class="d-none d-sm-inline">退出</span> | |
| <span class="d-inline d-sm-none">退出</span> | |
| </button> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- 主容器 --> | |
| <div class="container main-container"> | |
| <!-- 统计信息 --> | |
| <div class="row mb-4"> | |
| <div class="col-12 col-sm-6 col-md-4 mb-3 mb-md-0"> | |
| <div class="card stats-card"> | |
| <div class="card-body"> | |
| <h3 id="totalCookies">0</h3> | |
| <p>总Cookie数</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-12 col-sm-6 col-md-4 mb-3 mb-md-0"> | |
| <div class="card stats-card"> | |
| <div class="card-body"> | |
| <h3 id="activeCookies">0</h3> | |
| <p>有效Cookie数</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-12 col-sm-6 col-md-4"> | |
| <div class="card stats-card"> | |
| <div class="card-body"> | |
| <h3 id="threadIdCount">0</h3> | |
| <p>已配置ThreadID</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Cookie管理 --> | |
| <div class="card"> | |
| <div class="card-header d-flex justify-content-between align-items-center"> | |
| <span> | |
| <i class="bi bi-key-fill me-2"></i> | |
| Cookie 管理 | |
| </span> | |
| <div class="d-none d-md-block"> | |
| <button class="btn btn-success btn-sm me-2" onclick="refreshCookies()"> | |
| <i class="bi bi-arrow-clockwise me-1"></i> | |
| <span class="d-none d-sm-inline">刷新状态</span> | |
| <span class="d-inline d-sm-none">刷新</span> | |
| </button> | |
| <button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addCookieModal"> | |
| <i class="bi bi-plus-circle me-1"></i> | |
| <span class="d-none d-sm-inline">添加Cookie</span> | |
| <span class="d-inline d-sm-none">添加</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="card-body p-0 p-md-3"> | |
| <div class="table-container"> | |
| <div class="table-responsive"> | |
| <table class="table table-hover mb-0"> | |
| <thead> | |
| <tr> | |
| <th width="40"> | |
| <i class="bi bi-toggle-on" title="启用/禁用"></i> | |
| </th> | |
| <th width="50">#</th> | |
| <th>用户ID</th> | |
| <th class="mobile-hide">空间ID</th> | |
| <th class="mobile-hide">Cookie预览</th> | |
| <th width="120">状态</th> | |
| <th class="mobile-hide" width="150">最后使用</th> | |
| <th class="mobile-hide" width="150">Thread ID</th> | |
| <th width="100">操作</th> | |
| </tr> | |
| </thead> | |
| <tbody id="cookieTableBody"> | |
| <!-- Cookie列表将通过JavaScript动态加载 --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div id="emptyCookieState" class="empty-state" style="display: none;"> | |
| <i class="bi bi-inbox d-block"></i> | |
| <p>暂无Cookie数据</p> | |
| <button class="btn btn-primary btn-sm mt-2" data-bs-toggle="modal" data-bs-target="#addCookieModal"> | |
| 添加第一个Cookie | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 操作日志(桌面端显示) --> | |
| <div class="card d-none d-md-block"> | |
| <div class="card-header"> | |
| <i class="bi bi-journal-text me-2"></i> | |
| 操作日志 | |
| </div> | |
| <div class="card-body"> | |
| <div id="logContainer" style="max-height: 300px; overflow-y: auto;"> | |
| <div class="text-muted text-center py-3">暂无操作日志</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 移动端底部操作栏 --> | |
| <div class="mobile-action-bar d-md-none"> | |
| <button class="btn btn-success btn-sm" onclick="refreshCookies()"> | |
| <i class="bi bi-arrow-clockwise"></i> | |
| 刷新 | |
| </button> | |
| <button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addCookieModal"> | |
| <i class="bi bi-plus-circle"></i> | |
| 添加 | |
| </button> | |
| </div> | |
| <!-- 添加Cookie模态框 --> | |
| <div class="modal fade" id="addCookieModal" tabindex="-1"> | |
| <div class="modal-dialog modal-lg modal-dialog-centered"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h5 class="modal-title"> | |
| <i class="bi bi-plus-circle me-2"></i> | |
| 添加新Cookie | |
| </h5> | |
| <button type="button" class="btn-close" data-bs-dismiss="modal"></button> | |
| </div> | |
| <div class="modal-body"> | |
| <form id="addCookieForm"> | |
| <div class="mb-3"> | |
| <label class="form-label">Cookie内容</label> | |
| <textarea class="form-control" id="cookieContent" rows="4" | |
| placeholder="请输入Cookie内容..." required></textarea> | |
| <small class="text-muted">支持单个Cookie或使用 | 分隔的多个Cookie</small> | |
| </div> | |
| <div class="mb-3"> | |
| <label class="form-label">Thread ID(可选)</label> | |
| <input type="text" class="form-control" id="cookieThreadId" | |
| placeholder="如需指定Thread ID,请在此输入"> | |
| <small class="text-muted">Thread ID需要手动从Notion获取,系统不会自动创建</small> | |
| </div> | |
| </form> | |
| </div> | |
| <div class="modal-footer"> | |
| <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> | |
| <button type="button" class="btn btn-primary" onclick="addCookie()"> | |
| <i class="bi bi-check-circle me-1"></i> | |
| 添加 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 编辑ThreadID模态框 --> | |
| <div class="modal fade" id="editThreadIdModal" tabindex="-1"> | |
| <div class="modal-dialog modal-dialog-centered"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h5 class="modal-title"> | |
| <i class="bi bi-pencil-square me-2"></i> | |
| 编辑Thread ID | |
| </h5> | |
| <button type="button" class="btn-close" data-bs-dismiss="modal"></button> | |
| </div> | |
| <div class="modal-body"> | |
| <form id="editThreadIdForm"> | |
| <input type="hidden" id="editCookieIndex"> | |
| <div class="mb-3"> | |
| <label class="form-label">用户ID</label> | |
| <input type="text" class="form-control" id="editUserId" readonly> | |
| </div> | |
| <div class="mb-3"> | |
| <label class="form-label">Thread ID</label> | |
| <input type="text" class="form-control" id="editThreadId" | |
| placeholder="输入Thread ID"> | |
| <small class="text-muted">留空表示不使用特定的Thread ID</small> | |
| </div> | |
| </form> | |
| </div> | |
| <div class="modal-footer"> | |
| <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> | |
| <button type="button" class="btn btn-primary" onclick="saveThreadId()"> | |
| <i class="bi bi-check-circle me-1"></i> | |
| 保存 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 加载动画 --> | |
| <div class="loading-spinner"> | |
| <div class="spinner-border text-primary" role="status"> | |
| <span class="visually-hidden">加载中...</span> | |
| </div> | |
| </div> | |
| <!-- Toast容器 --> | |
| <div class="toast-container"></div> | |
| <!-- Scripts --> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> | |
| <script src="/admin.js"></script> | |
| </div> | |
| </body> | |
| </html> | |