malt666 commited on
Commit
172460b
·
verified ·
1 Parent(s): 7831ad4

Upload 6 files

Browse files
Files changed (3) hide show
  1. app.py +32 -11
  2. templates/dashboard.html +12 -57
  3. templates/login.html +141 -29
app.py CHANGED
@@ -18,9 +18,6 @@ app = Flask(__name__, template_folder='templates')
18
  app.secret_key = os.environ.get("SECRET_KEY", "abacus_chat_proxy_secret_key")
19
  app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
20
 
21
- # 获取 Hugging Face Space 主机名 (如果存在)
22
- SPACE_HOST = os.environ.get("SPACE_HOST")
23
- BASE_URL = f"https://{SPACE_HOST}" if SPACE_HOST else None
24
 
25
  API_ENDPOINT_URL = "https://abacus.ai/api/v0/describeDeployment"
26
  MODEL_LIST_URL = "https://abacus.ai/api/v0/listExternalApplications"
@@ -934,13 +931,13 @@ def login():
934
  if password and hashlib.sha256(password.encode()).hexdigest() == PASSWORD:
935
  flask_session['logged_in'] = True
936
  flask_session.permanent = True
937
- # 登录成功后重定向到仪表盘
938
  return redirect(url_for('dashboard'))
939
  else:
940
- # 更新错误提示信息
941
- error = "密码不正确。密码为您在环境变量 'password' 中设置的值,该值也用作 API 调用的验证密钥。"
942
- # 将 BASE_URL 传递给模板
943
- return render_template('login.html', error=error, base_url=BASE_URL)
 
944
 
945
 
946
  @app.route("/logout")
@@ -977,12 +974,36 @@ def dashboard():
977
  model_stats=model_usage_stats,
978
  total_tokens=total_tokens,
979
  compute_points=compute_points,
980
- compute_points_log=compute_points_log,
981
- # 将 BASE_URL 传递给模板
982
- base_url=BASE_URL
983
  )
984
 
985
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
986
  if __name__ == "__main__":
987
  # 启动保活线程
988
  threading.Thread(target=keep_alive, daemon=True).start()
 
18
  app.secret_key = os.environ.get("SECRET_KEY", "abacus_chat_proxy_secret_key")
19
  app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
20
 
 
 
 
21
 
22
  API_ENDPOINT_URL = "https://abacus.ai/api/v0/describeDeployment"
23
  MODEL_LIST_URL = "https://abacus.ai/api/v0/listExternalApplications"
 
931
  if password and hashlib.sha256(password.encode()).hexdigest() == PASSWORD:
932
  flask_session['logged_in'] = True
933
  flask_session.permanent = True
 
934
  return redirect(url_for('dashboard'))
935
  else:
936
+ # 密码错误时提示使用环境变量密码
937
+ error = "密码不正确。请使用设置的环境变量 password password.txt 中的值作为密码和API认证密钥。"
938
+
939
+ # 传递空间URL给模板
940
+ return render_template('login.html', error=error, space_url=SPACE_URL)
941
 
942
 
943
  @app.route("/logout")
 
974
  model_stats=model_usage_stats,
975
  total_tokens=total_tokens,
976
  compute_points=compute_points,
977
+ compute_points_log=compute_points_log
 
 
978
  )
979
 
980
 
981
+ # 获取Hugging Face Space URL
982
+ def get_space_url():
983
+ # 尝试从环境变量获取
984
+ space_url = os.environ.get("SPACE_URL")
985
+ if space_url:
986
+ return space_url
987
+
988
+ # 如果SPACE_URL不存在,尝试从SPACE_ID构建
989
+ space_id = os.environ.get("SPACE_ID")
990
+ if space_id:
991
+ username, space_name = space_id.split("/")
992
+ return f"https://{username}-{space_name}.hf.space"
993
+
994
+ # 如果以上都不存在,尝试从单独的用户名和空间名构建
995
+ username = os.environ.get("SPACE_USERNAME")
996
+ space_name = os.environ.get("SPACE_NAME")
997
+ if username and space_name:
998
+ return f"https://{username}-{space_name}.hf.space"
999
+
1000
+ # 默认返回None
1001
+ return None
1002
+
1003
+ # 获取空间URL
1004
+ SPACE_URL = get_space_url()
1005
+
1006
+
1007
  if __name__ == "__main__":
