cacode commited on
Commit
77c8ac9
·
verified ·
1 Parent(s): f1e0f03

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +62 -0
  2. static/style.css +87 -8
app.py CHANGED
@@ -943,6 +943,68 @@ async def api_admin_overview(request: Request):
943
  }
944
 
945
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946
  @app.post("/api/admin/tasks/{username}/delete")
947
  async def api_admin_delete_task(request: Request, username: str):
948
  _require_admin_session(request)
 
943
  }
944
 
945
 
946
+ @app.get("/api/admin/tasks/{username}")
947
+ async def api_admin_task_detail(request: Request, username: str, log_limit: int = MAX_LOG_LINES):
948
+ _require_admin_session(request)
949
+ username = username.strip()
950
+ user_meta = _get_user_meta_or_404(username)
951
+
952
+ try:
953
+ cfg = _load_user_config(username)
954
+ users_data = _load_user_users_data(username)
955
+ except Exception as exc:
956
+ return JSONResponse(
957
+ status_code=500,
958
+ content={"ok": False, "message": f"加载任务详情失败:{exc}"},
959
+ )
960
+
961
+ scheduler_cfg = cfg.get("scheduler", {})
962
+ runtime = _get_runtime(username)
963
+ target_count = _count_targets(users_data)
964
+ snapshot = runtime.snapshot(account_count=len(users_data), target_count=target_count)
965
+
966
+ accounts = []
967
+ all_targets = []
968
+ for item in users_data:
969
+ targets = _sanitize_targets(item.get("targets", []))
970
+ all_targets.extend(targets)
971
+ accounts.append(
972
+ {
973
+ "username": str(item.get("username", "未知用户")),
974
+ "unique_id": str(item.get("unique_id", "")),
975
+ "target_count": len(targets),
976
+ "targets": targets,
977
+ "cookie_count": len(item.get("cookies", [])) if isinstance(item.get("cookies", []), list) else 0,
978
+ }
979
+ )
980
+
981
+ log_limit = min(max(100, log_limit), 3000)
982
+ return {
983
+ "ok": True,
984
+ "task": {
985
+ "username": username,
986
+ "unique_id": user_meta.get("unique_id", ""),
987
+ "created_at": user_meta.get("created_at", "-"),
988
+ "scheduler_enabled": bool(scheduler_cfg.get("enabled", True)),
989
+ "schedule_time": f"{int(scheduler_cfg.get('hour', 9)):02d}:{int(scheduler_cfg.get('minute', 0)):02d}",
990
+ "schedule_timezone": str(scheduler_cfg.get("timezone", DEFAULT_TIMEZONE)),
991
+ "message_template": str(cfg.get("messageTemplate", "")),
992
+ "targets": all_targets,
993
+ "target_count": len(all_targets),
994
+ "runtime": snapshot,
995
+ "history": runtime.history_rows(),
996
+ "logs": runtime.recent_logs(limit=log_limit),
997
+ "config": {
998
+ "multiTask": bool(cfg.get("multiTask", True)),
999
+ "taskCount": int(cfg.get("taskCount", 1) or 1),
1000
+ "hitokotoTypes": cfg.get("hitokotoTypes", []),
1001
+ "proxyAddress": str(cfg.get("proxyAddress", "")),
1002
+ },
1003
+ "accounts": accounts,
1004
+ },
1005
+ }
1006
+
1007
+
1008
  @app.post("/api/admin/tasks/{username}/delete")
1009
  async def api_admin_delete_task(request: Request, username: str):
1010
  _require_admin_session(request)
static/style.css CHANGED
@@ -406,11 +406,84 @@ pre {
406
  gap: 6px;
407
  }
408
 
409
- .clamp-cell {
410
- max-width: 260px;
411
- white-space: pre-wrap;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
  word-break: break-word;
413
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
 
415
  @media (max-width: 1100px) {
416
  .stats-grid {
@@ -439,9 +512,15 @@ pre {
439
  }
440
  }
441
 
442
- @media (max-width: 520px) {
443
- .stats-grid {
444
- grid-template-columns: 1fr;
445
- }
446
- }
 
 
 
 
 
 
447
 
 
406
  gap: 6px;
407
  }
408
 
409
+ .admin-table th,
410
+ .admin-table td {
411
+ vertical-align: middle;
412
+ }
413
+
414
+ .ellipsis-cell {
415
+ max-width: 240px;
416
+ white-space: nowrap;
417
+ overflow: hidden;
418
+ text-overflow: ellipsis;
419
+ }
420
+
421
+ .detail-grid {
422
+ display: grid;
423
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
424
+ gap: 10px;
425
+ margin-bottom: 12px;
426
+ }
427
+
428
+ .detail-item {
429
+ border: 1px solid #d5e4de;
430
+ border-radius: 10px;
431
+ background: #f8fcfa;
432
+ padding: 10px 12px;
433
+ }
434
+
435
+ .detail-item span {
436
+ display: block;
437
+ color: var(--muted);
438
+ font-size: 12px;
439
+ margin-bottom: 4px;
440
+ }
441
+
442
+ .detail-item strong {
443
+ font-size: 14px;
444
  word-break: break-word;
445
  }
446
+
447
+ .detail-split {
448
+ display: grid;
449
+ grid-template-columns: repeat(2, minmax(0, 1fr));
450
+ gap: 10px;
451
+ margin-bottom: 10px;
452
+ }
453
+
454
+ .detail-card {
455
+ border: 1px solid #d5e4de;
456
+ border-radius: 12px;
457
+ padding: 10px;
458
+ background: #fff;
459
+ margin-bottom: 10px;
460
+ }
461
+
462
+ .detail-card h3 {
463
+ margin: 0 0 8px;
464
+ font-size: 14px;
465
+ color: #20584d;
466
+ }
467
+
468
+ .detail-message {
469
+ margin: 0;
470
+ min-height: 90px;
471
+ max-height: 220px;
472
+ overflow: auto;
473
+ background: #10211c;
474
+ color: #cdf8ec;
475
+ border: 1px solid #21453d;
476
+ }
477
+
478
+ .detail-history th,
479
+ .detail-history td {
480
+ vertical-align: middle;
481
+ }
482
+
483
+ .detail-logbox {
484
+ min-height: 180px;
485
+ max-height: 440px;
486
+ }
487
 
488
  @media (max-width: 1100px) {
489
  .stats-grid {
 
512
  }
513
  }
514
 
515
+ @media (max-width: 520px) {
516
+ .stats-grid {
517
+ grid-template-columns: 1fr;
518
+ }
519
+ }
520
+
521
+ @media (max-width: 860px) {
522
+ .detail-split {
523
+ grid-template-columns: 1fr;
524
+ }
525
+ }
526