Spaces:
XCAPI
/
Sleeping

XCAPI commited on
Commit
ae5570a
·
verified ·
1 Parent(s): 39b2db8

Upload 2 files

Browse files
Files changed (2) hide show
  1. admin.html +249 -285
  2. workers +2 -2
admin.html CHANGED
@@ -1,285 +1,249 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>代理端点管理</title>
5
- <style>
6
- body {
7
- font-family: Arial, sans-serif;
8
- max-width: 1200px;
9
- margin: 20px auto;
10
- padding: 0 20px;
11
- }
12
- .endpoint-group {
13
- margin: 20px 0;
14
- padding: 15px;
15
- border: 1px solid #ddd;
16
- border-radius: 8px;
17
- }
18
- .endpoint {
19
- display: flex;
20
- align-items: center;
21
- margin: 10px 0;
22
- padding: 10px;
23
- border: 1px solid #eee;
24
- border-radius: 4px;
25
- background-color: #f9f9f9;
26
- }
27
- .endpoint input[type="text"] {
28
- flex: 1;
29
- margin-right: 10px;
30
- padding: 8px;
31
- border: 1px solid #ddd;
32
- border-radius: 4px;
33
- }
34
- .endpoint input[type="number"] {
35
- width: 80px;
36
- margin: 0 10px;
37
- padding: 8px;
38
- border: 1px solid #ddd;
39
- border-radius: 4px;
40
- }
41
- .endpoint input[type="checkbox"] {
42
- margin: 0 10px;
43
- transform: scale(1.2);
44
- }
45
- button {
46
- padding: 8px 15px;
47
- margin: 5px;
48
- cursor: pointer;
49
- border: none;
50
- border-radius: 4px;
51
- background-color: #4CAF50;
52
- color: white;
53
- }
54
- button:hover {
55
- background-color: #45a049;
56
- }
57
- button.delete {
58
- background-color: #f44336;
59
- }
60
- button.delete:hover {
61
- background-color: #da190b;
62
- }
63
- .status {
64
- position: fixed;
65
- top: 20px;
66
- right: 20px;
67
- padding: 15px;
68
- border-radius: 4px;
69
- display: none;
70
- z-index: 1000;
71
- }
72
- .success {
73
- background-color: #4CAF50;
74
- color: white;
75
- }
76
- .error {
77
- background-color: #f44336;
78
- color: white;
79
- }
80
- h2 {
81
- color: #333;
82
- border-bottom: 2px solid #4CAF50;
83
- padding-bottom: 10px;
84
- }
85
- .controls {
86
- margin: 20px 0;
87
- padding: 10px;
88
- background-color: #f5f5f5;
89
- border-radius: 4px;
90
- text-align: right;
91
- }
92
- .stats-group {
93
- margin: 20px 0;
94
- }
95
- .stat-item {
96
- margin: 10px 0;
97
- padding: 10px;
98
- border: 1px solid #ddd;
99
- border-radius: 4px;
100
- background-color: #f9f9f9;
101
- }
102
- .stat-item p {
103
- margin: 5px 0;
104
- }
105
- .blocked {
106
- background-color: #ffebee;
107
- }
108
- </style>
109
- </head>
110
- <body>
111
- <h1>代理端点管理</h1>
112
-
113
- <div class="endpoint-group">
114
- <h2>Models 端点</h2>
115
- <div id="modelsEndpoints"></div>
116
- <button onclick="addEndpoint('models')">添加 Models 端点</button>
117
- </div>
118
-
119
- <div class="endpoint-group">
120
- <h2>Chat 端点</h2>
121
- <div id="chatEndpoints"></div>
122
- <button onclick="addEndpoint('chat')">添加 Chat 端点</button>
123
- </div>
124
-
125
- <div class="stats-group">
126
- <h2>请求统计</h2>
127
- <div id="statsData"></div>
128
- </div>
129
-
130
- <div class="controls">
131
- <button onclick="saveConfig()">保存所有配置</button>
132
- <button onclick="logout()" style="background-color: #f44336;">退出登录</button>
133
- </div>
134
-
135
- <div id="status" class="status"></div>
136
-
137
- <script>
138
- // 获取存储的密钥
139
- let apiKey = localStorage.getItem('apiKey');
140
-
141
- // 如果没有密钥,提示输入
142
- if (!apiKey) {
143
- apiKey = prompt('请输入访问密钥:');
144
- if (apiKey) {
145
- localStorage.setItem('apiKey', apiKey);
146
- } else {
147
- window.location.href = '/';
148
- }
149
- }
150
-
151
- // 显示状态信息
152
- function showStatus(message, isError = false) {
153
- const status = document.getElementById('status');
154
- status.textContent = message;
155
- status.className = 'status ' + (isError ? 'error' : 'success');
156
- status.style.display = 'block';
157
- setTimeout(() => status.style.display = 'none', 3000);
158
- }
159
-
160
- // 添加端点
161
- function addEndpoint(type, url = '', weight = 1, enabled = true) {
162
- const container = document.getElementById(type + 'Endpoints');
163
- const div = document.createElement('div');
164
- div.className = 'endpoint';
165
- div.innerHTML = `
166
- <input type="text" placeholder="输入端点URL" value="${url}">
167
- <input type="number" placeholder="权重" value="${weight}" min="1">
168
- <label>
169
- <input type="checkbox" ${enabled ? 'checked' : ''}>
170
- 启用
171
- </label>
172
- <button class="delete" onclick="this.parentElement.remove()">删除</button>
173
- `;
174
- container.appendChild(div);
175
- }
176
-
177
- // 获取端点配置
178
- function getEndpointsConfig(type) {
179
- const endpoints = [];
180
- document.querySelectorAll(`#${type}Endpoints .endpoint`).forEach(el => {
181
- endpoints.push({
182
- url: el.querySelector('input[type="text"]').value.trim(),
183
- weight: parseInt(el.querySelector('input[type="number"]').value) || 1,
184
- enabled: el.querySelector('input[type="checkbox"]').checked
185
- });
186
- });
187
- return endpoints;
188
- }
189
-
190
- // 带认证的fetch
191
- async function fetchWithAuth(url, options = {}) {
192
- const headers = {
193
- ...options.headers,
194
- 'Authorization': apiKey
195
- };
196
-
197
- const response = await fetch(url, { ...options, headers });
198
-
199
- if (response.status === 401) {
200
- localStorage.removeItem('apiKey');
201
- window.location.reload();
202
- return null;
203
- }
204
-
205
- return response;
206
- }
207
-
208
- // 保存配置
209
- async function saveConfig() {
210
- const config = {
211
- models: getEndpointsConfig('models'),
212
- chat: getEndpointsConfig('chat')
213
- };
214
-
215
- try {
216
- const response = await fetchWithAuth('/admin/config', {
217
- method: 'POST',
218
- headers: {'Content-Type': 'application/json'},
219
- body: JSON.stringify(config)
220
- });
221
-
222
- if (!response) return;
223
-
224
- if (response.ok) {
225
- showStatus('配置已保存');
226
- loadConfig(); // 重新加载配置以更新统计数据
227
- } else {
228
- showStatus('保存失败: ' + await response.text(), true);
229
- }
230
- } catch (error) {
231
- showStatus('保存失败: ' + error.message, true);
232
- }
233
- }
234
-
235
- // 加载配置和统计数据
236
- async function loadConfig() {
237
- try {
238
- const response = await fetchWithAuth('/admin/config');
239
- if (!response) return;
240
-
241
- const config = await response.json();
242
-
243
- // 清空现有配置
244
- document.getElementById('modelsEndpoints').innerHTML = '';
245
- document.getElementById('chatEndpoints').innerHTML = '';
246
- document.getElementById('statsData').innerHTML = '';
247
-
248
- // 加载Models端点
249
- config.models.forEach(ep => {
250
- addEndpoint('models', ep.url, ep.weight, ep.enabled);
251
- });
252
-
253
- // 加载Chat端点
254
- config.chat.forEach(ep => {
255
- addEndpoint('chat', ep.url, ep.weight, ep.enabled);
256
- });
257
-
258
- // 显示统计数据
259
- const statsHtml = Object.entries(config.stats).map(([fingerprint, stat]) => `
260
- <div class="stat-item ${stat.blocked ? 'blocked' : ''}">
261
- <p><strong>IP:</strong> ${stat.ip}</p>
262
- <p><strong>请求次数:</strong> ${stat.chat_count}</p>
263
- <p><strong>最后访问:</strong> ${new Date(stat.last_access).toLocaleString()}</p>
264
- <p><strong>状态:</strong> ${stat.blocked ? '已拉黑' : '正常'}</p>
265
- </div>
266
- `).join('');
267
-
268
- document.getElementById('statsData').innerHTML = statsHtml || '<p>暂无统计数据</p>';
269
- } catch (error) {
270
- showStatus('加载配置失败: ' + error.message, true);
271
- }
272
- }
273
-
274
- // 退出登录
275
- function logout() {
276
- localStorage.removeItem('apiKey');
277
- window.location.reload();
278
- }
279
-
280
- // 页面加载时获取配置
281
- document.addEventListener('DOMContentLoaded', loadConfig);
282
-
283
- </script>
284
- </body>
285
- </html>
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>代理端点管理</title>
5
+ <style>
6
+ body {
7
+ font-family: Arial, sans-serif;
8
+ max-width: 1000px;
9
+ margin: 20px auto;
10
+ padding: 0 20px;
11
+ }
12
+ .endpoint-group {
13
+ margin: 20px 0;
14
+ padding: 15px;
15
+ border: 1px solid #ddd;
16
+ border-radius: 8px;
17
+ }
18
+ .endpoint {
19
+ display: flex;
20
+ align-items: center;
21
+ margin: 10px 0;
22
+ padding: 10px;
23
+ border: 1px solid #eee;
24
+ border-radius: 4px;
25
+ background-color: #f9f9f9;
26
+ }
27
+ .endpoint input[type="text"] {
28
+ flex: 1;
29
+ margin-right: 10px;
30
+ padding: 8px;
31
+ border: 1px solid #ddd;
32
+ border-radius: 4px;
33
+ }
34
+ .endpoint input[type="number"] {
35
+ width: 80px;
36
+ margin: 0 10px;
37
+ padding: 8px;
38
+ border: 1px solid #ddd;
39
+ border-radius: 4px;
40
+ }
41
+ .endpoint input[type="checkbox"] {
42
+ margin: 0 10px;
43
+ transform: scale(1.2);
44
+ }
45
+ button {
46
+ padding: 8px 15px;
47
+ margin: 5px;
48
+ cursor: pointer;
49
+ border: none;
50
+ border-radius: 4px;
51
+ background-color: #4CAF50;
52
+ color: white;
53
+ }
54
+ button:hover {
55
+ background-color: #45a049;
56
+ }
57
+ button.delete {
58
+ background-color: #f44336;
59
+ }
60
+ button.delete:hover {
61
+ background-color: #da190b;
62
+ }
63
+ .status {
64
+ position: fixed;
65
+ top: 20px;
66
+ right: 20px;
67
+ padding: 15px;
68
+ border-radius: 4px;
69
+ display: none;
70
+ z-index: 1000;
71
+ }
72
+ .success {
73
+ background-color: #4CAF50;
74
+ color: white;
75
+ }
76
+ .error {
77
+ background-color: #f44336;
78
+ color: white;
79
+ }
80
+ h2 {
81
+ color: #333;
82
+ border-bottom: 2px solid #4CAF50;
83
+ padding-bottom: 10px;
84
+ }
85
+ .controls {
86
+ margin: 20px 0;
87
+ padding: 10px;
88
+ background-color: #f5f5f5;
89
+ border-radius: 4px;
90
+ text-align: right;
91
+ }
92
+ </style>
93
+ </head>
94
+ <body>
95
+ <h1>代理端点管理</h1>
96
+
97
+ <div class="endpoint-group">
98
+ <h2>Models 端点</h2>
99
+ <div id="modelsEndpoints"></div>
100
+ <button onclick="addEndpoint('models')">添加 Models 端点</button>
101
+ </div>
102
+
103
+ <div class="endpoint-group">
104
+ <h2>Chat 端点</h2>
105
+ <div id="chatEndpoints"></div>
106
+ <button onclick="addEndpoint('chat')">添加 Chat 端点</button>
107
+ </div>
108
+
109
+ <div class="controls">
110
+ <button onclick="saveConfig()">保存所有配置</button>
111
+ <button onclick="logout()" style="background-color: #f44336;">退出登录</button>
112
+ </div>
113
+
114
+ <div id="status" class="status"></div>
115
+
116
+ <script>
117
+ // 获取存储的密钥
118
+ let apiKey = localStorage.getItem('apiKey');
119
+
120
+ // 如果没有密钥,提示输入
121
+ if (!apiKey) {
122
+ apiKey = prompt('请输入访问密钥:');
123
+ if (apiKey) {
124
+ localStorage.setItem('apiKey', apiKey);
125
+ } else {
126
+ window.location.href = '/';
127
+ }
128
+ }
129
+
130
+ // 显示状态信息
131
+ function showStatus(message, isError = false) {
132
+ const status = document.getElementById('status');
133
+ status.textContent = message;
134
+ status.className = 'status ' + (isError ? 'error' : 'success');
135
+ status.style.display = 'block';
136
+ setTimeout(() => status.style.display = 'none', 3000);
137
+ }
138
+
139
+ // 添加端点
140
+ function addEndpoint(type, url = '', weight = 1, enabled = true) {
141
+ const container = document.getElementById(type + 'Endpoints');
142
+ const div = document.createElement('div');
143
+ div.className = 'endpoint';
144
+ div.innerHTML = `
145
+ <input type="text" placeholder="输入端点URL" value="${url}">
146
+ <input type="number" placeholder="权重" value="${weight}" min="1">
147
+ <label>
148
+ <input type="checkbox" ${enabled ? 'checked' : ''}>
149
+ 启用
150
+ </label>
151
+ <button class="delete" onclick="this.parentElement.remove()">删除</button>
152
+ `;
153
+ container.appendChild(div);
154
+ }
155
+
156
+ // 获取端点配置
157
+ function getEndpointsConfig(type) {
158
+ const endpoints = [];
159
+ document.querySelectorAll(`#${type}Endpoints .endpoint`).forEach(el => {
160
+ endpoints.push({
161
+ url: el.querySelector('input[type="text"]').value.trim(),
162
+ weight: parseInt(el.querySelector('input[type="number"]').value) || 1,
163
+ enabled: el.querySelector('input[type="checkbox"]').checked
164
+ });
165
+ });
166
+ return endpoints;
167
+ }
168
+
169
+ // 带认证的fetch
170
+ async function fetchWithAuth(url, options = {}) {
171
+ const headers = {
172
+ ...options.headers,
173
+ 'Authorization': apiKey
174
+ };
175
+
176
+ const response = await fetch(url, { ...options, headers });
177
+
178
+ if (response.status === 401) {
179
+ localStorage.removeItem('apiKey');
180
+ window.location.reload();
181
+ return null;
182
+ }
183
+
184
+ return response;
185
+ }
186
+
187
+ // 保存配置
188
+ async function saveConfig() {
189
+ const config = {
190
+ models: getEndpointsConfig('models'),
191
+ chat: getEndpointsConfig('chat')
192
+ };
193
+
194
+ try {
195
+ const response = await fetchWithAuth('/admin/config', {
196
+ method: 'POST',
197
+ headers: {'Content-Type': 'application/json'},
198
+ body: JSON.stringify(config)
199
+ });
200
+
201
+ if (!response) return;
202
+
203
+ if (response.ok) {
204
+ showStatus('配置已保存');
205
+ } else {
206
+ showStatus('保存失败: ' + await response.text(), true);
207
+ }
208
+ } catch (error) {
209
+ showStatus('保存失败: ' + error.message, true);
210
+ }
211
+ }
212
+
213
+ // 加载配置
214
+ async function loadConfig() {
215
+ try {
216
+ const response = await fetchWithAuth('/admin/config');
217
+ if (!response) return;
218
+
219
+ const config = await response.json();
220
+
221
+ // 清空现有配置
222
+ document.getElementById('modelsEndpoints').innerHTML = '';
223
+ document.getElementById('chatEndpoints').innerHTML = '';
224
+
225
+ // 加载Models端点
226
+ config.models.forEach(ep => {
227
+ addEndpoint('models', ep.url, ep.weight, ep.enabled);
228
+ });
229
+
230
+ // 加载Chat端点
231
+ config.chat.forEach(ep => {
232
+ addEndpoint('chat', ep.url, ep.weight, ep.enabled);
233
+ });
234
+ } catch (error) {
235
+ showStatus('加载配置失败: ' + error.message, true);
236
+ }
237
+ }
238
+
239
+ // 退出登录
240
+ function logout() {
241
+ localStorage.removeItem('apiKey');
242
+ window.location.reload();
243
+ }
244
+
245
+ // 页面加载时获取配置
246
+ document.addEventListener('DOMContentLoaded', loadConfig);
247
+ </script>
248
+ </body>
249
+ </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
workers CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:6ae27657344f374b5cb70d435063f783f75ca03448036d145f2388aa591083f5
3
- size 13025629
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:25fbd4a183b182a163af232f0cfbd3727785e602d7dbef27b3423ca9293ee90b
3
+ size 8721107