1008
  # 启动保活线程
1009
  threading.Thread(target=keep_alive, daemon=True).start()
templates/dashboard.html CHANGED
@@ -43,23 +43,11 @@
43
  left: 0;
44
  width: 100%;
45
  height: 100%;
46
- /* 使用多个径向渐变模拟蜘蛛网节点和线条 */
47
- background-color: var(--bg-color); /* 确保有底色 */
48
- background-image:
49
- /* 细密的网格线 */
50
- linear-gradient(rgba(70, 90, 150, 0.08) 1px, transparent 1px),
51
- linear-gradient(90deg, rgba(70, 90, 150, 0.08) 1px, transparent 1px),
52
- /* 模拟节点和放射线 - 多层叠加 */
53
- radial-gradient(circle at 10% 10%, rgba(94, 133, 241, 0.1) 0%, transparent 10%),
54
- radial-gradient(circle at 90% 80%, rgba(111, 66, 193, 0.1) 0%, transparent 10%),
55
- radial-gradient(circle at 50% 50%, rgba(70, 111, 171, 0.05) 0%, transparent 15%),
56
- radial-gradient(circle at 25% 75%, rgba(111, 66, 193, 0.08) 0%, transparent 8%),
57
- radial-gradient(circle at 75% 25%, rgba(94, 133, 241, 0.08) 0%, transparent 8%);
58
- background-size: 50px 50px, 50px 50px, 200px 200px, 300px 300px, 400px 400px, 250px 250px, 250px 250px;
59
- background-position: 0 0, 0 0, 10px 10px, 30px 30px, 50px 50px, 20px 80px, 80px 20px;
60
  z-index: -1;
61
- /* 添加轻微的动画效果 */
62
- animation: subtle-spiderweb-move 60s linear infinite alternate;
63
  }
64
 
65
  @keyframes grid-move {
@@ -71,15 +59,6 @@
71
  }
72
  }
73
 
74
- @keyframes subtle-spiderweb-move {
75
- 0% {
76
- background-position: 0 0, 0 0, 10px 10px, 30px 30px, 50px 50px, 20px 80px, 80px 20px;
77
- }
78
- 100% {
79
- background-position: 50px 50px, 50px 50px, -10px -10px, 10px 10px, 30px 30px, 0px 60px, 60px 0px;
80
- }
81
- }
82
-
83
  /* 顶部导航栏 */
84
  .navbar {
85
  padding: 1rem 2rem;
@@ -374,16 +353,14 @@
374
  border-radius: 4px;
375
  margin-top: 0.25rem;
376
  display: inline-block;
377
- word-break: break-all; /* 确保长链接能换行 */
378
- }
379
-
380
- .endpoint-url a {
381
- color: var(--accent-color);
382
  text-decoration: none;
 
383
  }
384
 
385
- .endpoint-url a:hover {
386
- text-decoration: underline;
 
387
  }
388
 
389
  /* 响应式布局 */
@@ -713,37 +690,15 @@
713
  </div>
714
  <div class="endpoint-item">
715
  <p>获取模型列表:</p>
716
- <code class="endpoint-url">
717
- GET
718
- {% if base_url %}
719
- <a href="{{ base_url }}/v1/models" target="_blank">{{ base_url }}/v1/models</a>
720
- {% else %}
721
- /v1/models
722
- {% endif %}
723
- </code>
724
  </div>
725
  <div class="endpoint-item">
