| <!DOCTYPE html> |
| <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"> |
| <title>Token 管理</title> |
| |
| <script> |
| (function() { |
| var isLoggedIn = localStorage.getItem('authToken'); |
| var currentTab = localStorage.getItem('currentTab') || 'tokens'; |
| var classes = ['auth-ready']; |
| if (isLoggedIn) classes.push('logged-in'); |
| if (currentTab === 'settings') classes.push('tab-settings'); |
| document.documentElement.className = classes.join(' '); |
| |
| if ('fonts' in document) { |
| document.fonts.ready.then(function() { |
| document.documentElement.classList.add('fonts-loaded'); |
| }); |
| } else { |
| |
| setTimeout(function() { |
| document.documentElement.classList.add('fonts-loaded'); |
| }, 1000); |
| } |
| })(); |
| </script> |
| <style> |
| |
| html:not(.auth-ready) #loginForm, |
| html:not(.auth-ready) #mainContent { visibility: hidden; } |
| |
| .logged-in #loginForm { display: none !important; } |
| .logged-in #mainContent { display: flex !important; } |
| html:not(.logged-in) #mainContent { display: none !important; } |
| |
| html.tab-settings #tokensPage { display: none !important; } |
| html.tab-settings #settingsPage { display: block !important; } |
| html.tab-settings .tab[data-tab="tokens"] { |
| background: transparent !important; |
| color: var(--text-light, #888) !important; |
| } |
| html.tab-settings .tab[data-tab="settings"] { |
| background: var(--primary, #4f46e5) !important; |
| color: white !important; |
| } |
| </style> |
| |
| <link rel="stylesheet" href="style.css"> |
| |
| <link rel="preconnect" href="https://font.sec.miui.com" crossorigin> |
| <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| |
| <link rel="stylesheet" href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin&display=swap" media="print" onload="this.media='all'"> |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Ubuntu+Mono:wght@400;700&display=swap" media="print" onload="this.media='all'"> |
| <noscript> |
| <link rel="stylesheet" href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin&display=swap"> |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Ubuntu+Mono:wght@400;700&display=swap"> |
| </noscript> |
| </head> |
| <body> |
| <div class="container"> |
| |
| <div id="loginForm" class="login-form"> |
| <h2>Token 管理</h2> |
| <form id="login"> |
| <div class="form-group"> |
| <label>👤 用户名</label> |
| <input type="text" id="username" required autocomplete="username"> |
| </div> |
| <div class="form-group"> |
| <label>🔑 密码</label> |
| <input type="password" id="password" required autocomplete="current-password"> |
| </div> |
| <button type="submit">登录</button> |
| </form> |
| </div> |
|
|
| |
| <div id="mainContent" class="main-content hidden"> |
| <div class="header"> |
| <div class="tabs"> |
| <button class="tab active" data-tab="tokens" onclick="switchTab('tokens')">🎯 Token</button> |
| <button class="tab" data-tab="settings" onclick="switchTab('settings')">⚙️ 设置</button> |
| </div> |
| <div class="header-right"> |
| <button onclick="logout()">🚪 退出</button> |
| </div> |
| </div> |
| <div class="content"> |
| |
| <div id="tokensPage"> |
| |
| <div class="top-bar"> |
| <div class="stats-inline"> |
| <div class="stat-item clickable active" onclick="filterTokens('all')"> |
| <span class="stat-num" id="totalTokens">0</span> |
| <span class="stat-text">总数</span> |
| </div> |
| <div class="stat-item success clickable" onclick="filterTokens('enabled')"> |
| <span class="stat-num" id="enabledTokens">0</span> |
| <span class="stat-text">启用</span> |
| </div> |
| <div class="stat-item danger clickable" onclick="filterTokens('disabled')"> |
| <span class="stat-num" id="disabledTokens">0</span> |
| <span class="stat-text">禁用</span> |
| </div> |
| </div> |
| <div class="action-btns"> |
| <button type="button" onclick="showOAuthModal()" class="btn btn-success btn-sm">🔐 OAuth</button> |
| <button type="button" onclick="showManualModal()" class="btn btn-secondary btn-sm">✏️ 手动</button> |
| <button type="button" onclick="loadTokens()" class="btn btn-warning btn-sm">🔄 刷新</button> |
| <button type="button" onclick="toggleSensitiveInfo()" class="btn btn-sm" id="toggleSensitiveBtn" title="隐藏/显示敏感信息">👁️ 显示</button> |
| </div> |
| </div> |
|
|
| |
| <div id="tokenList" class="token-grid"> |
| <div class="empty-state"> |
| <div class="empty-state-icon">📦</div> |
| <div class="empty-state-text">暂无Token</div> |
| <div class="empty-state-hint">点击上方OAuth按钮添加Token</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="settingsPage" class="hidden"> |
| <form id="configForm" class="config-form"> |
| <div class="config-grid"> |
| |
| <div class="config-section"> |
| <h4>🖥️ 服务器</h4> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>端口</label> |
| <input type="number" name="PORT" placeholder="8045"> |
| </div> |
| <div class="form-group compact"> |
| <label>监听地址</label> |
| <input type="text" name="HOST" placeholder="0.0.0.0"> |
| </div> |
| </div> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>最大请求大小</label> |
| <input type="text" name="MAX_REQUEST_SIZE" placeholder="500mb"> |
| </div> |
| <div class="form-group compact"> |
| <label>API密钥</label> |
| <input type="password" name="API_KEY" placeholder="留空则不验证"> |
| </div> |
| </div> |
| <div class="form-row-inline switch-row"> |
| <div class="form-group compact switch-group"> |
| <label>跳过验证 <span class="help-tip" data-tooltip="跳过ProjectId获取,直接随机生成(仅Pro账号)">?</span></label> |
| <label class="switch"> |
| <input type="checkbox" name="SKIP_PROJECT_ID_FETCH"> |
| <span class="slider"></span> |
| </label> |
| </div> |
| <div class="form-group compact switch-group"> |
| <label>原生Axios <span class="help-tip" data-tooltip="使用原生axios而非TLS指纹请求器">?</span></label> |
| <label class="switch"> |
| <input type="checkbox" name="USE_NATIVE_AXIOS"> |
| <span class="slider"></span> |
| </label> |
| </div> |
| </div> |
| <div class="form-group compact"> |
| <label>图片访问链接</label> |
| <input type="text" name="IMAGE_BASE_URL" placeholder="https://your-domain.zeabur.app"> |
| </div> |
| <div class="form-group compact"> |
| <label>代理地址</label> |
| <input type="text" name="PROXY" placeholder="http://127.0.0.1:7890"> |
| </div> |
| </div> |
|
|
| |
| <div class="config-section"> |
| <h4>🎛️ 模型参数</h4> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>温度</label> |
| <input type="number" step="0.1" name="DEFAULT_TEMPERATURE" placeholder="1"> |
| </div> |
| <div class="form-group compact"> |
| <label>Top P</label> |
| <input type="number" step="0.01" name="DEFAULT_TOP_P" placeholder="1"> |
| </div> |
| </div> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>Top K</label> |
| <input type="number" name="DEFAULT_TOP_K" placeholder="50"> |
| </div> |
| <div class="form-group compact"> |
| <label>最大Token</label> |
| <input type="number" name="DEFAULT_MAX_TOKENS" placeholder="32000"> |
| </div> |
| </div> |
| <div class="form-group compact highlight"> |
| <label>思考预算 <span class="help-tip" data-tooltip="思考模型的思考token预算,影响推理深度">?</span></label> |
| <input type="number" name="DEFAULT_THINKING_BUDGET" placeholder="16000"> |
| </div> |
| <div class="form-row-inline switch-row"> |
| <div class="form-group compact switch-group"> |
| <label>上下文System <span class="help-tip" data-tooltip="合并开头连续的system消息到SystemInstruction">?</span></label> |
| <label class="switch"> |
| <input type="checkbox" name="USE_CONTEXT_SYSTEM_PROMPT"> |
| <span class="slider"></span> |
| </label> |
| </div> |
| </div> |
| <div class="form-group compact"> |
| <label>系统提示词</label> |
| <textarea name="SYSTEM_INSTRUCTION" rows="3" placeholder="可选的系统提示词"></textarea> |
| </div> |
| </div> |
|
|
| |
| <div class="config-section"> |
| <h4>🔄 轮询与性能</h4> |
| <div class="form-row-inline switch-row"> |
| <div class="form-group compact switch-group"> |
| <label>透传签名 <span class="help-tip" data-tooltip="将响应中的thoughtSignature透传到客户端">?</span></label> |
| <label class="switch"> |
| <input type="checkbox" name="PASS_SIGNATURE_TO_CLIENT"> |
| <span class="slider"></span> |
| </label> |
| </div> |
| </div> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>策略模式 <span class="help-tip" data-tooltip="均衡负载:每次请求切换Token 额度耗尽:用完额度才切换 自定义次数:指定次数后切换">?</span></label> |
| <select name="ROTATION_STRATEGY" id="rotationStrategy" onchange="toggleRequestCountInput()"> |
| <option value="round_robin">均衡负载</option> |
| <option value="quota_exhausted">额度耗尽切换</option> |
| <option value="request_count">自定义次数</option> |
| </select> |
| </div> |
| <div class="form-group compact" id="requestCountGroup"> |
| <label>每Token请求次数 <span class="help-tip" data-tooltip="自定义次数模式下,每个Token处理多少次请求后切换">?</span></label> |
| <input type="number" name="ROTATION_REQUEST_COUNT" min="1" placeholder="10"> |
| </div> |
| </div> |
| <div class="rotation-status" id="rotationStatus"> |
| <span class="rotation-label">当前状态:</span> |
| <span id="currentRotationInfo">加载中...</span> |
| </div> |
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>超时(ms)</label> |
| <input type="number" name="TIMEOUT" placeholder="300000"> |
| </div> |
| <div class="form-group compact"> |
| <label>429重试次数</label> |
| <input type="number" name="RETRY_TIMES" placeholder="0"> |
| </div> |
| </div> |
|
|
| <div class="form-row-inline"> |
| <div class="form-group compact"> |
| <label>心跳间隔(ms) <span class="help-tip" data-tooltip="SSE心跳间隔,防止CF超时断连">?</span></label> |
| <input type="number" name="HEARTBEAT_INTERVAL" placeholder="15000"> |
| </div> |
| <div class="form-group compact"> |
| <label>内存阈值(MB) <span class="help-tip" data-tooltip="超过此值触发GC清理">?</span></label> |
| <input type="number" name="MEMORY_THRESHOLD" placeholder="100"> |
| </div> |
| </div> |
| <div class="form-group compact"> |
| <label>🔤 界面字体大小 (px)</label> |
| <div class="font-size-control"> |
| <input type="range" id="fontSizeRange" min="10" max="24" value="18" oninput="changeFontSize(this.value)"> |
| <input type="number" id="fontSizeInput" min="10" max="24" value="18" onchange="changeFontSize(this.value)" style="width: 60px;"> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="config-actions"> |
| <button type="submit" class="btn btn-success">💾 保存配置</button> |
| <button type="button" onclick="loadConfig()" class="btn btn-secondary">🔄 重新加载</button> |
| </div> |
| </form> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <script src="js/utils.js" defer></script> |
| <script src="js/ui.js" defer></script> |
| <script src="js/auth.js" defer></script> |
| <script src="js/quota.js" defer></script> |
| <script src="js/tokens.js" defer></script> |
| <script src="js/config.js" defer></script> |
| <script src="js/main.js" defer></script> |
| </body> |
| </html> |
|
|