| <!DOCTYPE html>
|
| <html>
|
| <head>
|
| <title>代理管理界面</title>
|
| <style>
|
| body {
|
| font-family: Arial, sans-serif;
|
| max-width: 1200px;
|
| margin: 0 auto;
|
| padding: 20px;
|
| }
|
| .container {
|
| display: flex;
|
| gap: 20px;
|
| }
|
| .section {
|
| flex: 1;
|
| background: #f5f5f5;
|
| padding: 20px;
|
| border-radius: 8px;
|
| }
|
| table {
|
| width: 100%;
|
| border-collapse: collapse;
|
| margin: 10px 0;
|
| }
|
| th, td {
|
| padding: 8px;
|
| border: 1px solid #ddd;
|
| text-align: left;
|
| }
|
| th { background: #eee; }
|
| .enabled { color: green; }
|
| .disabled { color: red; }
|
| .form-group {
|
| margin: 10px 0;
|
| }
|
| button {
|
| padding: 5px 10px;
|
| margin: 2px;
|
| cursor: pointer;
|
| }
|
| .status-bar {
|
| background: #e0e0e0;
|
| padding: 10px;
|
| margin: 10px 0;
|
| border-radius: 4px;
|
| }
|
| </style>
|
| </head>
|
| <body>
|
| <h1>代理管理界面</h1>
|
|
|
| <div class="status-bar">
|
| <strong>系统状态:</strong>
|
| Models代理数: <span id="modelsCount">0</span> |
|
| Chat代理数: <span id="chatCount">0</span>
|
| </div>
|
|
|
| <div class="container">
|
| <div class="section">
|
| <h2>Models代理列表</h2>
|
| <table id="modelsTable">
|
| <tr>
|
| <th>URL</th>
|
| <th>权重</th>
|
| <th>状态</th>
|
| <th>操作</th>
|
| </tr>
|
| </table>
|
|
|
| <h3>添加Models代理</h3>
|
| <div class="form-group">
|
| <input type="text" id="modelsUrl" placeholder="URL">
|
| <input type="number" id="modelsWeight" placeholder="权重" value="1">
|
| <button onclick="addTarget('models')">添加</button>
|
| </div>
|
| </div>
|
|
|
| <div class="section">
|
| <h2>Chat代理列表</h2>
|
| <table id="chatTable">
|
| <tr>
|
| <th>URL</th>
|
| <th>权重</th>
|
| <th>状态</th>
|
| <th>操作</th>
|
| </tr>
|
| </table>
|
|
|
| <h3>添加Chat代理</h3>
|
| <div class="form-group">
|
| <input type="text" id="chatUrl" placeholder="URL">
|
| <input type="number" id="chatWeight" placeholder="权重" value="1">
|
| <button onclick="addTarget('chat')">添加</button>
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <script>
|
| const password = new URLSearchParams(window.location.search).get('password');
|
|
|
| function updateTables() {
|
| fetch('/admin/api/targets?password=' + password)
|
| .then(response => response.json())
|
| .then(data => {
|
| document.getElementById('modelsCount').textContent = data.models.length;
|
| document.getElementById('chatCount').textContent = data.chat.length;
|
|
|
| updateTable('models', data.models);
|
| updateTable('chat', data.chat);
|
| });
|
| }
|
|
|
| function updateTable(type, targets) {
|
| const table = document.getElementById(type + 'Table');
|
|
|
| while (table.rows.length > 1) {
|
| table.deleteRow(1);
|
| }
|
|
|
| targets.forEach((target, index) => {
|
| const row = table.insertRow();
|
| row.innerHTML = `
|
| <td>${target.url}</td>
|
| <td>${target.weight}</td>
|
| <td class="${target.enabled ? 'enabled' : 'disabled'}">
|
| ${target.enabled ? '启用' : '禁用'}
|
| </td>
|
| <td>
|
| <button onclick="toggleTarget('${type}', '${target.url}')">
|
| ${target.enabled ? '禁用' : '启用'}
|
| </button>
|
| <button onclick="deleteTarget('${type}', '${target.url}')">删除</button>
|
| </td>
|
| `;
|
| });
|
| }
|
|
|
| function addTarget(type) {
|
| const url = document.getElementById(type + 'Url').value;
|
| const weight = document.getElementById(type + 'Weight').value;
|
|
|
| fetch('/admin/api/target', {
|
| method: 'POST',
|
| headers: {
|
| 'Content-Type': 'application/json',
|
| },
|
| body: JSON.stringify({
|
| type: type,
|
| url: url,
|
| weight: parseInt(weight),
|
| password: password
|
| })
|
| }).then(() => {
|
| document.getElementById(type + 'Url').value = '';
|
| document.getElementById(type + 'Weight').value = '1';
|
| updateTables();
|
| });
|
| }
|
|
|
| function toggleTarget(type, url) {
|
| fetch('/admin/api/target/toggle', {
|
| method: 'POST',
|
| headers: {
|
| 'Content-Type': 'application/json',
|
| },
|
| body: JSON.stringify({
|
| type: type,
|
| url: url,
|
| password: password
|
| })
|
| }).then(() => updateTables());
|
| }
|
|
|
| function deleteTarget(type, url) {
|
| if (!confirm('确定要删除这个代理地址吗?')) return;
|
|
|
| fetch('/admin/api/target', {
|
| method: 'DELETE',
|
| headers: {
|
| 'Content-Type': 'application/json',
|
| },
|
| body: JSON.stringify({
|
| type: type,
|
| url: url,
|
| password: password
|
| })
|
| }).then(() => updateTables());
|
| }
|
|
|
|
|
| updateTables();
|
|
|
| setInterval(updateTables, 5000);
|
| </script>
|
| </body>
|
| </html>
|
|
|