726
  <p>聊天补全:</p>
727
- <code class="endpoint-url">
728
- POST
729
- {% if base_url %}
730
- <a href="{{ base_url }}/v1/chat/completions" target="_blank">{{ base_url }}/v1/chat/completions</a>
731
- {% else %}
732
- /v1/chat/completions
733
- {% endif %}
734
- <br><small>(需要 'Authorization: Bearer YOUR_PASSWORD' 请求头)</small>
735
- </code>
736
  </div>
737
  <div class="endpoint-item">
738
  <p>健康检查:</p>
739
- <code class="endpoint-url">
740
- GET
741
- {% if base_url %}
742
- <a href="{{ base_url }}/health" target="_blank">{{ base_url }}/health</a>
743
- {% else %}
744
- /health
745
- {% endif %}
746
- </code>
747
  </div>
748
  </div>
749
 
 
43
  left: 0;
44
  width: 100%;
45
  height: 100%;
46
+ background-image: linear-gradient(rgba(50, 50, 100, 0.05) 1px, transparent 1px),
47
+ linear-gradient(90deg, rgba(50, 50, 100, 0.05) 1px, transparent 1px);
48
+ background-size: 30px 30px;
 
 
 
 
 
 
 
 
 
 
 
49
  z-index: -1;
50
+ animation: grid-move 20s linear infinite;
 
51
  }
52
 
53
  @keyframes grid-move {
 
59
  }
60
  }
61
 
 
 
 
 
 
 
 
 
 
62
  /* 顶部导航栏 */
63
  .navbar {
64
  padding: 1rem 2rem;
 
353
  border-radius: 4px;
354
  margin-top: 0.25rem;
355
  display: inline-block;
356
+ color: var(--text-color);
 
 
 
 
357
  text-decoration: none;
358
+ transition: all 0.2s;
359
  }
360
 
361
+ .endpoint-url:hover {
362
+ background: rgba(111, 66, 193, 0.3);
363
+ color: var(--text-color);
364
  }
365
 
366
  /* 响应式布局 */
 
690
  </div>
691
  <div class="endpoint-item">
692
  <p>获取模型列表:</p>
693
+ <a href="/v1/models" class="endpoint-url" target="_blank">GET /v1/models</a>
 
 
 
 
 
 
 
694
  </div>
695
  <div class="endpoint-item">
696
  <p>聊天补全:</p>
697
+ <a href="javascript:void(0);" class="endpoint-url">POST /v1/chat/completions</a>
 
 
 
 
 
 
 
 
698
  </div>
699
  <div class="endpoint-item">
700
  <p>健康检查:</p>
701
+ <a href="/health" class="endpoint-url" target="_blank">GET /health</a>
 
 
 
 
 
 
 
702
  </div>
703
  </div>
704
 
templates/login.html CHANGED
@@ -37,6 +37,22 @@
37
  overflow: hidden;
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  /* 动态背景网格 */
41
  .grid-background {
42
  position: absolute;
@@ -96,7 +112,7 @@
96
  }
97
 
98
  .login-card {
99
- width: 380px;
100
  padding: 2.5rem;
101
  border-radius: 16px;
102
  background: var(--card-bg);
@@ -138,6 +154,28 @@
138
  font-size: 0.95rem;
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  .login-form {
142
  display: flex;
143
  flex-direction: column;
@@ -233,15 +271,14 @@
233
  }
234
 
235
  .error-message {
236
- background: rgba(248, 113, 113, 0.1); /* error-color with opacity */
237
  color: var(--error-color);
238
- padding: 1rem;
239
- border-radius: 8px;
240
  margin-bottom: 1.5rem;
241
- border: 1px solid rgba(248, 113, 113, 0.3);
242
- text-align: center;
243
  font-size: 0.9rem;
244
- line-height: 1.5; /* 增加行高以便阅读 */
 
245
  }
246
 
247
  .logo {
@@ -258,23 +295,6 @@
258
  text-shadow: 0 0 10px rgba(111, 66, 193, 0.8), 0 0 20px rgba(111, 66, 193, 0.8);
259
  }
260
  }
