Spaces:
Sleeping
Sleeping
| <html lang="zh-CN" class="h-full"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Zencoder Console</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| DEFAULT: '#007AFF', | |
| hover: '#0063CE', | |
| }, | |
| background: { | |
| light: '#F5F5F7', | |
| dark: '#000000', | |
| }, | |
| surface: { | |
| light: '#FFFFFF', | |
| dark: '#1C1C1E', | |
| }, | |
| border: { | |
| light: '#E5E5E5', | |
| dark: '#38383A', | |
| } | |
| }, | |
| fontFamily: { | |
| sans: ['-apple-system', 'BlinkMacSystemFont', 'Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'], | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'); | |
| body { | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| } | |
| /* Custom Scrollbar */ | |
| ::-webkit-scrollbar { width: 6px; height: 6px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: #D1D5DB; border-radius: 3px; } | |
| .dark ::-webkit-scrollbar-thumb { background: #4B5563; } | |
| ::-webkit-scrollbar-thumb:hover { background: #9CA3AF; } | |
| .glass-panel { | |
| background: rgba(255, 255, 255, 0.8); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| } | |
| .dark .glass-panel { | |
| background: rgba(28, 28, 30, 0.8); | |
| } | |
| .justify-between { | |
| justify-content: end; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-background-light dark:bg-background-dark text-gray-900 dark:text-gray-100 h-full flex flex-col transition-colors duration-300"> | |
| <!-- Admin Password Modal --> | |
| <div id="adminPasswordModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-2xl border border-border-light dark:border-border-dark p-8 max-w-md w-full mx-4 transition-colors duration-300"> | |
| <div class="text-center mb-6"> | |
| <div class="w-16 h-16 bg-primary rounded-full flex items-center justify-center text-white mx-auto mb-4"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" viewBox="0 0 20 20" fill="currentColor"> | |
| <path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd" /> | |
| </svg> | |
| </div> | |
| <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">管理员验证</h2> | |
| <p class="text-sm text-gray-500 dark:text-gray-400">请输入管理密码以访问控制台</p> | |
| </div> | |
| <form id="adminPasswordForm" class="space-y-4"> | |
| <div> | |
| <label for="adminPassword" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">管理密码</label> | |
| <div class="relative"> | |
| <input type="password" id="adminPassword" autocomplete="off" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-3 px-4 transition-colors placeholder-gray-400" | |
| placeholder="输入管理密码"> | |
| <button type="button" onclick="toggleAdminPasswordVisibility()" class="absolute inset-y-0 right-0 px-3 flex items-center text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none"> | |
| <svg id="adminEyeIcon" class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="rememberPassword" type="checkbox" class="h-4 w-4 text-primary focus:ring-primary border-gray-300 dark:border-gray-600 rounded"> | |
| <label for="rememberPassword" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">记住密码</label> | |
| </div> | |
| <div class="pt-4"> | |
| <button type="submit" id="adminLoginBtn" class="w-full flex justify-center py-3 px-4 border border-transparent rounded-xl shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-all active:scale-[0.98]"> | |
| <span id="adminBtnText">验证</span> | |
| <svg id="adminBtnLoading" class="animate-spin ml-2 h-4 w-4 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> | |
| <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> | |
| <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> | |
| </svg> | |
| </button> | |
| </div> | |
| <div id="passwordError" class="hidden text-sm text-red-600 dark:text-red-400 text-center mt-2"> | |
| 密码错误,请重试 | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Main Application (Hidden initially) --> | |
| <div id="mainApp" class="hidden h-full flex flex-col"> | |
| <!-- Navbar --> | |
| <nav class="sticky top-0 z-50 border-b border-border-light dark:border-border-dark glass-panel transition-colors duration-300"> | |
| <div class="max-w-[1800px] mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between h-16 items-center"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center text-white"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> | |
| <path fill-rule="evenodd" d="M12.395 2.553a1 1 0 00-1.45-.385c-.345.23-.614.558-.822.88-.214.33-.403.713-.57 1.116-.334.804-.614 1.768-.84 2.734a31.365 31.365 0 00-.613 3.58 2.64 2.64 0 01-.945-1.067c-.328-.68-.398-1.534-.398-2.654A1 1 0 005.05 6.05 6.981 6.981 0 003 11a7 7 0 1011.95-4.95c-.592-.591-.98-.985-1.348-1.467-.363-.476-.724-1.063-1.207-2.03zM12.12 15.12A3 3 0 017 13s.879.5 2.5.5c0-1 .5-4 1.25-4.5.5 1 .786 1.293 1.371 1.879A2.99 2.99 0 0113 13a2.99 2.99 0 01-.879 2.121z" clip-rule="evenodd" /> | |
| </svg> | |
| </div> | |
| <span class="text-lg font-semibold tracking-tight">Zencoder Console</span> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <!-- Pool/Token Toggle --> | |
| <div class="flex space-x-1 bg-gray-200 dark:bg-gray-700 p-1 rounded-lg"> | |
| <button type="button" onclick="switchMainView('pool')" id="view-pool" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm"> | |
| <span class="flex items-center gap-1"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /> | |
| </svg> | |
| 号池 | |
| </span> | |
| </button> | |
| <button type="button" onclick="switchMainView('token')" id="view-token" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white"> | |
| <span class="flex items-center gap-1"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /> | |
| </svg> | |
| 令牌 | |
| </span> | |
| </button> | |
| </div> | |
| <!-- Logout Button --> | |
| <button onclick="logout()" title="退出登录" class="p-2 rounded-full hover:bg-red-100 dark:hover:bg-red-900/20 transition-colors focus:outline-none focus:ring-2 focus:ring-red-500 text-red-600 dark:text-red-400"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" /> | |
| </svg> | |
| </button> | |
| <!-- Theme Toggle --> | |
| <button id="themeToggle" class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors focus:outline-none focus:ring-2 focus:ring-primary"> | |
| <!-- Sun Icon --> | |
| <svg id="sunIcon" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path> | |
| </svg> | |
| <!-- Moon Icon --> | |
| <svg id="moonIcon" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <main class="flex-1 max-w-[1800px] w-full mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| <!-- Pool View (默认显示) --> | |
| <div id="poolView" class="grid grid-cols-1 lg:grid-cols-12 gap-8"> | |
| <!-- Left Column: Add Account & Stats --> | |
| <div class="lg:col-span-3 space-y-6"> | |
| <!-- Add Account Form --> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-sm border border-border-light dark:border-border-dark p-6 transition-colors duration-300"> | |
| <div class="flex items-center justify-between mb-1"> | |
| <h2 class="text-xl font-semibold flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| 添加账号 | |
| </h2> | |
| <button type="button" onclick="startOAuthForRT()" class="px-3 py-1 text-xs font-medium rounded-lg bg-green-600 hover:bg-green-700 text-white transition-all flex items-center gap-1"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /> | |
| </svg> | |
| 一键获取 | |
| </button> | |
| </div> | |
| <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">请输入凭证信息以连接服务。</p> | |
| <!-- Mode Switcher --> | |
| <div class="flex space-x-1 bg-gray-200 dark:bg-gray-700 p-1 rounded-lg mb-4"> | |
| <button type="button" onclick="switchAddMode('credential')" id="mode-credential" class="flex-1 px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm">凭证模式</button> | |
| <button type="button" onclick="switchAddMode('generate')" id="mode-generate" class="flex-1 px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">生成模式</button> | |
| </div> | |
| <form id="addForm" class="space-y-4" autocomplete="off"> | |
| <!-- Credential Mode Fields --> | |
| <div id="credentialFields"> | |
| <div class="space-y-4"> | |
| <div> | |
| <label for="credential_access_token" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Access Token (JWT)</label> | |
| <textarea id="credential_access_token" rows="4" autocomplete="off" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors placeholder-gray-400 font-mono text-xs" | |
| placeholder="输入 Access Token (JWT格式,优先使用)"></textarea> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">直接使用 JWT access_token,无需刷新</p> | |
| </div> | |
| <div> | |
| <label for="credential_refresh_token" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Refresh Token (UUID)</label> | |
| <input type="text" id="credential_refresh_token" autocomplete="off" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors placeholder-gray-400 font-mono text-sm" | |
| placeholder="输入 Refresh Token (UUID格式)"> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">使用 refresh_token 获取 access_token</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Generate Mode Fields --> | |
| <div id="generateFields" class="hidden"> | |
| <div class="space-y-4"> | |
| <div> | |
| <label for="generate_access_token" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Master Access Token (JWT)</label> | |
| <textarea id="generate_access_token" rows="4" autocomplete="off" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors placeholder-gray-400 font-mono text-xs" | |
| placeholder="输入主账号的 Access Token (JWT格式,优先使用)"></textarea> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">直接使用 JWT access_token 创建子账号</p> | |
| </div> | |
| <div> | |
| <label for="generate_refresh_token" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Master Refresh Token (UUID)</label> | |
| <input type="text" id="generate_refresh_token" autocomplete="off" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors placeholder-gray-400 font-mono text-sm" | |
| placeholder="输入主账号的 Refresh Token (UUID格式)"> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">使用 refresh_token 获取 access_token 后创建子账号</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="proxy" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">代理 (可选)</label> | |
| <div class="relative rounded-md shadow-sm"> | |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
| <span class="text-gray-500 sm:text-sm"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| </span> | |
| </div> | |
| <input type="text" id="proxy" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 pl-10 px-3 transition-colors placeholder-gray-400" | |
| placeholder="http://127.0.0.1:7890"> | |
| </div> | |
| </div> | |
| <div class="pt-2"> | |
| <button type="submit" id="submitBtn" class="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-xl shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-all active:scale-[0.98]"> | |
| <span id="btnText">添加账号</span> | |
| <svg id="btnLoading" class="animate-spin ml-2 h-4 w-4 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> | |
| <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> | |
| <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> | |
| </svg> | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| <!-- Stats Panel (Moved here) --> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">总账号数</div> | |
| <div class="text-2xl font-bold text-gray-900 dark:text-white mt-1" id="stat-total-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">活跃账号</div> | |
| <div class="text-2xl font-bold text-green-600 dark:text-green-400 mt-1" id="stat-active-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">冷却账号</div> | |
| <div class="text-2xl font-bold text-orange-600 dark:text-orange-400 mt-1" id="stat-cooling-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">封禁账号</div> | |
| <div class="text-2xl font-bold text-red-600 dark:text-red-400 mt-1" id="stat-banned-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">错误账号</div> | |
| <div class="text-2xl font-bold text-yellow-600 dark:text-yellow-400 mt-1" id="stat-error-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">已禁用</div> | |
| <div class="text-2xl font-bold text-gray-600 dark:text-gray-400 mt-1" id="stat-disabled-accounts">-</div> | |
| </div> | |
| <div class="bg-surface-light dark:bg-surface-dark p-4 rounded-2xl shadow-sm border border-border-light dark:border-border-dark transition-colors duration-300 col-span-2"> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2">使用量统计</div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <div class="text-xs text-gray-500 dark:text-gray-400">今日用量</div> | |
| <div class="text-xl font-bold text-blue-600 dark:text-blue-400" id="stat-today-usage">-</div> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-xs text-gray-500 dark:text-gray-400">总用量</div> | |
| <div class="text-xl font-bold text-purple-600 dark:text-purple-400" id="stat-total-usage">-</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Progress Modal (Hidden by default) --> | |
| <div id="progressModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-2xl border border-border-light dark:border-border-dark p-6 max-w-md w-full mx-4 transition-colors duration-300"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white">批量生成进度</h3> | |
| <button onclick="closeProgressModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <!-- Progress Bar --> | |
| <div class="mb-4"> | |
| <div class="flex justify-between text-sm text-gray-600 dark:text-gray-400 mb-2"> | |
| <span id="progressText">准备中...</span> | |
| <span id="progressCount">0/0</span> | |
| </div> | |
| <div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5"> | |
| <div id="progressBar" class="bg-primary h-2.5 rounded-full transition-all duration-300" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <!-- Log Container --> | |
| <div class="bg-gray-50 dark:bg-gray-800 rounded-lg p-3 max-h-64 overflow-y-auto"> | |
| <div id="progressLog" class="text-xs font-mono space-y-1"> | |
| <!-- Logs will be added here --> | |
| </div> | |
| </div> | |
| <!-- Summary (Hidden until complete) --> | |
| <div id="progressSummary" class="hidden mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800"> | |
| <div class="flex items-center gap-2 text-sm"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-600 dark:text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| <span class="text-blue-900 dark:text-blue-100"> | |
| 完成!成功 <span id="summarySuccess" class="font-bold">0</span> 个,失败 <span id="summaryFail" class="font-bold">0</span> 个 | |
| </span> | |
| </div> | |
| </div> | |
| <!-- Close Button (Hidden until complete) --> | |
| <div id="progressCloseBtn" class="hidden mt-4"> | |
| <button onclick="closeProgressModal()" class="w-full py-2.5 px-4 bg-primary hover:bg-primary-hover text-white rounded-xl font-medium transition-all"> | |
| 关闭 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Refresh Progress Modal (Hidden by default) --> | |
| <div id="refreshProgressModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-2xl border border-border-light dark:border-border-dark p-6 max-w-md w-full mx-4 transition-colors duration-300"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white">批量刷新Token进度</h3> | |
| <button onclick="closeRefreshProgressModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <!-- Progress Bar --> | |
| <div class="mb-4"> | |
| <div class="flex justify-between text-sm text-gray-600 dark:text-gray-400 mb-2"> | |
| <span id="refreshProgressText">准备中...</span> | |
| <span id="refreshProgressCount">0/0</span> | |
| </div> | |
| <div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5"> | |
| <div id="refreshProgressBar" class="bg-blue-600 h-2.5 rounded-full transition-all duration-300" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <!-- Log Container --> | |
| <div class="bg-gray-50 dark:bg-gray-800 rounded-lg p-3 max-h-64 overflow-y-auto"> | |
| <div id="refreshProgressLog" class="text-xs font-mono space-y-1"> | |
| <!-- Logs will be added here --> | |
| </div> | |
| </div> | |
| <!-- Summary (Hidden until complete) --> | |
| <div id="refreshProgressSummary" class="hidden mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800"> | |
| <div class="flex items-center gap-2 text-sm"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-600 dark:text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| <span class="text-blue-900 dark:text-blue-100"> | |
| 完成!成功 <span id="refreshSummarySuccess" class="font-bold">0</span> 个,失败 <span id="refreshSummaryFail" class="font-bold">0</span> 个 | |
| </span> | |
| </div> | |
| </div> | |
| <!-- Close Button (Hidden until complete) --> | |
| <div id="refreshProgressCloseBtn" class="hidden mt-4"> | |
| <button onclick="closeRefreshProgressModal()" class="w-full py-2.5 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-xl font-medium transition-all"> | |
| 关闭 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Column: Account List --> | |
| <div class="lg:col-span-9"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-sm border border-border-light dark:border-border-dark flex flex-col h-full overflow-hidden transition-colors duration-300"> | |
| <div class="px-6 py-5 border-b border-border-light dark:border-border-dark flex flex-col gap-4 bg-gray-50/50 dark:bg-gray-800/50"> | |
| <div class="flex justify-between items-center w-full"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /> | |
| </svg> | |
| 账号列表 | |
| </h3> | |
| <div class="flex items-center gap-3"> | |
| <span class="text-xs text-gray-400 flex items-center gap-1"> | |
| <span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span> | |
| 自动刷新中 | |
| </span> | |
| </div> | |
| </div> | |
| <!-- Tabs & Batch Actions --> | |
| <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3"> | |
| <div class="flex space-x-1 bg-gray-200 dark:bg-gray-700 p-1 rounded-lg"> | |
| <button onclick="switchCategory('normal')" id="tab-normal" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm">正常</button> | |
| <button onclick="switchCategory('cooling')" id="tab-cooling" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">冷却</button> | |
| <button onclick="switchCategory('disabled')" id="tab-disabled" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">已禁用</button> | |
| <button onclick="switchCategory('banned')" id="tab-banned" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">封禁</button> | |
| <button onclick="switchCategory('error')" id="tab-error" class="px-3 py-1.5 text-xs font-medium rounded-md transition-all text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">错误</button> | |
| </div> | |
| <div id="batchActions" class="hidden items-center gap-2"> | |
| <span class="text-xs text-gray-500 dark:text-gray-400 hidden" id="selectedCount">0 选中</span> | |
| <div id="batchButtonsContainer" class="flex items-center gap-2"> | |
| <!-- 动态按钮将在这里通过 JavaScript 生成 --> | |
| </div> | |
| <!-- 批量刷新token按钮 --> | |
| <div class="flex items-center gap-2 border-l border-gray-300 dark:border-gray-600 pl-2 ml-2"> | |
| <button onclick="batchRefreshToken(false)" | |
| class="px-3 py-1.5 bg-blue-600 text-white text-xs font-medium rounded-md hover:bg-blue-700 transition-colors flex items-center gap-1" | |
| title="刷新选中账号的token"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> | |
| </svg> | |
| 刷新Token | |
| </button> | |
| <button onclick="batchRefreshToken(true)" | |
| class="px-3 py-1.5 bg-purple-600 text-white text-xs font-medium rounded-md hover:bg-purple-700 transition-colors flex items-center gap-1" | |
| title="刷新所有正常账号的token"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> | |
| </svg> | |
| 全部刷新 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="tableContainer" class="flex-1 overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-border-light dark:divide-border-dark"> | |
| <thead class="bg-gray-50 dark:bg-gray-800"> | |
| <tr> | |
| <th scope="col" class="px-6 py-3 text-center w-12"> | |
| <input type="checkbox" id="selectAll" onclick="toggleSelectAll()" class="rounded border-gray-300 dark:border-gray-600 text-primary focus:ring-primary h-4 w-4 mx-auto"> | |
| </th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-20">ID</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Client ID / Email</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">订阅信息</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">今日用量</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">最后使用</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Token过期</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">积分刷新</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">状态</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th> | |
| </tr> | |
| </thead> | |
| <tbody id="accountList" class="bg-surface-light dark:bg-surface-dark divide-y divide-border-light dark:divide-border-dark"> | |
| <!-- Loaded via JS --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- Pagination --> | |
| <div id="paginationContainer" class="px-6 py-4 border-t border-border-light dark:border-border-dark flex items-center justify-between bg-gray-50/50 dark:bg-gray-800/50"> | |
| <div class="text-xs text-gray-500 dark:text-gray-400"> | |
| 显示 <span id="pageStart" class="font-medium">0</span> 到 <span id="pageEnd" class="font-medium">0</span> 条,共 <span id="totalItems" class="font-medium">0</span> 条 | |
| </div> | |
| <div class="flex gap-2"> | |
| <button id="prevPage" onclick="changePage(-1)" class="px-3 py-1 text-xs font-medium rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed">上一页</button> | |
| <button id="nextPage" onclick="changePage(1)" class="px-3 py-1 text-xs font-medium rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed">下一页</button> | |
| </div> | |
| </div> | |
| <!-- Empty State (Hidden by default) --> | |
| <div id="emptyState" class="hidden flex-1 flex-col items-center justify-center py-12 text-center"> | |
| <div class="bg-gray-100 dark:bg-gray-800 rounded-full p-4 mb-3"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" /> | |
| </svg> | |
| </div> | |
| <h3 class="text-sm font-medium text-gray-900 dark:text-white">暂无账号</h3> | |
| <p class="text-sm text-gray-500 dark:text-gray-400 mt-1">请在左侧添加您的第一个账号。</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Token View (默认隐藏) --> | |
| <div id="tokenView" class="hidden"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-sm border border-border-light dark:border-border-dark overflow-hidden transition-colors duration-300"> | |
| <div class="px-6 py-5 border-b border-border-light dark:border-border-dark bg-gray-50/50 dark:bg-gray-800/50"> | |
| <div class="flex justify-between items-center"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /> | |
| </svg> | |
| 令牌管理 | |
| </h3> | |
| <div class="flex items-center gap-3"> | |
| <button onclick="refreshTokenData()" class="px-3 py-1.5 text-xs font-medium rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline-block mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> | |
| </svg> | |
| 刷新 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Token Stats --> | |
| <div class="px-6 py-4 border-b border-border-light dark:border-border-dark"> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4"> | |
| <div> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">活跃令牌</div> | |
| <div class="text-2xl font-bold text-green-600 dark:text-green-400 mt-1" id="token-stat-active">0</div> | |
| </div> | |
| <div> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">正常账号</div> | |
| <div class="text-2xl font-bold text-blue-600 dark:text-blue-400 mt-1" id="token-stat-normal">0</div> | |
| </div> | |
| <div> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">运行任务</div> | |
| <div class="text-2xl font-bold text-orange-600 dark:text-orange-400 mt-1" id="token-stat-running">0</div> | |
| </div> | |
| <div> | |
| <div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">触发阈值</div> | |
| <div class="text-2xl font-bold text-purple-600 dark:text-purple-400 mt-1"> | |
| <span id="token-stat-threshold">10</span> | |
| <span class="text-xs text-gray-500">个</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Token List --> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-border-light dark:divide-border-dark"> | |
| <thead class="bg-gray-50 dark:bg-gray-800"> | |
| <tr> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">邮箱/描述</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">订阅计划</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">订阅时间</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">令牌状态</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">已生成/阈值</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">成功/失败</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">自动生成</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th> | |
| </tr> | |
| </thead> | |
| <tbody id="tokenList" class="bg-surface-light dark:bg-surface-dark divide-y divide-border-light dark:divide-border-dark"> | |
| <!-- Token records will be loaded here --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- Empty State --> | |
| <div id="tokenEmptyState" class="hidden flex-col items-center justify-center py-12 text-center"> | |
| <div class="bg-gray-100 dark:bg-gray-800 rounded-full p-4 mb-3"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /> | |
| </svg> | |
| </div> | |
| <h3 class="text-sm font-medium text-gray-900 dark:text-white">暂无令牌记录</h3> | |
| <p class="text-sm text-gray-500 dark:text-gray-400 mt-1">使用生成模式添加账号后会自动记录令牌。</p> | |
| </div> | |
| </div> | |
| <!-- Generation Tasks History --> | |
| <div class="mt-6 bg-surface-light dark:bg-surface-dark rounded-2xl shadow-sm border border-border-light dark:border-border-dark overflow-hidden transition-colors duration-300"> | |
| <div class="px-6 py-5 border-b border-border-light dark:border-border-dark bg-gray-50/50 dark:bg-gray-800/50"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| 生成任务历史 | |
| </h3> | |
| </div> | |
| <div class="overflow-x-auto max-h-96"> | |
| <table class="min-w-full divide-y divide-border-light dark:divide-border-dark"> | |
| <thead class="bg-gray-50 dark:bg-gray-800 sticky top-0"> | |
| <tr> | |
| <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">任务ID</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">批次大小</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">成功/失败</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">状态</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">开始时间</th> | |
| <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">完成时间</th> | |
| </tr> | |
| </thead> | |
| <tbody id="taskList" class="bg-surface-light dark:bg-surface-dark divide-y divide-border-light dark:divide-border-dark"> | |
| <!-- Tasks will be loaded here --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> <!-- End mainApp --> | |
| <!-- Token Config Modal --> | |
| <div id="tokenConfigModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-2xl border border-border-light dark:border-border-dark p-6 max-w-md w-full mx-4 transition-colors duration-300"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white">配置令牌</h3> | |
| <button onclick="closeTokenConfigModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <form id="tokenConfigForm" class="space-y-4"> | |
| <input type="hidden" id="configTokenId"> | |
| <div> | |
| <label for="configDescription" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">描述</label> | |
| <input type="text" id="configDescription" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors" | |
| placeholder="令牌描述"> | |
| </div> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <label for="configThreshold" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">触发阈值</label> | |
| <input type="number" id="configThreshold" min="1" max="100" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors" | |
| placeholder="10"> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">账号少于此数量时触发</p> | |
| </div> | |
| <div> | |
| <label for="configBatch" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">批次大小</label> | |
| <input type="number" id="configBatch" min="1" max="200" | |
| class="w-full rounded-xl border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm focus:border-primary focus:ring-primary sm:text-sm py-2.5 px-3 transition-colors" | |
| placeholder="30"> | |
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">每次生成账号数量</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center justify-between py-2 px-3 bg-gray-50 dark:bg-gray-800 rounded-lg"> | |
| <label for="configAutoGenerate" class="text-sm font-medium text-gray-700 dark:text-gray-300">自动生成</label> | |
| <button type="button" id="configAutoGenerate" onclick="toggleConfigSwitch('configAutoGenerate')" | |
| class="relative inline-flex h-6 w-11 items-center rounded-full bg-gray-200 dark:bg-gray-600 transition-colors duration-200"> | |
| <span class="inline-block h-4 w-4 transform rounded-full bg-white shadow-lg transition-transform duration-200 translate-x-1"></span> | |
| </button> | |
| </div> | |
| <div class="flex items-center justify-between py-2 px-3 bg-gray-50 dark:bg-gray-800 rounded-lg"> | |
| <label for="configIsActive" class="text-sm font-medium text-gray-700 dark:text-gray-300">激活状态</label> | |
| <button type="button" id="configIsActive" onclick="toggleConfigSwitch('configIsActive')" | |
| class="relative inline-flex h-6 w-11 items-center rounded-full bg-gray-200 dark:bg-gray-600 transition-colors duration-200"> | |
| <span class="inline-block h-4 w-4 transform rounded-full bg-white shadow-lg transition-transform duration-200 translate-x-1"></span> | |
| </button> | |
| </div> | |
| <div class="flex gap-3 pt-4"> | |
| <button type="button" onclick="closeTokenConfigModal()" | |
| class="flex-1 py-2.5 px-4 border border-gray-300 dark:border-gray-600 rounded-xl text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-all"> | |
| 取消 | |
| </button> | |
| <button type="submit" | |
| class="flex-1 py-2.5 px-4 bg-primary hover:bg-primary-hover text-white rounded-xl font-medium transition-all"> | |
| 保存 | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Account Info Modal (Hidden by default) --> | |
| <div id="accountInfoModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-surface-light dark:bg-surface-dark rounded-2xl shadow-2xl border border-border-light dark:border-border-dark p-6 max-w-md w-full mx-4 transition-colors duration-300"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| 账号生成成功 | |
| </h3> | |
| <button onclick="closeAccountInfoModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <div class="bg-green-50 dark:bg-green-900/20 p-4 rounded-lg border border-green-200 dark:border-green-800"> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <div> | |
| <label class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">邮箱地址</label> | |
| <div id="accountInfoEmail" class="text-sm font-medium text-gray-900 dark:text-white mt-1">-</div> | |
| </div> | |
| <div> | |
| <label class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">订阅计划</label> | |
| <div id="accountInfoPlan" class="text-sm font-medium text-gray-900 dark:text-white mt-1">-</div> | |
| </div> | |
| <div class="col-span-2"> | |
| <label class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Token过期时间</label> | |
| <div id="accountInfoTokenExpiry" class="text-sm font-medium text-gray-900 dark:text-white mt-1">-</div> | |
| </div> | |
| <div class="col-span-2"> | |
| <label class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">订阅开始时间</label> | |
| <div id="accountInfoSubscriptionStart" class="text-sm font-medium text-gray-900 dark:text-white mt-1">-</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-2 text-sm text-green-700 dark:text-green-300"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| 账号已成功添加到号池中,可在账号列表中查看详情 | |
| </div> | |
| <div class="pt-4"> | |
| <button onclick="closeAccountInfoModal()" class="w-full py-2.5 px-4 bg-primary hover:bg-primary-hover text-white rounded-xl font-medium transition-all"> | |
| 确定 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="/static/app.js"></script> | |
| </body> | |
| </html> |