| <!DOCTYPE html>
|
| <html lang="zh-CN">
|
|
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>Document Parser - 控制面板</title>
|
| <link rel="preconnect" href="https://fonts.googleapis.com">
|
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
| <style>
|
| :root {
|
| --bg-primary: #0a0a0f;
|
| --bg-secondary: #12121a;
|
| --bg-card: rgba(255, 255, 255, 0.03);
|
| --border-color: rgba(255, 255, 255, 0.08);
|
| --text-primary: #f5f5f7;
|
| --text-secondary: #8e8e93;
|
| --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| --success-color: #30d158;
|
| --error-color: #ff453a;
|
| --warning-color: #ffd60a;
|
| }
|
|
|
| * {
|
| margin: 0;
|
| padding: 0;
|
| box-sizing: border-box;
|
| }
|
|
|
| body {
|
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
| background: var(--bg-primary);
|
| color: var(--text-primary);
|
| min-height: 100vh;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| padding: 20px;
|
| background-image:
|
| radial-gradient(ellipse 80% 50% at 50% -20%, rgba(102, 126, 234, 0.15), transparent),
|
| radial-gradient(ellipse 60% 40% at 100% 100%, rgba(118, 75, 162, 0.1), transparent);
|
| }
|
|
|
| .container {
|
| width: 100%;
|
| max-width: 600px;
|
| }
|
|
|
| .card {
|
| background: var(--bg-card);
|
| border: 1px solid var(--border-color);
|
| border-radius: 20px;
|
| padding: 40px;
|
| backdrop-filter: blur(20px);
|
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
| margin-bottom: 20px;
|
| }
|
|
|
| .header {
|
| text-align: center;
|
| margin-bottom: 36px;
|
| }
|
|
|
| .logo {
|
| font-size: 48px;
|
| margin-bottom: 16px;
|
| display: block;
|
| }
|
|
|
| h1 {
|
| font-size: 24px;
|
| font-weight: 600;
|
| background: var(--accent-gradient);
|
| -webkit-background-clip: text;
|
| -webkit-text-fill-color: transparent;
|
| background-clip: text;
|
| margin-bottom: 8px;
|
| }
|
|
|
| .subtitle {
|
| color: var(--text-secondary);
|
| font-size: 14px;
|
| }
|
|
|
| .form-group {
|
| margin-bottom: 20px;
|
| }
|
|
|
| label {
|
| display: block;
|
| font-size: 13px;
|
| font-weight: 500;
|
| color: var(--text-secondary);
|
| margin-bottom: 8px;
|
| }
|
|
|
| input,
|
| textarea {
|
| width: 100%;
|
| padding: 14px 16px;
|
| background: var(--bg-secondary);
|
| border: 1px solid var(--border-color);
|
| border-radius: 12px;
|
| color: var(--text-primary);
|
| font-size: 14px;
|
| font-family: inherit;
|
| transition: all 0.2s ease;
|
| }
|
|
|
| textarea {
|
| resize: vertical;
|
| min-height: 80px;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| font-size: 12px;
|
| }
|
|
|
| input:focus,
|
| textarea:focus {
|
| outline: none;
|
| border-color: #667eea;
|
| box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.15);
|
| }
|
|
|
| input::placeholder,
|
| textarea::placeholder {
|
| color: var(--text-secondary);
|
| opacity: 0.6;
|
| }
|
|
|
| .btn {
|
| width: 100%;
|
| padding: 16px;
|
| background: var(--accent-gradient);
|
| border: none;
|
| border-radius: 12px;
|
| color: white;
|
| font-size: 15px;
|
| font-weight: 600;
|
| font-family: inherit;
|
| cursor: pointer;
|
| transition: all 0.2s ease;
|
| margin-top: 8px;
|
| }
|
|
|
| .btn:hover {
|
| transform: translateY(-2px);
|
| box-shadow: 0 8px 24px rgba(102, 126, 234, 0.35);
|
| }
|
|
|
| .btn:active {
|
| transform: translateY(0);
|
| }
|
|
|
| .btn:disabled {
|
| opacity: 0.6;
|
| cursor: not-allowed;
|
| transform: none;
|
| }
|
|
|
| .btn-secondary {
|
| background: var(--bg-secondary);
|
| border: 1px solid var(--border-color);
|
| }
|
|
|
| .btn-secondary:hover {
|
| background: rgba(255, 255, 255, 0.1);
|
| box-shadow: none;
|
| }
|
|
|
| .btn-danger {
|
| background: linear-gradient(135deg, #ff453a 0%, #d63031 100%);
|
| }
|
|
|
| .status-panel {
|
| margin-top: 28px;
|
| padding: 20px;
|
| background: var(--bg-secondary);
|
| border-radius: 14px;
|
| border: 1px solid var(--border-color);
|
| }
|
|
|
| .status-header {
|
| display: flex;
|
| align-items: center;
|
| justify-content: space-between;
|
| margin-bottom: 16px;
|
| }
|
|
|
| .status-label {
|
| font-size: 13px;
|
| font-weight: 500;
|
| color: var(--text-secondary);
|
| }
|
|
|
| .status-badge {
|
| display: flex;
|
| align-items: center;
|
| gap: 6px;
|
| padding: 6px 12px;
|
| border-radius: 20px;
|
| font-size: 12px;
|
| font-weight: 600;
|
| }
|
|
|
| .status-badge.idle {
|
| background: rgba(142, 142, 147, 0.15);
|
| color: var(--text-secondary);
|
| }
|
|
|
| .status-badge.loading {
|
| background: rgba(255, 214, 10, 0.15);
|
| color: var(--warning-color);
|
| }
|
|
|
| .status-badge.success {
|
| background: rgba(48, 209, 88, 0.15);
|
| color: var(--success-color);
|
| }
|
|
|
| .status-badge.error {
|
| background: rgba(255, 69, 58, 0.15);
|
| color: var(--error-color);
|
| }
|
|
|
| .status-dot {
|
| width: 8px;
|
| height: 8px;
|
| border-radius: 50%;
|
| background: currentColor;
|
| }
|
|
|
| .status-badge.loading .status-dot {
|
| animation: pulse 1.5s ease-in-out infinite;
|
| }
|
|
|
| @keyframes pulse {
|
|
|
| 0%,
|
| 100% {
|
| opacity: 1;
|
| }
|
|
|
| 50% {
|
| opacity: 0.4;
|
| }
|
| }
|
|
|
| .status-details {
|
| font-size: 13px;
|
| color: var(--text-secondary);
|
| line-height: 1.6;
|
| }
|
|
|
| .status-details pre {
|
| background: rgba(0, 0, 0, 0.3);
|
| padding: 12px;
|
| border-radius: 8px;
|
| overflow-x: auto;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| font-size: 12px;
|
| margin-top: 12px;
|
| white-space: pre-wrap;
|
| word-break: break-all;
|
| }
|
|
|
| .model-list {
|
| margin-top: 16px;
|
| max-height: 400px;
|
| overflow-y: auto;
|
| }
|
|
|
| .model-item {
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| padding: 10px 14px;
|
| background: rgba(255, 255, 255, 0.03);
|
| border-radius: 10px;
|
| margin-bottom: 8px;
|
| border: 1px solid transparent;
|
| transition: all 0.2s ease;
|
| }
|
|
|
| .model-item:hover {
|
| border-color: var(--border-color);
|
| background: rgba(255, 255, 255, 0.05);
|
| }
|
|
|
| .model-icon {
|
| font-size: 18px;
|
| }
|
|
|
| .model-name {
|
| flex: 1;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| font-size: 13px;
|
| }
|
|
|
| .model-count {
|
| background: var(--accent-gradient);
|
| -webkit-background-clip: text;
|
| -webkit-text-fill-color: transparent;
|
| background-clip: text;
|
| font-weight: 600;
|
| font-size: 14px;
|
| }
|
|
|
| .section-title {
|
| font-size: 16px;
|
| font-weight: 600;
|
| margin-bottom: 20px;
|
| color: var(--text-primary);
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| }
|
|
|
| .section-title .icon {
|
| font-size: 20px;
|
| }
|
|
|
| .tabs {
|
| display: flex;
|
| gap: 8px;
|
| margin-bottom: 24px;
|
| }
|
|
|
| .tab {
|
| flex: 1;
|
| padding: 12px;
|
| background: var(--bg-secondary);
|
| border: 1px solid var(--border-color);
|
| border-radius: 10px;
|
| color: var(--text-secondary);
|
| font-size: 13px;
|
| font-weight: 500;
|
| cursor: pointer;
|
| transition: all 0.2s ease;
|
| text-align: center;
|
| }
|
|
|
| .tab:hover {
|
| background: rgba(255, 255, 255, 0.05);
|
| }
|
|
|
| .tab.active {
|
| background: var(--accent-gradient);
|
| color: white;
|
| border-color: transparent;
|
| }
|
|
|
| .tab-content {
|
| display: none;
|
| }
|
|
|
| .tab-content.active {
|
| display: block;
|
| }
|
|
|
| .footer {
|
| text-align: center;
|
| margin-top: 24px;
|
| font-size: 12px;
|
| color: var(--text-secondary);
|
| }
|
|
|
| .footer a {
|
| color: #667eea;
|
| text-decoration: none;
|
| }
|
|
|
| .footer a:hover {
|
| text-decoration: underline;
|
| }
|
|
|
| .alert {
|
| padding: 14px 16px;
|
| border-radius: 10px;
|
| font-size: 13px;
|
| margin-bottom: 16px;
|
| display: none;
|
| }
|
|
|
| .alert.success {
|
| background: rgba(48, 209, 88, 0.15);
|
| border: 1px solid rgba(48, 209, 88, 0.3);
|
| color: var(--success-color);
|
| display: block;
|
| }
|
|
|
| .alert.error {
|
| background: rgba(255, 69, 58, 0.15);
|
| border: 1px solid rgba(255, 69, 58, 0.3);
|
| color: var(--error-color);
|
| display: block;
|
| }
|
|
|
| .info-box {
|
| background: rgba(102, 126, 234, 0.1);
|
| border: 1px solid rgba(102, 126, 234, 0.2);
|
| border-radius: 10px;
|
| padding: 14px 16px;
|
| font-size: 12px;
|
| color: var(--text-secondary);
|
| margin-bottom: 20px;
|
| }
|
|
|
| .info-box code {
|
| background: rgba(0, 0, 0, 0.3);
|
| padding: 2px 6px;
|
| border-radius: 4px;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| }
|
|
|
| .guide-box {
|
| background: var(--bg-secondary);
|
| border: 1px solid var(--border-color);
|
| border-radius: 12px;
|
| margin-bottom: 20px;
|
| overflow: hidden;
|
| }
|
|
|
| .guide-header {
|
| display: flex;
|
| align-items: center;
|
| justify-content: space-between;
|
| padding: 14px 16px;
|
| cursor: pointer;
|
| font-size: 14px;
|
| font-weight: 500;
|
| transition: background 0.2s ease;
|
| }
|
|
|
| .guide-header:hover {
|
| background: rgba(255, 255, 255, 0.03);
|
| }
|
|
|
| .guide-toggle {
|
| font-size: 12px;
|
| color: var(--text-secondary);
|
| transition: transform 0.2s ease;
|
| }
|
|
|
| .guide-toggle.open {
|
| transform: rotate(180deg);
|
| }
|
|
|
| .guide-content {
|
| display: none;
|
| padding: 0 16px 16px;
|
| border-top: 1px solid var(--border-color);
|
| }
|
|
|
| .guide-content.open {
|
| display: block;
|
| }
|
|
|
| .guide-steps {
|
| padding-top: 16px;
|
| }
|
|
|
| .guide-step {
|
| display: flex;
|
| gap: 14px;
|
| margin-bottom: 16px;
|
| }
|
|
|
| .guide-step:last-child {
|
| margin-bottom: 0;
|
| }
|
|
|
| .step-number {
|
| width: 28px;
|
| height: 28px;
|
| background: var(--accent-gradient);
|
| border-radius: 50%;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| font-size: 13px;
|
| font-weight: 600;
|
| flex-shrink: 0;
|
| }
|
|
|
| .step-content {
|
| flex: 1;
|
| }
|
|
|
| .step-content strong {
|
| display: block;
|
| font-size: 13px;
|
| margin-bottom: 4px;
|
| color: var(--text-primary);
|
| }
|
|
|
| .step-content p {
|
| font-size: 12px;
|
| color: var(--text-secondary);
|
| line-height: 1.5;
|
| }
|
|
|
| .step-content a {
|
| color: #667eea;
|
| text-decoration: none;
|
| }
|
|
|
| .step-content a:hover {
|
| text-decoration: underline;
|
| }
|
|
|
| .step-content code {
|
| background: rgba(0, 0, 0, 0.3);
|
| padding: 2px 6px;
|
| border-radius: 4px;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| font-size: 11px;
|
| }
|
|
|
| .guide-note {
|
| margin-top: 16px;
|
| padding: 12px 14px;
|
| background: rgba(255, 214, 10, 0.08);
|
| border: 1px solid rgba(255, 214, 10, 0.15);
|
| border-radius: 8px;
|
| font-size: 12px;
|
| color: var(--text-secondary);
|
| line-height: 1.6;
|
| }
|
|
|
| .guide-note a {
|
| color: #667eea;
|
| text-decoration: none;
|
| }
|
|
|
| .guide-note a:hover {
|
| text-decoration: underline;
|
| }
|
|
|
| .guide-note code {
|
| background: rgba(0, 0, 0, 0.3);
|
| padding: 2px 6px;
|
| border-radius: 4px;
|
| font-family: 'SF Mono', 'Consolas', monospace;
|
| font-size: 11px;
|
| }
|
| </style>
|
| </head>
|
|
|
| <body>
|
| <div class="container">
|
| <div class="card">
|
| <div class="header">
|
| <span class="logo">📄</span>
|
| <h1>Document Parser</h1>
|
| <p class="subtitle">PDF 分析工具</p>
|
| </div>
|
|
|
| <div class="tabs">
|
| <div class="tab active" onclick="switchTab('status')">📊 服务状态</div>
|
| <div class="tab" onclick="switchTab('cookie')">⚙️ 设置管理</div>
|
| </div>
|
|
|
|
|
| <div id="status-tab" class="tab-content active">
|
| <div class="form-group">
|
| <label for="apiUrl">接口地址</label>
|
| <input type="text" id="apiUrl" value="https://asem12345-mineru.hf.space" placeholder="输入地址">
|
| </div>
|
|
|
| <div class="form-group">
|
| <label for="bearerToken">访问密钥</label>
|
| <input type="password" id="bearerToken" placeholder="输入密钥">
|
| </div>
|
|
|
| <button class="btn" id="checkBtn" onclick="checkStatus()">
|
| 检测服务状态
|
| </button>
|
|
|
| <div class="status-panel">
|
| <div class="status-header">
|
| <span class="status-label">状态</span>
|
| <div class="status-badge idle" id="statusBadge">
|
| <span class="status-dot"></span>
|
| <span id="statusText">等待检测</span>
|
| </div>
|
| </div>
|
| <div class="status-details" id="statusDetails">
|
| 点击上方按钮检测 Monica Proxy 的 Cookie 是否可用。
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="cookie-tab" class="tab-content">
|
|
|
| <div class="guide-box">
|
| <div class="guide-header" onclick="toggleGuide()">
|
| <span>📖 如何获取 Cookie?</span>
|
| <span class="guide-toggle" id="guideToggle">▼</span>
|
| </div>
|
| <div class="guide-content" id="guideContent">
|
| <div class="guide-steps">
|
| <div class="guide-step">
|
| <span class="step-number">1</span>
|
| <div class="step-content">
|
| <strong>打开 Monica 官网并登录</strong>
|
| <p>访问 <a href="https://monica.im" target="_blank">https://monica.im</a> 并登录你的账号</p>
|
| </div>
|
| </div>
|
| <div class="guide-step">
|
| <span class="step-number">2</span>
|
| <div class="step-content">
|
| <strong>打开开发者工具</strong>
|
| <p>按 <code>F12</code> 打开开发者工具</p>
|
| </div>
|
| </div>
|
| <div class="guide-step">
|
| <span class="step-number">3</span>
|
| <div class="step-content">
|
| <strong>找到 Cookie</strong>
|
| <p>切换到 <code>Application</code> → <code>Cookies</code> → <code>monica.im</code></p>
|
| </div>
|
| </div>
|
| <div class="guide-step">
|
| <span class="step-number">4</span>
|
| <div class="step-content">
|
| <strong>复制 session_id</strong>
|
| <p>找到 <code>session_id</code>,复制其值</p>
|
| </div>
|
| </div>
|
| <div class="guide-step">
|
| <span class="step-number">5</span>
|
| <div class="step-content">
|
| <strong>更新 Cookie</strong>
|
| <p>将复制的值粘贴到下方输入框,点击更新按钮</p>
|
| </div>
|
| </div>
|
| </div>
|
| <div class="guide-note">
|
| 💡 <strong>提示:</strong>Cookie 通常有效 7-30 天,过期后按上述流程重新获取。
|
| <br><br>
|
| 🔗 也可以直接在 <a href="https://huggingface.co/spaces/ASEM12345/monica-proxy/settings"
|
| target="_blank">HF Space Settings</a> 中更新 <code>MONICA_COOKIE</code> Secret。
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <div class="info-box">
|
| ⚠️ 更新 Cookie 需要提供 Bearer Token 进行身份验证。Cookie 更新后,代理服务将自动重启以应用新配置。
|
| </div>
|
|
|
| <div id="cookieAlert" class="alert"></div>
|
|
|
| <div class="form-group">
|
| <label for="cookieApiUrl">API 地址</label>
|
| <input type="text" id="cookieApiUrl" value="https://asem12345-monica-proxy.hf.space"
|
| placeholder="输入 API 地址">
|
| </div>
|
|
|
| <div class="form-group">
|
| <label for="cookieBearerToken">Bearer Token(身份验证)</label>
|
| <input type="password" id="cookieBearerToken" placeholder="输入你的 Bearer Token">
|
| </div>
|
|
|
| <div class="form-group">
|
| <label for="newCookie">新的 MONICA_COOKIE</label>
|
| <textarea id="newCookie" placeholder="粘贴新的 Monica Cookie 值..."></textarea>
|
| </div>
|
|
|
| <button class="btn btn-danger" id="updateCookieBtn" onclick="updateCookie()">
|
| 🔄 更新 Cookie
|
| </button>
|
| </div>
|
| </div>
|
|
|
| <div class="footer">
|
| Powered by <a href="https://github.com/ycvk/monica-proxy" target="_blank">ycvk/monica-proxy</a>
|
| </div>
|
| </div>
|
|
|
| <script>
|
| function switchTab(tabName) {
|
|
|
| document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
|
| event.target.classList.add('active');
|
|
|
|
|
| document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
| document.getElementById(tabName + '-tab').classList.add('active');
|
| }
|
|
|
| function toggleGuide() {
|
| const content = document.getElementById('guideContent');
|
| const toggle = document.getElementById('guideToggle');
|
| content.classList.toggle('open');
|
| toggle.classList.toggle('open');
|
| }
|
|
|
| async function checkStatus() {
|
| const apiUrl = document.getElementById('apiUrl').value.trim().replace(/\/$/, '');
|
| const bearerToken = document.getElementById('bearerToken').value.trim();
|
| const btn = document.getElementById('checkBtn');
|
| const statusBadge = document.getElementById('statusBadge');
|
| const statusText = document.getElementById('statusText');
|
| const statusDetails = document.getElementById('statusDetails');
|
|
|
| if (!apiUrl) {
|
| alert('请输入 API 地址');
|
| return;
|
| }
|
|
|
| if (!bearerToken) {
|
| alert('请输入 Bearer Token');
|
| return;
|
| }
|
|
|
|
|
| btn.disabled = true;
|
| btn.textContent = '检测中...';
|
| statusBadge.className = 'status-badge loading';
|
| statusText.textContent = '检测中';
|
| statusDetails.innerHTML = '正在连接到 Monica Proxy...';
|
|
|
| try {
|
| const response = await fetch(`${apiUrl}/v1/models`, {
|
| method: 'GET',
|
| headers: {
|
| 'Authorization': `Bearer ${bearerToken}`,
|
| 'Content-Type': 'application/json'
|
| }
|
| });
|
|
|
| const data = await response.json();
|
|
|
| if (response.ok && data.data && data.data.length > 0) {
|
|
|
| statusBadge.className = 'status-badge success';
|
| statusText.textContent = 'Cookie 可用';
|
|
|
| let html = `
|
| <p>✅ Cookie 工作正常!</p>
|
| <div style="margin-top: 16px; display: flex; align-items: center; justify-content: space-between;">
|
| <span class="section-title" style="margin: 0;"><span class="icon">🧠</span> 可用模型</span>
|
| <span class="model-count">${data.data.length} 个</span>
|
| </div>
|
| <div class="model-list">
|
| `;
|
|
|
| data.data.forEach(model => {
|
| const icon = getModelIcon(model.id);
|
| html += `<div class="model-item"><span class="model-icon">${icon}</span><span class="model-name">${model.id}</span></div>`;
|
| });
|
|
|
| html += '</div>';
|
| statusDetails.innerHTML = html;
|
| } else if (response.status === 401) {
|
|
|
| statusBadge.className = 'status-badge error';
|
| statusText.textContent = 'Token 错误';
|
| statusDetails.innerHTML = `<p>❌ Bearer Token 验证失败</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
|
| } else {
|
|
|
| statusBadge.className = 'status-badge error';
|
| statusText.textContent = 'Cookie 失效';
|
| statusDetails.innerHTML = `
|
| <p>❌ Cookie 可能已失效或存在其他问题</p>
|
| <pre>${JSON.stringify(data, null, 2)}</pre>
|
| <p style="margin-top: 16px;">👉 请切换到 <strong>Cookie 管理</strong> 标签页更新 Cookie</p>
|
| `;
|
| }
|
| } catch (error) {
|
| statusBadge.className = 'status-badge error';
|
| statusText.textContent = '连接失败';
|
| statusDetails.innerHTML = `<p>❌ 无法连接到 API</p><pre>${error.message}</pre><p style="margin-top: 12px; color: var(--text-secondary);">可能原因:网络问题、CORS 限制、或服务不可用</p>`;
|
| } finally {
|
| btn.disabled = false;
|
| btn.textContent = '检测 Cookie 状态';
|
| }
|
| }
|
|
|
| function getModelIcon(modelId) {
|
| const id = modelId.toLowerCase();
|
| if (id.includes('gpt')) return '🟢';
|
| if (id.includes('claude')) return '🟠';
|
| if (id.includes('gemini')) return '🔵';
|
| if (id.includes('grok')) return '⚫';
|
| if (id.includes('llama')) return '🦙';
|
| if (id.includes('qwen')) return '🟣';
|
| if (id.includes('deepseek')) return '🔷';
|
| if (id.includes('sonar')) return '📡';
|
| if (id.includes('o1') || id.includes('o3')) return '🧪';
|
| return '🤖';
|
| }
|
|
|
| async function updateCookie() {
|
| const apiUrl = document.getElementById('cookieApiUrl').value.trim().replace(/\/$/, '');
|
| const bearerToken = document.getElementById('cookieBearerToken').value.trim();
|
| const newCookie = document.getElementById('newCookie').value.trim();
|
| const btn = document.getElementById('updateCookieBtn');
|
| const alertBox = document.getElementById('cookieAlert');
|
|
|
| if (!apiUrl || !bearerToken || !newCookie) {
|
| showAlert('error', '请填写所有字段');
|
| return;
|
| }
|
|
|
| btn.disabled = true;
|
| btn.textContent = '更新中...';
|
| alertBox.className = 'alert';
|
|
|
| try {
|
| const response = await fetch(`${apiUrl}/admin/update-cookie`, {
|
| method: 'POST',
|
| headers: {
|
| 'Authorization': `Bearer ${bearerToken}`,
|
| 'Content-Type': 'application/json'
|
| },
|
| body: JSON.stringify({ cookie: newCookie })
|
| });
|
|
|
| const data = await response.json();
|
|
|
| if (response.ok) {
|
| showAlert('success', '✅ Cookie 更新成功!服务将在几秒后重启。');
|
| document.getElementById('newCookie').value = '';
|
| } else {
|
| showAlert('error', `❌ 更新失败: ${data.error || data.message || '未知错误'}`);
|
| }
|
| } catch (error) {
|
| showAlert('error', `❌ 请求失败: ${error.message}`);
|
| } finally {
|
| btn.disabled = false;
|
| btn.textContent = '🔄 更新 Cookie';
|
| }
|
| }
|
|
|
| function showAlert(type, message) {
|
| const alertBox = document.getElementById('cookieAlert');
|
| alertBox.className = `alert ${type}`;
|
| alertBox.textContent = message;
|
| }
|
|
|
|
|
| document.getElementById('bearerToken').addEventListener('keypress', function (e) {
|
| if (e.key === 'Enter') {
|
| checkStatus();
|
| }
|
| });
|
| </script>
|
| </body>
|
|
|
| </html> |