261
-
262
- .info-text {
263
- text-align: center;
264
- color: rgba(230, 230, 255, 0.7);
265
- margin-bottom: 1.5rem;
266
- font-size: 0.9rem;
267
- }
268
-
269
- .info-text a {
270
- color: var(--accent-color);
271
- text-decoration: none;
272
- font-weight: 600;
273
- }
274
-
275
- .info-text a:hover {
276
- text-decoration: underline;
277
- }
278
  </style>
279
  </head>
280
  <body>
@@ -282,6 +302,9 @@
282
  <div class="particles">
283
  <!-- 粒子元素会由JS生成 -->
284
  </div>
 
 
 
285
 
286
  <div class="login-card">
287
  <div class="login-header">
@@ -290,10 +313,10 @@
290
  <p>请输入访问密码</p>
291
  </div>
292
 
293
- {% if base_url %}
294
- <p class="info-text">
295
- 请访问 <a href="{{ base_url }}" target="_blank">{{ base_url }}</a> 来登录查看使用情况。
296
- </p>
297
  {% endif %}
298
 
299
  <div class="error-message" id="error-message">
@@ -341,9 +364,98 @@
341
  }
342
  }
343
 
344
- // 页面加载时创建粒子
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  window.addEventListener('load', () => {
346
  createParticles();
 
347
  });
348
  </script>
349
  </body>
 
37
  overflow: hidden;
38
  }
39
 
40
+ /* 科幻蜘蛛网动画 */
41
+ .web-container {
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ width: 100%;
46
+ height: 100%;
47
+ z-index: -2;
48
+ opacity: 0.6;
49
+ }
50
+
51
+ .web {
52
+ width: 100%;
53
+ height: 100%;
54
+ }
55
+
56
  /* 动态背景网格 */
57
  .grid-background {
58
  position: absolute;
 
112
  }
113
 
114
  .login-card {
115
+ width: 420px;
116
  padding: 2.5rem;
117
  border-radius: 16px;
118
  background: var(--card-bg);
 
154
  font-size: 0.95rem;
155
  }
156
 
157
+ .space-info {
158
+ text-align: center;
159
+ background: rgba(50, 50, 150, 0.2);
160
+ padding: 0.75rem;
161
+ border-radius: 8px;
162
+ margin-bottom: 1.5rem;
163
+ font-size: 0.9rem;
164
+ border: 1px solid rgba(111, 66, 193, 0.3);
165
+ }
166
+
167
+ .space-info a {
168
+ color: var(--primary-color);
169
+ text-decoration: none;
170
+ font-weight: bold;
171
+ transition: all 0.2s;
172
+ }
173
+
174
+ .space-info a:hover {
175
+ text-decoration: underline;
176
+ color: var(--secondary-color);
177
+ }
178
+
179
  .login-form {
180
  display: flex;
181
  flex-direction: column;
 
271
  }
272
 
273
  .error-message {
274
+ background-color: rgba(248, 114, 114, 0.2);
275
  color: var(--error-color);
276
+ padding: 0.75rem;
277
+ border-radius: 6px;
278
  margin-bottom: 1.5rem;
 
 
279
  font-size: 0.9rem;
280
+ border-left: 3px solid var(--error-color);
281
+ display: {{ 'block' if error else 'none' }};
282
  }
283
 
284
  .logo {
 
295
  text-shadow: 0 0 10px rgba(111, 66, 193, 0.8), 0 0 20px rgba(111, 66, 193, 0.8);
296
  }
297
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  </style>
299
  </head>
300
  <body>
 
302
  <div class="particles">
303
  <!-- 粒子元素会由JS生成 -->
304
  </div>
305
+ <div class="web-container">
306
+ <canvas class="web" id="webCanvas"></canvas>
307
+ </div>
308
 
309
  <div class="login-card">
310
  <div class="login-header">
 
313
  <p>请输入访问密码</p>
314
  </div>
315
 
316
+ {% if space_url %}
317
+ <div class="space-info">
318
+ 请访问 <a href="{{ space_url }}" target="_blank">{{ space_url }}</a> 登录查看使用情况
319
+ </div>
320
  {% endif %}
321
 
322
  <div class="error-message" id="error-message">
 
364
  }
365
  }
366
 
367
+ // 科幻蜘蛛网效果
368
+ function initWebCanvas() {
369
+ const canvas = document.getElementById('webCanvas');
370
+ const ctx = canvas.getContext('2d');
371
+ let width = window.innerWidth;
372
+ let height = window.innerHeight;
373
+
374
+ // 设置canvas尺寸
375
+ canvas.width = width;
376
+ canvas.height = height;
377
+
378
+ // 节点类
379
+ class Node {
380
+ constructor(x, y) {
381
+ this.x = x;
382
+ this.y = y;
383
+ this.vx = (Math.random() - 0.5) * 0.5;
384
+ this.vy = (Math.random() - 0.5) * 0.5;
385
+ this.radius = Math.random() * 2 + 1;
386
+ }
387
+
388
+ update() {
389
+ if (this.x < 0 || this.x > width) this.vx = -this.vx;
390
+ if (this.y < 0 || this.y > height) this.vy = -this.vy;
391
+
392
+ this.x += this.vx;
393
+ this.y += this.vy;
394
+ }
395
+
396
+ draw() {
397
+ ctx.beginPath();
398
+ ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
399
+ ctx.fillStyle = 'rgba(111, 66, 193, 0.4)';
400
+ ctx.fill();
401
+ }
402
+ }
403
+
404
+ // 创建节点
405
+ const nodeCount = Math.floor(width * height / 15000);
406
+ const nodes = [];
407
+
408
+ for (let i = 0; i < nodeCount; i++) {
409
+ nodes.push(new Node(Math.random() * width, Math.random() * height));
410
+ }
411
+
412
+ // 绘制线条
413
+ function drawWeb() {
414
+ ctx.clearRect(0, 0, width, height);
415
+
416
+ // 更新节点
417
+ nodes.forEach(node => {
418
+ node.update();
419
+ node.draw();
420
+ });
421
+
422
+ // 绘制连线
423
+ for (let i = 0; i < nodes.length; i++) {
424
+ for (let j = i + 1; j < nodes.length; j++) {
425
+ const dx = nodes[i].x - nodes[j].x;
426
+ const dy = nodes[i].y - nodes[j].y;
427
+ const distance = Math.sqrt(dx * dx + dy * dy);
428
+
429
+ if (distance < 150) {
430
+ ctx.beginPath();
431
+ ctx.moveTo(nodes[i].x, nodes[i].y);
432
+ ctx.lineTo(nodes[j].x, nodes[j].y);
433
+ ctx.strokeStyle = `rgba(111, 66, 193, ${0.2 * (1 - distance / 150)})`;
434
+ ctx.lineWidth = 0.5;
435
+ ctx.stroke();
436
+ }
437
+ }
438
+ }
439
+
440
+ requestAnimationFrame(drawWeb);
441
+ }
442
+
443
+ // 监听窗口大小变化
444
+ window.addEventListener('resize', () => {
445
+ width = window.innerWidth;
446
+ height = window.innerHeight;
447
+ canvas.width = width;
448
+ canvas.height = height;
449
+ });
450
+
451
+ // 开始动画
452
+ drawWeb();
453
+ }
454
+
455
+ // 页面加载时初始化效果
456
  window.addEventListener('load', () => {
457
  createParticles();
458
+ initWebCanvas();
459
  });
460
  </script>
461
  </body>